Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/cakephp/src/Shell/Task/CommandTask.php
<?php
/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 * @link          https://cakephp.org CakePHP(tm) Project
 * @since         2.5.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Cake\Shell\Task;

use
Cake\Console\Shell;
use
Cake\Core\App;
use
Cake\Core\Plugin;
use
Cake\Filesystem\Folder;
use
Cake\Utility\Hash;
use
Cake\Utility\Inflector;
use
ReflectionClass;
use
ReflectionMethod;

/**
 * Base class for Shell Command reflection.
 */
class CommandTask extends Shell
{
   
/**
     * Gets the shell command listing.
     *
     * @return array
     */
   
public function getShellList()
    {
       
$skipFiles = ['app'];
       
$hiddenCommands = ['command_list', 'completion'];
       
$plugins = Plugin::loaded();
       
$shellList = array_fill_keys($plugins, null) + ['CORE' => null, 'app' => null];

       
$appPath = App::path('Shell');
       
$shellList = $this->_findShells($shellList, $appPath[0], 'app', $skipFiles);

       
$appPath = App::path('Command');
       
$shellList = $this->_findShells($shellList, $appPath[0], 'app', $skipFiles);

       
$skipCore = array_merge($skipFiles, $hiddenCommands, $shellList['app']);
       
$corePath = dirname(__DIR__);
       
$shellList = $this->_findShells($shellList, $corePath, 'CORE', $skipCore);

       
$corePath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'Command';
       
$shellList = $this->_findShells($shellList, $corePath, 'CORE', $skipCore);

        foreach (
$plugins as $plugin) {
           
$pluginPath = Plugin::classPath($plugin) . 'Shell';
           
$shellList = $this->_findShells($shellList, $pluginPath, $plugin, []);
        }

        return
array_filter($shellList);
    }

   
/**
     * Find shells in $path and add them to $shellList
     *
     * @param array $shellList The shell listing array.
     * @param string $path The path to look in.
     * @param string $key The key to add shells to
     * @param string[] $skip A list of commands to exclude.
     * @return array The updated list of shells.
     */
   
protected function _findShells($shellList, $path, $key, $skip)
    {
       
$shells = $this->_scanDir($path);

        return
$this->_appendShells($key, $shells, $shellList, $skip);
    }

   
/**
     * Scan the provided paths for shells, and append them into $shellList
     *
     * @param string $type The type of object.
     * @param array $shells The shell name.
     * @param array $shellList List of shells.
     * @param array $skip List of command names to skip.
     * @return array The updated $shellList
     */
   
protected function _appendShells($type, $shells, $shellList, $skip)
    {
        if (!isset(
$shellList[$type])) {
           
$shellList[$type] = [];
        }

        foreach (
$shells as $shell) {
           
$name = Inflector::underscore(preg_replace('/(Shell|Command)$/', '', $shell));
            if (!
in_array($name, $skip, true)) {
               
$shellList[$type][] = $name;
            }
        }
       
sort($shellList[$type]);

        return
$shellList;
    }

   
/**
     * Scan a directory for .php files and return the class names that
     * should be within them.
     *
     * @param string $dir The directory to read.
     * @return array The list of shell classnames based on conventions.
     */
   
protected function _scanDir($dir)
    {
       
$dir = new Folder($dir);
       
$contents = $dir->read(true, true);
        if (empty(
$contents[1])) {
            return [];
        }
       
$shells = [];
        foreach (
$contents[1] as $file) {
            if (
substr($file, -4) !== '.php') {
                continue;
            }
           
$shells[] = substr($file, 0, -4);
        }

        return
$shells;
    }

   
/**
     * Return a list of all commands
     *
     * @return array
     */
   
public function commands()
    {
       
$shellList = $this->getShellList();
       
$flatten = Hash::flatten($shellList);
       
$duplicates = array_intersect($flatten, array_unique(array_diff_key($flatten, array_unique($flatten))));
       
$duplicates = Hash::expand($duplicates);

       
$options = [];
        foreach (
$shellList as $type => $commands) {
            foreach (
$commands as $shell) {
               
$prefix = '';
                if (
                    !
in_array(strtolower($type), ['app', 'core']) &&
                    isset(
$duplicates[$type]) &&
                   
in_array($shell, $duplicates[$type])
                ) {
                   
$prefix = $type . '.';
                }

               
$options[] = $prefix . $shell;
            }
        }

        return
$options;
    }

   
/**
     * Return a list of subcommands for a given command
     *
     * @param string $commandName The command you want subcommands from.
     * @return string[]
     * @throws \ReflectionException
     */
   
public function subCommands($commandName)
    {
       
$Shell = $this->getShell($commandName);

        if (!
$Shell) {
            return [];
        }

       
$taskMap = $this->Tasks->normalizeArray((array)$Shell->tasks);
       
$return = array_keys($taskMap);
       
$return = array_map('Cake\Utility\Inflector::underscore', $return);

       
$shellMethodNames = ['main', 'help', 'getOptionParser', 'initialize', 'runCommand'];

       
$baseClasses = ['Object', 'Shell', 'AppShell'];

       
$Reflection = new ReflectionClass($Shell);
       
$methods = $Reflection->getMethods(ReflectionMethod::IS_PUBLIC);
       
$methodNames = [];
        foreach (
$methods as $method) {
           
$declaringClass = $method->getDeclaringClass()->getShortName();
            if (!
in_array($declaringClass, $baseClasses)) {
               
$methodNames[] = $method->getName();
            }
        }

       
$return = array_merge($return, array_diff($methodNames, $shellMethodNames));
       
sort($return);

        return
$return;
    }

   
/**
     * Get Shell instance for the given command
     *
     * @param string $commandName The command you want.
     * @return \Cake\Console\Shell|false Shell instance if the command can be found, false otherwise.
     */
   
public function getShell($commandName)
    {
        list(
$pluginDot, $name) = pluginSplit($commandName, true);

        if (
in_array(strtolower($pluginDot), ['app.', 'core.'])) {
           
$commandName = $name;
           
$pluginDot = '';
        }

        if (!
in_array($commandName, $this->commands()) && (empty($pluginDot) && !in_array($name, $this->commands()))) {
            return
false;
        }

        if (empty(
$pluginDot)) {
           
$shellList = $this->getShellList();

            if (!
in_array($commandName, $shellList['app']) && !in_array($commandName, $shellList['CORE'])) {
                unset(
$shellList['CORE'], $shellList['app']);
                foreach (
$shellList as $plugin => $commands) {
                    if (
in_array($commandName, $commands)) {
                       
$pluginDot = $plugin . '.';
                        break;
                    }
                }
            }
        }

       
$name = Inflector::camelize($name);
       
$pluginDot = Inflector::camelize($pluginDot);
       
$class = App::className($pluginDot . $name, 'Shell', 'Shell');
        if (!
$class) {
            return
false;
        }

       
/** @var \Cake\Console\Shell $Shell */
       
$Shell = new $class();
       
$Shell->plugin = trim($pluginDot, '.');
       
$Shell->initialize();

        return
$Shell;
    }

   
/**
     * Get options list for the given command or subcommand
     *
     * @param string $commandName The command to get options for.
     * @param string $subCommandName The subcommand to get options for. Can be empty to get options for the command.
     * If this parameter is used, the subcommand must be a valid subcommand of the command passed
     * @return array Options list for the given command or subcommand
     */
   
public function options($commandName, $subCommandName = '')
    {
       
$Shell = $this->getShell($commandName);

        if (!
$Shell) {
            return [];
        }

       
$parser = $Shell->getOptionParser();

        if (!empty(
$subCommandName)) {
           
$subCommandName = Inflector::camelize($subCommandName);
            if (
$Shell->hasTask($subCommandName)) {
               
$parser = $Shell->{$subCommandName}->getOptionParser();
            } else {
                return [];
            }
        }

       
$options = [];
       
$array = $parser->options();
       
/** @var \Cake\Console\ConsoleInputOption $obj */
       
foreach ($array as $name => $obj) {
           
$options[] = "--$name";
           
$short = $obj->short();
            if (
$short) {
               
$options[] = "-$short";
            }
        }

        return
$options;
    }
}