Argh::usageString()   B
last analyzed

Complexity

Conditions 10
Paths 20

Size

Total Lines 53
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 21
nc 20
nop 0
dl 0
loc 53
rs 7.6666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
	
3
/**
4
	* Argh.php
5
	*/ 
6
	
7
namespace netfocusinc\argh;
8
9
//
10
// CONVENIENCE DEFINITIONS
11
//
12
13
define('ARGH_TYPE_BOOLEAN', Parameter::ARGH_TYPE_BOOLEAN, true);
14
define('ARGH_TYPE_INT', Parameter::ARGH_TYPE_INT, true);
15
define('ARGH_TYPE_STRING', Parameter::ARGH_TYPE_STRING, true);
16
define('ARGH_TYPE_LIST', Parameter::ARGH_TYPE_LIST, true);
17
define('ARGH_TYPE_COMMAND', Parameter::ARGH_TYPE_COMMAND, true);
18
define('ARGH_TYPE_VARIABLE', Parameter::ARGH_TYPE_VARIABLE, true);
19
20
/**
21
	* Argument Helper
22
	* 
23
	* The main class to be used by clients for parsing command line arguments.
24
	*
25
	* @api
26
	*
27
	* @author  Benjamin Hough - Net Focus, Inc.
28
	*
29
	* @since 1.0.0
30
	*
31
	*/
32
class Argh
33
{
34
	
35
	//
36
	// PRIVATE PROPERTIES
37
	//
38
	
39
	/** @var array A copy of the $argv array, as registered by PHP CLI */
40
	private $argv = null;
41
	
42
	/** @var Language  A set of Rules used to interpret command line arguments */
43
	private $language = null; // Language
44
	
45
	/** @var ParameterCollection  A collection of Parameters supplied by clients */
46
	private $parameters = null;
47
	
48
	//
49
	// STATIC METHODS
50
	//
51
	
52
	/**
53
		* Create a new Argh instance and parses the arguments from $argv array
54
		*
55
		* This convenience method accepts both the PHP $argv array, and an array of Parameters used to interpret them.
56
		* After creating a new instance of Argh, the $argv array is interpreted against the specificed Parameters.
57
		*
58
		* @api
59
		*
60
		* @since 1.0.0
61
		*
62
		* @param array $argv
63
		* @param array $parameters Array of Parameters
64
		*
65
		* @return Argh
66
		*/
67
	public static function parse(array $argv, array $parameters) : Argh
68
	{
69
		$argh = new Argh($parameters);
70
		
71
		$argh->parseArguments($argv);
72
		
73
		return $argh;
74
	}
75
	
76
	/**
77
		* Create a new Argh instance and parses the arguments from $args string
78
		*
79
		* This convenience method accepts both a string of command line arguments, and an array of Parameters used to interpret them.
80
		* After creating a new instance of Argh, the $args string is interpreted against the specified Parameters.
81
		* 
82
		* @api
83
		*
84
		* @since 1.0.0
85
		*
86
		* @param string $args A string simulating command line entry
87
		* @param array $parameters Array of Parameters
88
		*
89
		* @return Argh
90
		*/
91
	public static function parseString(string $args, array $parameters) : Argh
92
	{
93
		// Force $args into an array
94
		$argv = explode(' ', $args);
95
		
96
		// Create a new Argh instance
97
		$argh = new Argh($parameters);
98
		
99
		// Parse
100
		$argh->parseArguments($argv);
101
		
102
		return $argh;
103
	}
104
	
105
	//
106
	// MAGIC METHODS
107
	//
108
109
	/** 
110
		* Magic method providing access to parameter values via object properties syntax
111
		*
112
		* Forward requests for undefined object properties to Argh->get() method
113
		*
114
		*	@internal
115
		* @since 1.0.0
116
		*		 
117
		* @param string $name The name (or flag) of a defined Parameter
118
		*
119
		* @return mixed The value of a Parameter (type depends on the Parameter's type)
120
		*/	
121
	public function __get(string $key)
122
	{
123
		// Get parameters from this instance
124
		return $this->get($key);
125
	}
126
	
127
	/**
128
		* Magic method checks if a parameter value has been set via object property syntax
129
		*
130
		* @internal
131
		* @since 1.0.0
132
		*
133
		* @param string $key The name (of flag) of a parameter
134
		*
135
		* @return boolean TRUE when the named parameter exists, otherwise FALSE
136
		*/
137
	public function __isset(string $key): bool
138
	{
139
		if( $this->parameters->exists($key) )
140
		{
141
			return TRUE;		
142
		}
143
		else
144
		{
145
			return FALSE;
146
		}
147
	}
148
	
149
	//
150
	// PUBLIC METHODS
151
	//
152
153
	/**
154
		* Contructs a new Argh instance
155
		*
156
		* Constructs a new instance of Argh with the specified Parameters.
157
		* The resulting Argh instance is ready to interpret command line arguments.
158
		* It is usually preferred to use Argh:parse() to create new Argh instances.
159
		* Direct contruction is only necessary if you want to re-use the same Argh instance
160
		* for parsing multiple sets of command line arguments. 
161
		*
162
		* @api
163
		*
164
		* @since 1.0.0
165
		*
166
		* @param array $parameters An array of Parameters to use for interpreting command line arguments
167
		*
168
		*/
169
	public function __construct(array $parameters)
170
	{ 
171
		// Init Language
172
		$this->language = Language::createWithRules();
173
		
174
		// Init ParameterCollection
175
		$this->parameters = new ParameterCollection();
176
		
177
		// Add Parameters to the ParameterCollection
178
		foreach($parameters as $p)
179
		{
180
			$this->parameters->addParameter($p);
181
		}
182
				
183
	} // END: public function __construct()
184
	
185
	/**
186
		* Interprets an array of command line arguments
187
		* 
188
		* Parses the given $argv array using this instances pre-defined set of Parameters
189
		*
190
		* @api
191
		*
192
		* @since 1.0.0
193
		*
194
		* @param array $argv An array of command line arguments to interpret
195
		*
196
		* @throws ArghException
197
		*/
198
	public function parseArguments(array $argv)
199
	{
200
		// Set properties on this object
201
		$this->argv = $argv;
202
		
203
		try
204
		{	
205
			// Prepare $argv for parsing
206
			$args = ArgvPreprocessor::process($this->argv);
207
			
208
			// Create an new ArgumentParser instance
209
			$parser = new ArgumentParser($this->language, $this->parameters);
210
			
211
			// Parse $args into an array of Arguments
212
			$arguments = $parser->parse($args);
213
			
214
			// Merge Arguments into Parameters
215
			$this->parameters->mergeArguments($arguments);
216
		}
217
		catch(ArghException $e)
218
		{
219
			throw $e;
220
		}
221
	}
222
223
	/**
224
		* Access elements of the original $argv array
225
		*
226
		* Provides access to the $argv array (and its elements) as registered by PHP CLI
227
		*
228
		*	@api
229
		*
230
		* @since 1.0.0
231
		*		 
232
		* @param int|null $i The index of an $argv element; or null to return the entire $argv array
233
		*
234
		* @return mixed The value of an element of the $argv array; or the entire $argv array (when param $i is null)
235
		* @throws ArghException if $i is not a valid index of $argv
236
		*/	
237
	public function argv(int $i=null)
238
	{
239
		if($i !== null)
240
		{
241
			if( array_key_exists($i, $this->argv) )
242
			{
243
				return $this->argv[$i];
244
			}
245
			else
246
			{
247
				throw new ArghException('Invalid index for argv');
248
			}
249
		}
250
		else
251
		{
252
			return $this->argv;
253
		}
254
	}
255
	
256
	/**
257
		* Retrieves the value of a defined Parameter.
258
		*
259
		* Find the value of an Parameter
260
		* Either the value of an Argument, if supplied on the command line,
261
		* or, the default value as defined by the arguments corresponding Parameter.
262
		*
263
		*	@api
264
		*
265
		* @since 1.0.0
266
		*		 
267
		* @param string $key The name (or flag) of a defined Parameter
268
		*
269
		* @return mixed The value of a Parameter (type depends on the Parameter's type)
270
		* @throws ArghException if the $key is not the name of a defined Parameter.
271
		*/
272
	public function get($key)
273
	{
274
		
275
		// Check the ParameterCollection for a Parameter with $key
276
		if( !$this->parameters->exists($key) )
277
		{
278
			throw new ArghException(__CLASS__ . ': Parameter \'' . $key . '\' was not defined.');
279
		}
280
	
281
		// Check if the Parameter has a value defined by an Argument
282
		
283
		//! TODO: Replace with Parameter::getValueOrDefault()
284
		
285
		if( $this->parameters->get($key)->getValue() )
286
		{
287
			// Return the Parameters value
288
			return $this->parameters->get($key)->getValue();
289
		}
290
		else
291
		{
292
			// Return the Parameters default value, if any
293
			return $this->parameters->get($key)->getDefault();
294
		}
295
	}
296
297
	/**
298
		* Retrieves any (unmarked) variables that were supplied as command line arguments.
299
		*
300
		* Variables are a type of Parameter that are unmarked (they have no name or flag).
301
		* To parse variables, a VariableParameter must be added when creating a new Argh instance.
302
		* This function is used to retrieve unmarked variables supplied as command line arguments.
303
		* Any variables will be returned as an array of values.
304
		*
305
		*	@api
306
		*
307
		* @since 1.0.0
308
		*		 
309
		* @param string $key The name (or flag) of a defined Parameter
310
		*
311
		* @return mixed An array of strings when variables are present, otherwise FALSE
312
		*/	
313
	public function variables()
314
	{
315
		if($this->parameters->hasVariable())
316
		{	
317
			return $this->parameters->get(Parameter::ARGH_NAME_VARIABLE)->getValue();
318
		}
319
		
320
		// No ARGH_TYPE_VARIABLE Parameters in ParameterCollection
321
		return FALSE;
322
	}
323
	
324
	/**
325
		* Retrieves the ParameterCollection maintained by this Argh instance.
326
		*
327
		* Variables are a type of Parameter that are unmarked (they have no name or flag).
328
		* To parse variables, a VariableParameter must be added when creating a new Argh instance.
329
		* This function is used to retrieve unmarked variables supplied as command line arguments.
330
		* Any variables will be returned as an array of values.
331
		*
332
		*	@api
333
		*
334
		* @since 1.0.0
335
		*		 
336
		* @param string $key The name (or flag) of a defined Parameter
337
		*
338
		* @return ParameterCollection A collection of Parameters maintained by Argh
339
		*/	
340
	public function parameters() : ParameterCollection { return $this->parameters; }
341
342
	/**
343
		* Creates a 'usage string' useful for describing the command line arguments accepted by your program.
344
		*
345
		* This method can be used to create a string of descriptive text that details the command line arguments your 
346
		* program accepts. This can be displayed to users when your program is invoked with a 'help' flag, or 
347
		* when invalid command line arguments are used.
348
		*
349
		*	@api
350
		*
351
		* @since 1.0.0
352
		*		 
353
		*
354
		* @return string Descriptive text that details the command line arguments accepted by your program.
355
		*/	
356
	public function usageString()
357
	{
358
		//! TODO: Accept a formatting string/array (e.g. ['-f', '--name', 'text'])
359
		
360
		$buff = 'Usage: ';
361
		$buff .= $this->argv(0) . "\n\n";
362
	
363
		// TODO: Sort the parameters by name
364
		
365
		// TODO: Determine the longest value of each parameter attribute, to make pretty columns
366
		
367
		// Show Commands
368
		foreach($this->parameters->all() as $p)
369
		{
370
			if($p->getParameterType() == ARGH_TYPE_COMMAND)
371
			{
372
				$buff .= 'COMMANDS:' . "\n";
373
				
374
				if($p->hasOptions())
375
				{
376
					foreach($p->getOptions() as $o)
377
					{
378
							$buff .= $o . "\n";
379
					} // END: foreach($p->options() as $o)
380
				} // END: if($p->hasOptions())
381
			} // END: if($p->type() == ARGH_TYPE_COMMAND)
382
		} // END: foreach($this->parameters->all() as $p)
383
		$buff .= "\n";
384
		
385
		$buff .= 'OPTIONS:' . "\n";
386
		foreach($this->parameters->all() as $p)
387
		{
388
			if( ($p->getParameterType() != ARGH_TYPE_COMMAND) && ($p->getParameterType() != ARGH_TYPE_VARIABLE) )
389
			{
390
				$buff .= '-' . $p->getFlag() . "\t" . $p->getName() . "\t" . $p->getDescription();
391
				
392
				if($p->hasOptions())
393
				{ 
394
					$buff .= "\t" . '[';
395
					foreach($p->getOptions() as $o)
396
					{
397
						$buff .= $o . ', ';
398
					}
399
					$buff = substr($buff, 0, -2); // remove trailing ', '
400
					$buff .= ']';
401
				}
402
				
403
				$buff .= "\n";
404
			}
405
406
		}
407
		
408
		return $buff;
409
	}
410
	
411
	/**
412
		* An alias of function usage()
413
		*
414
		*	@api
415
		*
416
		* @since 1.0.0
417
		*
418
		* @return string Descriptive text that details the command line arguments accepted by your program.
419
		*/	
420
	public function usage() { return $this->usageString(); }
421
	
422
}
423