From 8bfdf451c411afd9c4552f61bcdd4bca403cafe6 Mon Sep 17 00:00:00 2001 From: scribu Date: Tue, 30 Jul 2013 03:55:57 +0300 Subject: [PATCH] introduce SynopsisValidator class --- php/WP_CLI/Dispatcher/Subcommand.php | 2 +- php/WP_CLI/SynopsisParser.php | 95 ------------------------------- php/WP_CLI/SynopsisValidator.php | 105 +++++++++++++++++++++++++++++++++++ tests/test-arg-validation.php | 12 ++-- 4 files changed, 112 insertions(+), 102 deletions(-) create mode 100644 php/WP_CLI/SynopsisValidator.php diff --git a/php/WP_CLI/Dispatcher/Subcommand.php b/php/WP_CLI/Dispatcher/Subcommand.php index 3203ef9d..16d101e3 100644 --- a/php/WP_CLI/Dispatcher/Subcommand.php +++ b/php/WP_CLI/Dispatcher/Subcommand.php @@ -42,7 +42,7 @@ class Subcommand extends CompositeCommand { if ( !$synopsis ) return; - $parser = new \WP_CLI\SynopsisParser( $synopsis ); + $parser = new \WP_CLI\SynopsisValidator( $synopsis ); if ( !$parser->enough_positionals( $args ) ) { $this->show_usage(); exit(1); diff --git a/php/WP_CLI/SynopsisParser.php b/php/WP_CLI/SynopsisParser.php index eb5dc8e0..3daf70d3 100644 --- a/php/WP_CLI/SynopsisParser.php +++ b/php/WP_CLI/SynopsisParser.php @@ -6,72 +6,6 @@ class SynopsisParser { private static $patterns = array(); - private $params = array(); - - public function __construct( $synopsis ) { - $this->params = $this->parse( $synopsis ); - } - - public function enough_positionals( $args ) { - $positional = $this->query_params( array( - 'type' => 'positional', - 'flavour' => 'mandatory' - ) ); - - return count( $args ) >= count( $positional ); - } - - public function validate_assoc( &$assoc_args, $ignored_keys = array() ) { - $assoc = $this->query_params( array( - 'type' => 'assoc', - ) ); - - $errors = array( - 'fatal' => array(), - 'warning' => array() - ); - - foreach ( $assoc as $param ) { - $key = $param['name']; - - if ( in_array( $key, $ignored_keys ) ) - continue; - - if ( !isset( $assoc_args[ $key ] ) ) { - if ( 'mandatory' == $param['flavour'] ) { - $errors['fatal'][] = "missing --$key parameter"; - } - } else { - if ( true === $assoc_args[ $key ] ) { - $error_type = ( 'mandatory' == $param['flavour'] ) ? 'fatal' : 'warning'; - $errors[ $error_type ][] = "--$key parameter needs a value"; - - unset( $assoc_args[ $key ] ); - } - } - } - - return $errors; - } - - public function unknown_assoc( $assoc_args ) { - $generic = $this->query_params( array( - 'type' => 'generic', - ) ); - - if ( count( $generic ) ) - return array(); - - $known_assoc = array(); - - foreach ( $this->params as $param ) { - if ( in_array( $param['type'], array( 'assoc', 'flag' ) ) ) - $known_assoc[] = $param['name']; - } - - return array_diff( array_keys( $assoc_args ), $known_assoc ); - } - /** * @param string * @return array List of parameters @@ -134,34 +68,5 @@ class SynopsisParser { } } } - - /** - * Filters a list of associatve 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_params( $args, $operator = 'AND' ) { - $operator = strtoupper( $operator ); - $count = count( $args ); - $filtered = array(); - - foreach ( $this->params 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; - } } diff --git a/php/WP_CLI/SynopsisValidator.php b/php/WP_CLI/SynopsisValidator.php new file mode 100644 index 00000000..597d89b5 --- /dev/null +++ b/php/WP_CLI/SynopsisValidator.php @@ -0,0 +1,105 @@ +spec = SynopsisParser::parse( $synopsis ); + } + + public function enough_positionals( $args ) { + $positional = $this->query_spec( array( + 'type' => 'positional', + 'flavour' => 'mandatory' + ) ); + + return count( $args ) >= count( $positional ); + } + + public function validate_assoc( &$assoc_args, $ignored_keys = array() ) { + $assoc = $this->query_spec( array( + 'type' => 'assoc', + ) ); + + $errors = array( + 'fatal' => array(), + 'warning' => array() + ); + + foreach ( $assoc as $param ) { + $key = $param['name']; + + if ( in_array( $key, $ignored_keys ) ) + continue; + + if ( !isset( $assoc_args[ $key ] ) ) { + if ( 'mandatory' == $param['flavour'] ) { + $errors['fatal'][] = "missing --$key parameter"; + } + } else { + if ( true === $assoc_args[ $key ] ) { + $error_type = ( 'mandatory' == $param['flavour'] ) ? 'fatal' : 'warning'; + $errors[ $error_type ][] = "--$key parameter needs a value"; + + unset( $assoc_args[ $key ] ); + } + } + } + + return $errors; + } + + 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 associatve 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; + } +} + diff --git a/tests/test-arg-validation.php b/tests/test-arg-validation.php index 88758911..f579823c 100644 --- a/tests/test-arg-validation.php +++ b/tests/test-arg-validation.php @@ -1,11 +1,11 @@ []' ); + $parser = new SynopsisValidator( ' []' ); $this->assertFalse( $parser->enough_positionals( array() ) ); $this->assertTrue( $parser->enough_positionals( array( 1, 2 ) ) ); @@ -13,7 +13,7 @@ class ArgValidationTests extends PHPUnit_Framework_TestCase { } function testRepeatingPositional() { - $parser = new SynopsisParser( ' [...]' ); + $parser = new SynopsisValidator( ' [...]' ); $this->assertFalse( $parser->enough_positionals( array() ) ); $this->assertTrue( $parser->enough_positionals( array( 1 ) ) ); @@ -21,14 +21,14 @@ class ArgValidationTests extends PHPUnit_Framework_TestCase { } function testUnknownAssocEmpty() { - $parser = new SynopsisParser( '' ); + $parser = new SynopsisValidator( '' ); $assoc_args = array( 'foo' => true, 'bar' => false ); $this->assertEquals( array_keys( $assoc_args ), $parser->unknown_assoc( $assoc_args ) ); } function testUnknownAssoc() { - $parser = new SynopsisParser( '--type= [--brand=] [--flag]' ); + $parser = new SynopsisValidator( '--type= [--brand=] [--flag]' ); $assoc_args = array( 'type' => 'analog', 'brand' => true, 'flag' => true ); $this->assertEmpty( $parser->unknown_assoc( $assoc_args ) ); @@ -38,7 +38,7 @@ class ArgValidationTests extends PHPUnit_Framework_TestCase { } function testMissingAssoc() { - $parser = new SynopsisParser( '--type= [--brand=] [--flag]' ); + $parser = new SynopsisValidator( '--type= [--brand=] [--flag]' ); $assoc_args = array( 'brand' => true, 'flag' => true ); $errors = $parser->validate_assoc( $assoc_args ); -- 2.11.0