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.
 
 
 

163 lines
3.7 KiB

<?php
namespace EE_CLI;
/**
* Checks if the list of parameters matches the specification defined in the synopsis.
*/
class SynopsisValidator {
/**
* @var array $spec Structured representation of command synopsis.
*/
private $spec = array();
/**
* @param string $synopsis Command's synopsis.
*/
public function __construct( $synopsis ) {
$this->spec = SynopsisParser::parse( $synopsis );
}
/**
* Get any unknown arugments.
*
* @return array
*/
public function get_unknown() {
return array_column( $this->query_spec( array(
'type' => 'unknown',
) ), 'token' );
}
/**
* Check whether there are enough positional arguments.
*
* @param array $args Positional arguments.
* @return bool
*/
public function enough_positionals( $args ) {
$positional = $this->query_spec( array(
'type' => 'positional',
'optional' => false,
) );
return count( $args ) >= count( $positional );
}
/**
* Check for any unknown positionals.
*
* @param array $args Positional arguments.
* @return array
*/
public function unknown_positionals( $args ) {
$positional_repeating = $this->query_spec( array(
'type' => 'positional',
'repeating' => true,
) );
// At least one positional supports as many as possible.
if ( !empty( $positional_repeating ) )
return array();
$positional = $this->query_spec( array(
'type' => 'positional',
'repeating' => false,
) );
return array_slice( $args, count( $positional ) );
}
/**
* Check that all required keys are present and that they have values.
*
* @param array $assoc_args Parameters passed to command.
* @return array
*/
public function validate_assoc( $assoc_args ) {
$assoc_spec = $this->query_spec( array(
'type' => 'assoc',
) );
$errors = array(
'fatal' => array(),
'warning' => array()
);
$to_unset = array();
foreach ( $assoc_spec as $param ) {
$key = $param['name'];
if ( !isset( $assoc_args[ $key ] ) ) {
if ( !$param['optional'] ) {
$errors['fatal'][$key] = "missing --$key parameter";
}
} else {
if ( true === $assoc_args[ $key ] && !$param['value']['optional'] ) {
$error_type = ( !$param['optional'] ) ? 'fatal' : 'warning';
$errors[ $error_type ][$key] = "--$key parameter needs a value";
$to_unset[] = $key;
}
}
}
return array( $errors, $to_unset );
}
/**
* Check whether there are unknown parameters supplied.
*
* @param array $assoc_args Parameters passed to command.
* @return array|false
*/
public function unknown_assoc( $assoc_args ) {
$generic = $this->query_spec( array(
'type' => 'generic',
) );
if ( count( $generic ) )
return array();
$known_assoc = array();
foreach ( $this->spec as $param ) {
if ( in_array( $param['type'], array( 'assoc', 'flag' ) ) )
$known_assoc[] = $param['name'];
}
return array_diff( array_keys( $assoc_args ), $known_assoc );
}
/**
* Filters a list of associative arrays, based on a set of key => value arguments.
*
* @param array $args An array of key => value arguments to match against
* @param string $operator
* @return array
*/
private function query_spec( $args, $operator = 'AND' ) {
$operator = strtoupper( $operator );
$count = count( $args );
$filtered = array();
foreach ( $this->spec as $key => $to_match ) {
$matched = 0;
foreach ( $args as $m_key => $m_value ) {
if ( array_key_exists( $m_key, $to_match ) && $m_value == $to_match[ $m_key ] )
$matched++;
}
if ( ( 'AND' == $operator && $matched == $count )
|| ( 'OR' == $operator && $matched > 0 )
|| ( 'NOT' == $operator && 0 == $matched ) ) {
$filtered[$key] = $to_match;
}
}
return $filtered;
}
}