Overview

Packages

  • Argv

Classes

  • Horde_Argv_AmbiguousOptionException
  • Horde_Argv_BadOptionException
  • Horde_Argv_Exception
  • Horde_Argv_HelpFormatter
  • Horde_Argv_IndentedHelpFormatter
  • Horde_Argv_Option
  • Horde_Argv_OptionConflictException
  • Horde_Argv_OptionContainer
  • Horde_Argv_OptionException
  • Horde_Argv_OptionGroup
  • Horde_Argv_OptionValueException
  • Horde_Argv_Parser
  • Horde_Argv_TitledHelpFormatter
  • Horde_Argv_Translation
  • Horde_Argv_Values
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * @author   Chuck Hagenbuch <chuck@horde.org>
  4:  * @author   Mike Naberezny <mike@maintainable.com>
  5:  * @license  http://www.horde.org/licenses/bsd BSD
  6:  * @category Horde
  7:  * @package  Argv
  8:  */
  9: 
 10: /**
 11:  *   Abstract base class.
 12:  *
 13:  *  Class attributes:
 14:  *    standardOptionList : [Option]
 15:  *      list of standard options that will be accepted by all instances
 16:  *      of this parser class (intended to be overridden by subclasses).
 17:  *
 18:  *  Instance attributes:
 19:  *    optionList : [Option]
 20:  *      the list of Option objects contained by this OptionContainer
 21:  *    shortOpt : { string : Option }
 22:  *      dictionary mapping short option strings, eg. "-f" or "-X",
 23:  *      to the Option instances that implement them.  If an Option
 24:  *      has multiple short option strings, it will appears in this
 25:  *      dictionary multiple times. [1]
 26:  *    longOpt : { string : Option }
 27:  *      dictionary mapping long option strings, eg. "--file" or
 28:  *      "--exclude", to the Option instances that implement them.
 29:  *      Again, a given Option can occur multiple times in this
 30:  *      dictionary. [1]
 31:  *    defaults : { string : any }
 32:  *      dictionary mapping option destination names to default
 33:  *      values for each destination [1]
 34:  *
 35:  *  [1] These mappings are common to (shared by) all components of the
 36:  *      controlling Horde_Argv_Parser, where they are initially created.
 37:  *
 38:  * @category Horde
 39:  * @package  Argv
 40:  */
 41: class Horde_Argv_OptionContainer
 42: {
 43:     public $description = '';
 44:     public $optionList = array();
 45:     public $optionClass = 'Horde_Argv_Option';
 46:     public $defaults = array();
 47:     public $shortOpt = array();
 48:     public $longOpt = array();
 49:     public $conflictHandler;
 50: 
 51:     /**
 52:      * Initialize the option list and related data structures.
 53:      * This method must be provided by subclasses, and it must
 54:      * initialize at least the following instance attributes:
 55:      * optionList, shortOpt, longOpt, defaults.
 56:     */
 57:     public function __construct($optionClass, $conflictHandler, $description)
 58:     {
 59:         $this->_createOptionList();
 60: 
 61:         $this->optionClass = $optionClass;
 62:         $this->setConflictHandler($conflictHandler);
 63:         $this->setDescription($description);
 64:     }
 65: 
 66:     /**
 67:      * For use by Horde_Argv_Parser constructor -- create the master
 68:      * option mappings used by this Horde_Argv_Parser and all
 69:      * OptionGroups that it owns.
 70:      */
 71:     protected function _createOptionMappings()
 72:     {
 73:         $this->shortOpt = array();       // single letter -> Option instance
 74:         $this->longOpt = array();        // long option -> Option instance
 75:         $this->defaults = array();       // maps option dest -> default value
 76:     }
 77: 
 78:     /**
 79:      * For use by OptionGroup constructor -- use shared option
 80:      * mappings from the Horde_Argv_Parser that owns this OptionGroup.
 81:      */
 82:     protected function _shareOptionMappings($parser)
 83:     {
 84:         $this->shortOpt =& $parser->shortOpt;
 85:         $this->longOpt =& $parser->longOpt;
 86:         $this->defaults = $parser->defaults;
 87:     }
 88: 
 89:     public function setConflictHandler($handler)
 90:     {
 91:         if (!in_array($handler, array('error', 'resolve'))) {
 92:             throw new InvalidArgumentException('invalid conflictHandler ' . var_export($handler, true));
 93:         }
 94:         $this->conflictHandler = $handler;
 95:     }
 96: 
 97:     public function setDescription($description)
 98:     {
 99:         $this->description = $description;
100:     }
101: 
102:     public function getDescription()
103:     {
104:         return $this->description;
105:     }
106: 
107:     // -- Option-adding methods -----------------------------------------
108: 
109:     protected function _checkConflict($option)
110:     {
111:         $conflictOpts = array();
112:         foreach ($option->shortOpts as $opt) {
113:             if (isset($this->shortOpt[$opt])) {
114:                 $conflictOpts[$opt] = $this->shortOpt[$opt];
115:             }
116:         }
117:         foreach ($option->longOpts as $opt) {
118:             if (isset($this->longOpt[$opt])) {
119:                 $conflictOpts[$opt] = $this->longOpt[$opt];
120:             }
121:         }
122: 
123:         if ($conflictOpts) {
124:             $handler = $this->conflictHandler;
125:             if ($handler == 'error') {
126:                 throw new Horde_Argv_OptionConflictException(sprintf(
127:                     'conflicting option string(s): %s',
128:                     implode(', ', array_keys($conflictOpts))), $option);
129:             } elseif ($handler == 'resolve') {
130:                 foreach ($conflictOpts as $opt => $c_option) {
131:                     if (strncmp($opt, '--', 2) === 0) {
132:                         $key = array_search($opt, $c_option->longOpts);
133:                         if ($key !== false) {
134:                             unset($c_option->longOpts[$key]);
135:                         }
136:                         unset($this->longOpt[$opt]);
137:                     } else {
138:                         $key = array_search($opt, $c_option->shortOpts);
139:                         if ($key !== false) {
140:                             unset($c_option->shortOpts[$key]);
141:                         }
142:                         unset($this->shortOpt[$opt]);
143:                     }
144: 
145:                     if (! ($c_option->shortOpts || $c_option->longOpts)) {
146:                         $key = array_search($c_option, $c_option->container->optionList);
147:                         unset($c_option->container->optionList[$key]);
148:                     }
149:                 }
150:             }
151:         }
152:     }
153: 
154:     public function addOption()
155:     {
156:         $opts = func_get_args();
157: 
158:         if (count($opts) && is_string($opts[0])) {
159:             $optionFactory = new ReflectionClass($this->optionClass);
160:             $option = $optionFactory->newInstanceArgs($opts);
161:         } elseif (count($opts) == 1) {
162:             $option = $opts[0];
163:             if (!$option instanceof Horde_Argv_Option)
164:                 throw new InvalidArgumentException('not an Option instance: ' . var_export($option, true));
165:         } else {
166:             throw new InvalidArgumentException('invalid arguments');
167:         }
168: 
169:         $this->_checkConflict($option);
170: 
171:         $this->optionList[] = $option;
172:         $option->container = $this;
173:         foreach ($option->shortOpts as $opt) {
174:             $this->shortOpt[$opt] = $option;
175:         }
176:         foreach ($option->longOpts as $opt) {
177:             $this->longOpt[$opt] = $option;
178:         }
179: 
180:         if (!is_null($option->dest)) {
181:             // option has a dest, we need a default
182:             if ($option->default !== Horde_Argv_Option::$NO_DEFAULT) {
183:                 $this->defaults[$option->dest] = $option->default;
184:             } elseif (!isset($this->defaults[$option->dest])) {
185:                 $this->defaults[$option->dest] = null;
186:             }
187:         }
188: 
189:         return $option;
190:     }
191: 
192:     public function addOptions($optionList)
193:     {
194:         foreach ($optionList as $option) {
195:             $this->addOption($option);
196:         }
197:     }
198: 
199:     // -- Option query/removal methods ----------------------------------
200: 
201:     public function getOption($opt_str)
202:     {
203:         if (isset($this->shortOpt[$opt_str])) {
204:             return $this->shortOpt[$opt_str];
205:         } elseif (isset($this->longOpt[$opt_str])) {
206:             return $this->longOpt[$opt_str];
207:         } else {
208:             return null;
209:         }
210:     }
211: 
212:     public function hasOption($opt_str)
213:     {
214:         return isset($this->shortOpt[$opt_str])
215:             || isset($this->longOpt[$opt_str]);
216:     }
217: 
218:     public function removeOption($opt_str)
219:     {
220:         $option = $this->getOption($opt_str);
221:         if (is_null($option)) {
222:             throw new InvalidArgumentException("no such option '$opt_str'");
223:         }
224: 
225:         foreach ($option->shortOpts as $opt) {
226:             unset($this->shortOpt[$opt]);
227:         }
228:         foreach ($option->longOpts as $opt) {
229:             unset($this->longOpt[$opt]);
230:         }
231:         $key = array_search($option, $option->container->optionList);
232:         unset($option->container->optionList[$key]);
233:     }
234: 
235: 
236:     // -- Help-formatting methods ---------------------------------------
237: 
238:     public function formatOptionHelp($formatter = null)
239:     {
240:         if (!$this->optionList)
241:             return '';
242:         $result = array();
243:         foreach ($this->optionList as $option) {
244:             if ($option->help != Horde_Argv_Option::SUPPRESS_HELP)
245:                 $result[] = $formatter->formatOption($option);
246:         }
247:         return implode('', $result);
248:     }
249: 
250:     public function formatDescription($formatter = null)
251:     {
252:         return $formatter->formatDescription($this->getDescription());
253:     }
254: 
255:     public function formatHelp($formatter = null)
256:     {
257:         $result = array();
258:         if ($this->description)
259:             $result[] = $this->formatDescription($formatter);
260:         if ($this->optionList)
261:             $result[] = $this->formatOptionHelp($formatter);
262:         return implode("\n", $result);
263:     }
264: 
265: }
266: 
API documentation generated by ApiGen