Adding Zend\Console\Getopt option callback hooks #5713

Merged
merged 2 commits into from Mar 4, 2014

2 participants

@nicktacular

Based on some @todo annotations present in this class, I've added the ability to use callbacks when options are parsed. This feature addresses several of these @todo annotations.

(1) Triggering callbacks for options when present

You can now trigger a callback for any option that is present. For example, suppose you wish to trigger a callback when the option apples is passed, either by it's short form a or by it's alias apple. Here is how you could do this:

$opts = new Getopt(array(
    'a|apple|apples=s' => 'Specify a type of apple you want to eat.'
));

$opts->setOptionCallback('apple', function($value){
    echo "You want a $value apple!";
});

As soon as you call $opts->parse() the callback will be called assuming you passed -a Gala, --apple=Gala, or --apples=Gala on the command line. Furthermore, the value "Gala" will be passed by value to the first callback parameter.

(2) Invalidating usage by returning false

Using a callback, you can return false to indicate that there is an issue with the way an option was used. Perhaps there is a dependance on some other value that must be present. For example:

$opts = new Getopt(array(
    'fruit|f-s' => 'The kind of fruit you would like to eat.',
    'a|apple|apples-s' => 'Specify a type of apple you want to eat.'
));

$opts->setOptionCallback('fruit', function($value, $opts){
    if (!$value) {
        //technically optional, so return
        return;
    }

    if ($value != 'apple') {
        echo "You like this kind of fruit: $value.";
        return;
    }

    if ($value == 'apple' && null === ($apple = $opts->getOption('apple'))) {
        return false;
        //you could also just throw a Exception\RuntimeException here, too, if you want more specificity
    }

    echo "You like apples, specifically $apple.";
});

Notice that you can specify a 2nd argument to the callback which is the instance of Getopt you're currently working with. This allows you to check on other command line parameters, should you need to.

This also accomplishes conditionally required parameters from the command line. Here, both options are technically optional, but specifying --fruit=apple will trigger the apple requirement. You can use callbacks to accomplish conditional logic in this manner.

Other @todo requests

Handle flags that implicitly print usage message, e.g. --help: this can easily be accomplished using a callback. Since Getopt class should never be dealing without output, the way to deal with this would be to attach a callback that throws the Exeption\RuntimeException method with the usage information. You can then use exception handling to print out the error message in the existing error handling for console apps:

try {
    $opts = new Getopt(/* params */);
    $opts->setOptionCallback('help', function($val, $opts){
        throw new Exception\RuntimeException('Usage:', $opts->getUsageMessage());
    });
    $opts->parse();
} catch (Exception\RuntimeException $e) {
    echo $e->getMessage() . PHP_EOL;
    echo $e->getUsageMessage();
    exit(1);
}

Enable user to specify header and footer content in the help message.: This class does not deal with output. The previous example could simply add header/footer information to the printing of the exception message and usage message wherever appropriate. This would simply be the programmers choice.


Excerpt of class doc block:

 *
 * @todo  Handle flags that implicitly print usage message, e.g. --help
 *
 * @todo  Enable user to specify header and footer content in the help message.
 *
 * @todo  Feature request to handle option interdependencies.
 *        e.g. if -b is specified, -a must be specified or else the
 *        usage is invalid.
 *
 * @todo  Feature request to implement callbacks.
 *        e.g. if -a is specified, run function 'handleOptionA'().
@Maks3w Maks3w commented on an outdated diff Feb 23, 2014
library/Zend/Console/Getopt.php
@@ -203,9 +199,9 @@ class Getopt
* The third parameter is an array of configuration parameters
* to control the behavior of this instance of Getopt; it is optional.
*
- * @param array $rules
- * @param array $argv
- * @param array $getoptConfig
+ * @param array $rules
@Maks3w
Zend Framework member
Maks3w added a line comment Feb 23, 2014

Please roll back all changes not related with the fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@nicktacular

Removed the stylistic changes for the method param docblocks.

@weierophinney
Zend Framework member

I love this idea! Looking forward to reviewing this for 2.3.0.

@weierophinney weierophinney added this to the 2.3.0 milestone Mar 3, 2014
@weierophinney weierophinney self-assigned this Mar 4, 2014
@weierophinney weierophinney added a commit that referenced this pull request Mar 4, 2014
@weierophinney weierophinney [#5713] CS fixes
- One argument per line on multi-line function calls
- @return self (instead of \Zend\Console\Getopt); performed throughout
  class for consistency
- Removed all @return void and @return null annotations
- Relative namespace qualification for all @throws annotations
497067f
@weierophinney weierophinney added a commit that referenced this pull request Mar 4, 2014
@weierophinney weierophinney Merge branch 'feature/5713' into develop
Close #5713
edab149
@weierophinney weierophinney merged commit 5df6f48 into zendframework:develop Mar 4, 2014

1 check failed

Details default The Travis CI build could not complete due to an error
@weierophinney weierophinney added a commit to zendframework/zend-console that referenced this pull request May 15, 2015
@weierophinney weierophinney Merge pull request zendframework/zendframework#5713 from nicktacular/…
…getopt

Adding Zend\Console\Getopt option callback hooks
139b8e7
@weierophinney weierophinney added a commit to zendframework/zend-console that referenced this pull request May 15, 2015
@weierophinney weierophinney [zendframework/zendframework#5713] CS fixes
- One argument per line on multi-line function calls
- @return self (instead of \Zend\Console\Getopt); performed throughout
  class for consistency
- Removed all @return void and @return null annotations
- Relative namespace qualification for all @throws annotations
a7fe006
@weierophinney weierophinney added a commit to zendframework/zend-console that referenced this pull request May 15, 2015
@weierophinney weierophinney Merge branch 'feature/5713' into develop 54faf5f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment