You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
9.5 KiB
393 lines
9.5 KiB
<?php
|
|
|
|
namespace EE_CLI;
|
|
|
|
use EE_CLI;
|
|
use EE_CLI\Utils;
|
|
use EE_CLI\Dispatcher;
|
|
|
|
/**
|
|
* Performs the execution of a command.
|
|
*
|
|
* @package EE_CLI
|
|
*/
|
|
class Runner {
|
|
|
|
private $global_config_path, $project_config_path;
|
|
|
|
private $config, $extra_config;
|
|
|
|
private $arguments, $assoc_args;
|
|
|
|
private $_early_invoke = array();
|
|
|
|
private $_global_config_path_debug;
|
|
|
|
private $_project_config_path_debug;
|
|
|
|
public function __get( $key ) {
|
|
if ( '_' === $key[0] )
|
|
return null;
|
|
|
|
return $this->$key;
|
|
}
|
|
|
|
/**
|
|
* Register a command for early invocation.
|
|
*
|
|
* @param string $when Named execution hook
|
|
* @param EE_CLI\Dispatcher\Subcommand $command
|
|
*/
|
|
public function register_early_invoke( $when, $command ) {
|
|
$this->_early_invoke[ $when ][] = array_slice( Dispatcher\get_path( $command ), 1 );
|
|
}
|
|
|
|
/**
|
|
* Perform the early invocation of a command.
|
|
*
|
|
* @param string $when Named execution hook
|
|
*/
|
|
private function do_early_invoke( $when ) {
|
|
if ( !isset( $this->_early_invoke[ $when ] ) )
|
|
return;
|
|
|
|
foreach ( $this->_early_invoke[ $when ] as $path ) {
|
|
if ( $this->cmd_starts_with( $path ) ) {
|
|
$this->_run_command();
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the path to the global configuration YAML file.
|
|
*
|
|
* @return string|false
|
|
*/
|
|
private function get_global_config_path() {
|
|
|
|
if ( isset( $runtime_config['config'] ) ) {
|
|
$config_path = $runtime_config['config'];
|
|
$this->_global_config_path_debug = 'Using global config from config runtime arg: ' . $config_path;
|
|
} else if ( getenv( 'EE_CLI_CONFIG_PATH' ) ) {
|
|
$config_path = getenv( 'EE_CLI_CONFIG_PATH' );
|
|
$this->_global_config_path_debug = 'Using global config from EE_CLI_CONFIG_PATH env var: ' . $config_path;
|
|
} else {
|
|
$config_path = getenv( 'HOME' ) . '/.ee-cli/config.yml';
|
|
$this->_global_config_path_debug = 'Using default global config: ' . $config_path;
|
|
}
|
|
|
|
if ( is_readable( $config_path ) ) {
|
|
return $config_path;
|
|
} else {
|
|
$this->_global_config_path_debug = 'No readable global config found';
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the path to the project-specific configuration
|
|
* YAML file.
|
|
* ee-cli.local.yml takes priority over ee-cli.yml.
|
|
*
|
|
* @return string|false
|
|
*/
|
|
private function get_project_config_path() {
|
|
$config_files = array(
|
|
'ee-cli.local.yml',
|
|
'ee-cli.yml'
|
|
);
|
|
|
|
// Stop looking upward when we find we have emerged from a subdirectory
|
|
// install into a parent install
|
|
$project_config_path = Utils\find_file_upward( $config_files, getcwd(), function ( $dir ) {
|
|
static $wp_load_count = 0;
|
|
$wp_load_path = $dir . DIRECTORY_SEPARATOR . 'wp-load.php';
|
|
if ( file_exists( $wp_load_path ) ) {
|
|
$wp_load_count += 1;
|
|
}
|
|
return $wp_load_count > 1;
|
|
} );
|
|
if ( ! empty( $project_config_path ) ) {
|
|
$this->_project_config_path_debug = 'Using project config: ' . $project_config_path;
|
|
} else {
|
|
$this->_project_config_path_debug = 'No project config found';
|
|
}
|
|
return $project_config_path;
|
|
}
|
|
|
|
private function cmd_starts_with( $prefix ) {
|
|
return $prefix == array_slice( $this->arguments, 0, count( $prefix ) );
|
|
}
|
|
|
|
/**
|
|
* Given positional arguments, find the command to execute.
|
|
*
|
|
* @param array $args
|
|
* @return array|string Command, args, and path on success; error message on failure
|
|
*/
|
|
public function find_command_to_run( $args ) {
|
|
$command = \EE_CLI::get_root_command();
|
|
|
|
$cmd_path = array();
|
|
|
|
while ( !empty( $args ) && $command->can_have_subcommands() ) {
|
|
$cmd_path[] = $args[0];
|
|
$full_name = implode( ' ', $cmd_path );
|
|
|
|
$subcommand = $command->find_subcommand( $args );
|
|
|
|
if ( !$subcommand ) {
|
|
if ( count( $cmd_path ) > 1 ) {
|
|
$child = array_pop( $cmd_path );
|
|
$parent_name = implode( ' ', $cmd_path );
|
|
return sprintf(
|
|
"'%s' is not a registered subcommand of '%s'. See 'ee help %s'.",
|
|
$child,
|
|
$parent_name,
|
|
$parent_name
|
|
);
|
|
} else {
|
|
return sprintf(
|
|
"'%s' is not a registered ee command. See 'ee help'.",
|
|
$full_name
|
|
);
|
|
}
|
|
}
|
|
|
|
/* if ( $this->is_command_disabled( $subcommand ) ) {
|
|
return sprintf(
|
|
"The '%s' command has been disabled from the config file.",
|
|
$full_name
|
|
);
|
|
}
|
|
*/
|
|
|
|
$command = $subcommand;
|
|
}
|
|
|
|
return array( $command, $args, $cmd_path );
|
|
}
|
|
|
|
/**
|
|
* Find the WP-CLI command to run given arguments,
|
|
* and invoke it.
|
|
*
|
|
* @param array $args Positional arguments including command name
|
|
* @param array $assoc_args
|
|
*/
|
|
public function run_command( $args, $assoc_args = array() ) {
|
|
$r = $this->find_command_to_run( $args );
|
|
if ( is_string( $r ) ) {
|
|
EE_CLI::error( $r );
|
|
}
|
|
|
|
list( $command, $final_args, $cmd_path ) = $r;
|
|
|
|
$name = implode( ' ', $cmd_path );
|
|
|
|
if ( isset( $this->extra_config[ $name ] ) ) {
|
|
$extra_args = $this->extra_config[ $name ];
|
|
} else {
|
|
$extra_args = array();
|
|
}
|
|
|
|
EE_CLI::debug( 'Running command: ' . $name );
|
|
try {
|
|
$command->invoke( $final_args, $assoc_args, $extra_args );
|
|
} catch ( EE_CLI\Iterators\Exception $e ) {
|
|
EE_CLI::error( $e->getMessage() );
|
|
}
|
|
}
|
|
|
|
private function _run_command() {
|
|
$this->run_command( $this->arguments, $this->assoc_args );
|
|
}
|
|
|
|
/**
|
|
* Check whether a given command is disabled by the config
|
|
*
|
|
* @return bool
|
|
*/
|
|
/*public function is_command_disabled( $command ) {
|
|
$path = implode( ' ', array_slice( \EE_CLI\Dispatcher\get_path( $command ), 1 ) );
|
|
return in_array( $path, $this->config['disabled_commands'] );
|
|
}*/
|
|
|
|
/**
|
|
* Transparently convert deprecated syntaxes
|
|
*
|
|
* @param array $args
|
|
* @param array $assoc_args
|
|
* @return array
|
|
*/
|
|
private static function back_compat_conversions( $args, $assoc_args ) {
|
|
$top_level_aliases = array(
|
|
'sql' => 'db',
|
|
'blog' => 'site'
|
|
);
|
|
if ( count( $args ) > 0 ) {
|
|
foreach ( $top_level_aliases as $old => $new ) {
|
|
if ( $old == $args[0] ) {
|
|
$args[0] = $new;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --json -> --format=json
|
|
if ( isset( $assoc_args['json'] ) ) {
|
|
$assoc_args['format'] = 'json';
|
|
unset( $assoc_args['json'] );
|
|
}
|
|
|
|
// --{version|info} -> cli {version|info}
|
|
if ( empty( $args ) ) {
|
|
$special_flags = array( 'version', 'info' );
|
|
foreach ( $special_flags as $key ) {
|
|
if ( isset( $assoc_args[ $key ] ) ) {
|
|
$args = array( 'cli', $key );
|
|
unset( $assoc_args[ $key ] );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return array( $args, $assoc_args );
|
|
}
|
|
|
|
/*
|
|
Dynamic arguments for stack to be checked before parsing
|
|
*/
|
|
private static function stack_work($args, $assoc_args)
|
|
{
|
|
print_r($args);
|
|
print_r($assoc_args);
|
|
foreach ( $assoc_args as $key => $value) {
|
|
if ($args[0] === 'stack') {
|
|
if ($args[1] === 'install'){
|
|
// check if key matches any stack config
|
|
// otherwise throw error if not exists
|
|
unset( $assoc_args[ $key ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
return array( $args, $assoc_args );
|
|
}
|
|
|
|
/**
|
|
* Whether or not the output should be rendered in color
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function in_color() {
|
|
return $this->colorize;
|
|
}
|
|
|
|
private function init_colorization() {
|
|
if ( 'auto' === $this->config['color'] ) {
|
|
$this->colorize = ( !\cli\Shell::isPiped() && !\EE_CLI\Utils\is_windows() );
|
|
} else {
|
|
$this->colorize = $this->config['color'];
|
|
}
|
|
}
|
|
|
|
private function init_logger() {
|
|
if ( $this->config['quiet'] )
|
|
$logger = new \EE_CLI\Loggers\Quiet;
|
|
else
|
|
$logger = new \EE_CLI\Loggers\Regular( $this->in_color() );
|
|
|
|
EE_CLI::set_logger( $logger );
|
|
}
|
|
|
|
|
|
private function init_config() {
|
|
$configurator = \EE_CLI::get_configurator();
|
|
|
|
// File config
|
|
{
|
|
$this->global_config_path = $this->get_global_config_path();
|
|
$this->project_config_path = $this->get_project_config_path();
|
|
|
|
$configurator->merge_yml( $this->global_config_path );
|
|
$configurator->merge_yml( $this->project_config_path );
|
|
}
|
|
|
|
// Runtime config and args
|
|
{
|
|
list( $args, $assoc_args, $runtime_config ) = $configurator->parse_args(
|
|
array_slice( $GLOBALS['argv'], 1 ) );
|
|
|
|
list( $this->arguments, $this->assoc_args ) = self::back_compat_conversions(
|
|
$args, $assoc_args );
|
|
|
|
list( $this->arguments, $this->assoc_args ) = self::stack_work(
|
|
$args, $assoc_args );
|
|
|
|
$configurator->merge_array( $runtime_config );
|
|
}
|
|
|
|
list( $this->config, $this->extra_config ) = $configurator->to_array();
|
|
}
|
|
|
|
|
|
public function start() {
|
|
$this->init_config();
|
|
$this->init_colorization();
|
|
$this->init_logger();
|
|
|
|
print_r($this->assoc_args);
|
|
EE_CLI::debug( $this->_global_config_path_debug );
|
|
EE_CLI::debug( $this->_project_config_path_debug );
|
|
|
|
// $this->check_root();
|
|
|
|
if ( empty( $this->arguments ) )
|
|
$this->arguments[] = 'help';
|
|
|
|
// Protect 'cli info' from most of the runtime
|
|
if ( 'cli' === $this->arguments[0] && ! empty( $this->arguments[1] ) && 'info' === $this->arguments[1] ) {
|
|
$this->_run_command();
|
|
exit;
|
|
}
|
|
|
|
// Load bundled commands early, so that they're forced to use the same
|
|
// APIs as non-bundled commands.
|
|
Utils\load_command( $this->arguments[0] );
|
|
|
|
if ( isset( $this->config['require'] ) ) {
|
|
foreach ( $this->config['require'] as $path ) {
|
|
if ( ! file_exists( $path ) ) {
|
|
EE_CLI::error( sprintf( "Required file '%s' doesn't exist", basename( $path ) ) );
|
|
}
|
|
Utils\load_file( $path );
|
|
EE_CLI::debug( 'Required file from config: ' . $path );
|
|
}
|
|
}
|
|
|
|
// Show synopsis if it's a composite command.
|
|
$r = $this->find_command_to_run( $this->arguments );
|
|
if ( is_array( $r ) ) {
|
|
list( $command ) = $r;
|
|
|
|
if ( $command->can_have_subcommands() ) {
|
|
$command->show_usage();
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// First try at showing man page
|
|
if ( 'help' === $this->arguments[0] ) {
|
|
$this->_run_command();
|
|
}
|
|
|
|
//$this->check_wp_version();
|
|
|
|
|
|
|
|
$this->_run_command();
|
|
|
|
}
|
|
}
|
|
|