Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

Adding Zend\Console\Getopt option callback hooks #5713

Merged
merged 2 commits into from
Mar 4, 2014
Merged

Adding Zend\Console\Getopt option callback hooks #5713

merged 2 commits into from
Mar 4, 2014

Conversation

nicktacular
Copy link
Contributor

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'().

* @param array $rules
* @param array $argv
* @param array $getoptConfig
* @param array $rules
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please roll back all changes not related with the fix

@nicktacular
Copy link
Contributor Author

Removed the stylistic changes for the method param docblocks.

@weierophinney
Copy link
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 added a commit that referenced this pull request Mar 4, 2014
Adding Zend\Console\Getopt option callback hooks
weierophinney added a commit that referenced this pull request Mar 4, 2014
- 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
weierophinney added a commit that referenced this pull request Mar 4, 2014
@weierophinney weierophinney merged commit 5df6f48 into zendframework:develop Mar 4, 2014
weierophinney added a commit to zendframework/zend-console that referenced this pull request May 15, 2015
…getopt

Adding Zend\Console\Getopt option callback hooks
weierophinney added a commit to zendframework/zend-console that referenced this pull request May 15, 2015
- 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
weierophinney added a commit to zendframework/zend-console that referenced this pull request May 15, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants