YetiForceCompany/YetiForceCRM

View on GitHub
app/Cli.php

Summary

Maintainability
C
7 hrs
Test Coverage
F
24%
<?php
/**
 * CLI file.
 *
 * @package App
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 */

namespace App;

/**
 * CLI class.
 */
class Cli
{
    /** @var \League\CLImate\CLImate CLImate instance. */
    public $climate;

    /** @var bool Php support exec */
    public $exec = true;

    /**
     * Construct.
     */
    public function __construct()
    {
        $this->exec = \function_exists('exec');
        $this->climate = new \League\CLImate\CLImate();
        if (!$this->exec) {
            $this->climate->setUtil(new \League\CLImate\Util\UtilFactory(new class() extends \League\CLImate\Util\System\System {
                public function width()
                {
                    return 120;
                }

                public function height()
                {
                    return 40;
                }

                protected function systemHasAnsiSupport()
                {
                    return true;
                }

                public function exec($command, $full = false)
                {
                    return '';
                }
            }));
        }
        $this->climate->clear();
        if (\function_exists('getmyuid') && getmyuid() !== fileowner(__FILE__)) {
            $this->climate->to('error')->lightRed('Error:  YetiForce CLI works only on the OS user who owns the CRM files');
            return;
        }
        if (\PHP_SAPI !== 'cli') {
            $this->climate->to('error')->lightRed('Error: YetiForce CLI only works from the operating system console (CLI)');
            return;
        }
        $this->climate->lightGreen()->border('─', 200);
        $this->climate->tab(2)->lightGreen('Y e t i F o r c e     C L I');
        $this->climate->lightGreen()->border('─', 200);
        $this->climate->white('Version: ' . Version::get() . ' | CRM URL: ' . \Config\Main::$site_URL);
        $this->climate->lightGreen()->border('─', 200);
        \App\User::setCurrentUserId(\Users::getActiveAdminId());
        \App\Language::setTemporaryLanguage('en-US');

        $this->climate->arguments->add([
            'module' => [
                'prefix' => 'm',
                'description' => 'Module name',
            ],
            'action' => [
                'prefix' => 'a',
                'description' => 'Module action name',
            ],
            'help' => [
                'prefix' => 'h',
                'description' => 'Help',
            ],
        ]);
        $this->climate->arguments->parse();
        if ($this->climate->arguments->defined('help')) {
            $this->showHelp();
            $this->climate->usage();
        } elseif ($this->climate->arguments->defined('module') && !$this->climate->arguments->defined('action') && !empty($this->climate->arguments->get('module'))) {
            $this->actionsList($this->climate->arguments->get('module'));
        } elseif ($this->climate->arguments->defined('module') && $this->climate->arguments->defined('action')) {
            $className = "\\App\\Cli\\{$this->climate->arguments->get('module')}";
            $instance = new $className($this);
            if (!method_exists($instance, $this->climate->arguments->get('action'))) {
                $this->climate->to('error')->lightRed("Error: Action '{$this->climate->arguments->get('action')}' does not exist in '{$this->climate->arguments->get('module')}'");
                return;
            }
            $this->climate->backgroundBlue()->out($instance->methods[$this->climate->arguments->get('action')]);
            $this->climate->border('─', 200);
            \call_user_func([$instance, $this->climate->arguments->get('action')]);
        } else {
            $this->modulesList();
        }
    }

    /**
     * Show modules list.
     *
     * @return void
     */
    public function modulesList(): void
    {
        if (!$this->exec) {
            $this->showHelp();
            $this->climate->usage();
            return;
        }
        $modules = $this->getModulesList();
        $modules['Exit'] = 'Exit';
        $input = $this->climate->radio('Module:', $modules);
        $module = $input->prompt();
        if ('Exit' === $module || empty($module)) {
            return;
        }
        $this->climate->clear();
        $this->actionsList($module);
    }

    /**
     * Get modules list.
     *
     * @return string[]
     */
    private function getModulesList(): array
    {
        $modules = [];
        foreach (new \DirectoryIterator(ROOT_DIRECTORY . '/app/Cli') as $fileInfo) {
            if ($fileInfo->isFile() && 'Base' !== $fileInfo->getBasename('.php')) {
                $module = $fileInfo->getBasename('.php');
                $className = "\\App\\Cli\\{$module}";
                $instance = new $className($this);
                $modules[$module] = $instance->moduleName;
            }
        }
        return $modules;
    }

    /**
     * Show actions list.
     *
     * @param string $module
     *
     * @return void
     */
    public function actionsList(string $module): void
    {
        $className = "\\App\\Cli\\{$module}";
        if (!class_exists($className)) {
            $this->climate->to('error')->lightRed("Error: Module '$module' does not exist");
            return;
        }
        if (!$this->exec) {
            $this->showHelp();
            $this->climate->usage();
            return;
        }
        $instance = new $className($this);
        $input = $this->climate->radio('Action:', array_merge($instance->methods, ['Exit' => 'Exit']));
        $action = $input->prompt();
        $this->climate->clear();
        if ('Exit' === $action) {
            $this->modulesList();
        } else {
            \call_user_func([$instance, $action]);
        }
    }

    /**
     * Show help.
     *
     * @return void
     */
    private function showHelp(): void
    {
        if ($this->climate->arguments->defined('module')) {
            $module = $this->climate->arguments->get('module');
            $className = "\\App\\Cli\\{$module}";
            if (!class_exists($className)) {
                $this->climate->to('error')->lightRed("Error: Module '{$this->climate->arguments->get('module')}' does not exist");
                return;
            }
            $instance = new $className($this);
            if ($this->climate->arguments->defined('action') && !empty($this->climate->arguments->get('action'))) {
                if (!method_exists($instance, $this->climate->arguments->get('action'))) {
                    $this->climate->to('error')->lightRed("Error: Action '{$this->climate->arguments->get('action')}' does not exist in '{$this->climate->arguments->get('module')}'");
                    return;
                }
                $instance->helpMode = true;
                \call_user_func([$instance, $this->climate->arguments->get('action')]);
            } else {
                $this->climate->white('Action list for module ' . $this->climate->arguments->get('module'));
                $this->climate->columns(array_merge([' > Action name <' => ' > Description <'], $instance->methods));
                $this->climate->lightGreen()->border('─', 200);
                foreach (array_keys($instance->methods) as $method) {
                    $this->climate->white("php cli.php -m $module -a $method");
                }
                $this->climate->lightGreen()->border('─', 200);
            }
        } else {
            $modules = $this->getModulesList();
            $modules = array_keys($modules);
            $this->climate->white('Modules list:')->columns($modules);
            $this->climate->lightGreen()->border('─', 200);
            foreach ($modules as $module) {
                $this->climate->white("php cli.php -m $module");
            }
            $this->climate->lightGreen()->border('─', 200);
        }
    }
}