Creation/Component.php

Summary

Maintainability
A
3 hrs
Test Coverage
B
82%
<?php


namespace Creation;


use Cli\Cli;
use Helper\FileHelper;
use Helper\TemplateHelper;
use Neoan3\Apps\Ops;

class Component
{
    private Cli $cli;
    private ?string $type = null;
    private ?string $view = null;
    private string $folder;
    private ?string $frame = null;
    private array $componentTypes = ['route', 'api', 'custom'];
    private TemplateHelper $template;
    private FileHelper $fileHelper;

    function __construct(Cli $cli)
    {
        $this->cli = $cli;
        $this->fileHelper = new FileHelper($cli);
        $this->template = new TemplateHelper($cli);
    }

    function init()
    {
        $this->parseFlags();
        if (!isset($this->cli->arguments[2])) {
            $this->cli->printLn('Malformed command. Expected format:', 'red');
            $this->cli->printLn('neoan3 new component <componentName>');
        } else {
            if($this->cli->versionHelper->appMainVersion < 3){
                $folderName = Ops::toCamelCase($this->cli->arguments[2]);
            } else {
                $folderName = Ops::toPascalCase($this->cli->arguments[2]);
            }
            $this->folder = $this->cli->workPath . '/component/' . $folderName;
            if($this->controllerExists()){
                return;
            }

            if ($this->type && in_array($this->type, $this->componentTypes)) {
                $this->generateFiles();
            } else {
                $this->cli->printLn('What type of component?', 'green');
                $this->cli->printLn('Route component  [0] (default)', 'magenta');
                $this->cli->printLn('API component    [1]', 'magenta');
                $this->cli->printLn('Custom component [2]', 'magenta');
                $this->askForType();
            }
        }
    }

    function askForType()
    {
        $this->cli->waitForSingleInput(function ($userInput) {
            if (isset($this->componentTypes[$userInput])) {
                $this->type = $this->componentTypes[$userInput];
            } else {
                $this->type = $this->componentTypes[0];
            }
            $this->generateFiles();
        });
    }

    function askForView()
    {
        $this->cli->printLn("Generate a view? [Y/n]", 'green');
        $this->cli->waitForSingleInput(function ($input) {
            $this->view = $input !== 'n';
        });
    }

    function generateFiles()
    {
        $this->fileHelper->createDirectory($this->folder);
        switch ($this->type) {
            case 'route':
                if ($this->view === null) {
                    $this->askForView();
                }
                if ($this->view) {
                    $this->writeView();
                }
                $this->writeCtrl();
                break;
            case 'api':
                $this->writeApi();
                break;
            case 'custom':
                $this->writeCustom();
                break;
        }

    }

    function askForFrame()
    {
        $this->cli->printLn('Which frame do you want to use?', 'green');

        $path = $this->cli->workPath . '/frame';
        $frames = [];
        $frameFolders = glob($path . "/*", GLOB_ONLYDIR);
        foreach ($frameFolders as $i => $frame) {
            $frames[$i] = substr($frame, strlen($path) + 1);
            $this->cli->printLn($frames[$i] . "  [$i]" . ($i < 1 ? ' (default)' : ''), 'magenta');
        }
        $this->cli->waitForSingleInput(function ($input) use ($frames) {
            if ($input === '') {
                $input = 0;
            }
            $this->frame = $frames[(int)$input];
        });
    }
    function writeCustom()
    {
        $template = $this->template->readTemplate('ce.js');
        if(!$template){
            $template .= '(function(){ console.log("{{name}}: no custom element template found") })();';
        }
        $template = $this->template->substituteVariables($template);
        file_put_contents($this->folder . '/' . Ops::toCamelCase($this->cli->arguments[2]) . '.ce.js', $template);
        $phpTemplate = $this->template->readTemplate('ce.php');
        if($phpTemplate){
            $phpTemplate = $this->template->substituteVariables($phpTemplate);
            file_put_contents($this->folder . '/' . Ops::toPascalCase($this->cli->arguments[2]) . '.ce.php', $phpTemplate);
        }
        $viewTemplate = $this->template->readTemplate('ce.html');
        if($viewTemplate){
            $viewTemplate = $this->template->substituteVariables($phpTemplate);
            file_put_contents($this->folder . '/' . Ops::toCamelCase($this->cli->arguments[2]) . '.ce.html', $viewTemplate);
        }
    }
    function writeApi()
    {
        if(!$this->frame){
            $this->askForFrame();
        }

        $template = $this->template->readTemplate('api.php');
        if (!$template) {
            $template = $this->template->readPartial('api');
        }
        $template = $this->template->substituteVariables($template, [
            'frame' => $this->frame,
            'frame.pascal' => Ops::toPascalCase($this->frame),
        ]);
        $this->template->writeController($template);
    }

    function writeCtrl()
    {
        $template = $this->template->readTemplate('route.php');
        if (!$template) {
            if(!$this->frame){
                $this->cli->printLn("Use a frame? [Y/n]", 'green');
                $this->cli->waitForSingleInput(function ($input) {
                    if ($input !== 'n' && $input !== 'no') {
                        $this->askForFrame();
                    }
                });
            }

            $routePartial = $this->template->readPartial('route');
            $extends = 'Neoan3\Core\Unicore';
            $extended = 'Unicore';
            if (!$this->frame) {
                $this->frame = '';
            } else {
                $this->frame = '\'' . Ops::toPascalCase($this->frame) . '\'';
            }
            $template = $this->template->substituteVariables($routePartial, [
                'extends' => $extends,
                'extended' => $extended,
                'hook' => $this->view ? '->hook(\'main\', \'' . Ops::toCamelCase($this->cli->arguments[2]) . '\')' : ''
            ]);
        }
        $template = $this->template->substituteVariables($template, ['frame' => $this->frame]);
        $this->template->writeController($template);
    }

    function writeView()
    {
        $template = $this->template->readTemplate('view.html');
        if (!$template) {
            $template = $this->template->substituteVariables($this->template->readPartial('view'));
        }
        $template = $this->template->substituteVariables($template);
        $this->template->writeView($template);
    }


    function parseFlags()
    {
        $this->type = $this->cli->flags['t'] ?? null;
        $this->frame = isset($this->cli->flags['f']) ? Ops::toPascalCase($this->cli->flags['f']) : null;
        $this->view = isset($this->cli->flags['v']) ? $this->cli->flags['v'] !== 'no' : null;
    }
    function controllerExists()
    {

        if(!empty(glob($this->folder . '/*.php'))){
            $this->cli->printLn('Component already exists', 'red');
            return true;
        }
        return false;
    }
}