raspisms/descartes/Console.php

244 lines
7.0 KiB
PHP

<?php
namespace descartes;
/**
* Class to route console query
*/
class Console
{
/**
* Check if a command explicitly ask for help
* @param array $command : Command called
* @param boolean : True if need help, false else
*/
private static function is_asking_for_help (array $command) : bool
{
return (isset($command[1]) && $command[1] == '--help');
}
/**
* Search name of controller to call and verify if it exist
* @param array $command : Command called
* @return string | bool : False if controller didn't exist. Name of controller if find
*/
private static function extract_controller (array $command)
{
//If we need help, we remove help flag
if (self::is_asking_for_help($command))
{
unset($command[1]);
$command = array_values($command);
}
//If no controller found
if (!isset($command[1]))
{
return false;
}
$controller = $command[1];
$controller = str_replace('/', '\\', $controller);
$ends_with = mb_substr($controller, -4);
if ($ends_with === '.php')
{
$controller = mb_substr($controller, 0, mb_strlen($controller) - 4);
}
if (!class_exists($controller))
{
return false;
}
return $controller;
}
/**
* Search name of the method to call, an verify it exist and is available
* @param array $command : Command called
* @param string $controller : Name of controller of the method
* @return string | bool : False if method not found, not exist or not available, method name else
*/
private static function extract_method (array $command, string $controller)
{
//Remove help flag if needed
if (self::is_asking_for_help($command))
{
unset($command[1]);
$command = array_values($command);
}
//If no method passed
if (!isset($command[2]))
{
return false;
}
$method = $command[2];
if (!method_exists($controller, $method))
{
return false;
}
return $method;
}
/**
* Extract params from the command
* @param array $command : La commande à analyser
* @return mixed : Array of params (format name => value).
* @return array | bool : An array with parameters in order we want theme to be passed to method. False if a need parameter is missing
*/
private static function extract_params (array $command, string $controller, string $method)
{
//Remove invocation, controller and method from command
unset($command[0], $command[1], $command[2]);
$command = array_values($command);
$params = [];
foreach ($command as $param)
{
$param = explode('=', $param, 2);
$name = str_replace('--', '', $param[0]);
$value = $param[1];
$params[$name] = $value;
}
$reflection = new \ReflectionMethod($controller, $method);
$method_arguments = [];
foreach ($reflection->getParameters() as $parameter)
{
if (!array_key_exists($parameter->getName(), $params) && !$parameter->isDefaultValueAvailable())
{
return false;
}
if ($parameter->isDefaultValueAvailable())
{
$method_arguments[$parameter->getName()] = $parameter->getDefaultValue();
}
if (!array_key_exists($parameter->getName(), $params))
{
continue;
}
//On ajoute la variable dans le tableau des arguments de la méthode
$method_arguments[$parameter->getName()] = $params[$parameter->getName()];
}
return $method_arguments;
}
/**
* Generate help text
* @param array $command : Called command
* @param ?string $controller : Name of the controller we want help for, null if not given
* @param ?string $method : Name of the method we want help for, null if not giver
* @param boolean $missing_arguments : If there is required arguments missing, false by default
* @param string : Le texte d'aide à afficher
*/
private static function generate_help_text (array $command, ?string $controller = null, ?string $method = null, bool $missing_arguments = false) : string
{
$retour = '';
$retour .= "Help : \n";
//Si pas de controlleur, on sort l'aide par défaut
if (!$controller)
{
$retour .= "You havn't supplied a Controller to call. To see help of a Controller : " . $command[0] . " --help <name controller> <name method>\n";
return $retour;
}
if ($missing_arguments)
{
$retour .= "Some required arguments are missing. \n";
}
if (!$method)
{
$retour .= 'Help of Controller ' . $controller . "\n" .
"Methods : \n";
$reflection = new \ReflectionClass($controller);
$reflection_methods = $reflection->getMethods();
}
else
{
$reflection_methods = [new \ReflectionMethod($controller, $method)];
$retour .= 'Help of Controller ' . $controller . ' and method ' . $method . "\n";
}
foreach ($reflection_methods as $reflection_method)
{
$retour .= " " . $reflection_method->getName();
foreach ($reflection_method->getParameters() as $parameter)
{
$retour .= ' --' . $parameter->getName() . "=<value" . ($parameter->isDefaultValueAvailable() ? ' (by default, ' . gettype($parameter->getDefaultValue()) . ':' . str_replace(PHP_EOL, '', print_r($parameter->getDefaultValue(), true)) . ')': '') . ">";
}
$retour .= "\n";
}
return $retour;
}
/**
* This method call controller and method from command
* @param array $command : Command to call
* @param $args : Arguments to pass to Controller constructor
* @return bool : False on error, true else
*/
public static function execute_command (array $command, ...$args)
{
$controller = self::extract_controller($command);
if (!$controller)
{
echo self::generate_help_text($command);
return true;
}
$method = self::extract_method($command, $controller);
if (!$method)
{
echo self::generate_help_text($command, $controller);
return true;
}
$params = self::extract_params($command, $controller, $method);
if ($params === false)
{
echo self::generate_help_text($command, $controller, $method, true);
return true;
}
$asking_for_help = self::is_asking_for_help($command);
if ($asking_for_help)
{
echo self::generate_help_text($command, $controller, $method);
return true;
}
$reflection = new \ReflectionClass($controller);
$reflection_method = $reflection->getMethod($method);
if (!$reflection_method->isStatic())
{
$controller = new $controller(...$args);
}
return call_user_func_array([$controller, $method], $params);
}
}