Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.ApiUsage.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 namespace {
7  /**
8  * Verify arguments for wsh programs
9  *
10  * @class ApiUsage
11  * @brief Verify arguments for wsh programs
12  * @code
13  $usage = new ApiUsage();
14  $usage->setDescriptionText("Refresh documents ");
15  $usage->addRequiredParameter("famid", "the family filter");
16  $usage->addOptionalParameter("revision", "use all revision - default is no", array(
17  "yes",
18  "no"
19  ));
20  $usage->addOptionalParameter("save", "use modify default is light", array(
21  "complete",
22  "light",
23  "none"
24  ));
25  $usage->verify();
26  * @endcode
27  */
28  class ApiUsage
29  {
30  const THROW_EXITHELP = 1988;
31  const GET_USAGE = null;
32  /**
33  * usage text
34  *
35  * @var string
36  */
37  private $text = '';
38  /**
39  * optionals arguments
40  *
41  * @var array
42  */
43  private $optArgs = array();
44  /**
45  * empty arguments
46  *
47  * @var array
48  */
49  private $emptyArgs = array();
50  /**
51  * needed arguments
52  *
53  * @var array
54  */
55  private $needArgs = array();
56  /**
57  * hidden arguments
58  *
59  * @var array
60  */
61  private $hiddenArgs = array();
62  /**
63  * current action
64  *
65  * @var Action
66  */
67  protected $action;
68  /**
69  * strict mode
70  *
71  * @var boolean
72  */
73  protected $strict = true;
74  /**
75  * force throw exception when verify fail instead of exitError
76  *
77  * @var boolean
78  */
79  protected $useException = false;
80  /**
81  * init action
82  */
83  public function __construct()
84  {
85  global $action;
86  $this->action = & $action;
87  $this->addHiddenParameter("api", "api file to use");
88  $this->addOptionalParameter('userid', "user system id or login name to execute function - default is (admin)", null, 1);
89  $this->addEmptyParameter('help', "Show usage");
90  }
91  /**
92  * Restriction callback to verify a scalar value
93  * @param string $argVal argument value
94  * @param string $argName argument name
95  * @param ApiUsage $apiUsage current apiUsage object
96  * @return string
97  */
98  public static function isScalar($argVal, $argName, $apiUsage)
99  {
100  $err = "";
101  if (!is_scalar($argVal)) {
102  if (is_array($argVal)) {
103  if (!isset($_FILES[$argName])) {
104  $err = sprintf("Argument doesn't support multiple value (values got are [%s])", implode(",", $argVal));
105  }
106  } else $err = sprintf("Value type %s isn't authorized for argument, must be a scalar", gettype($argVal));
107  }
108  return $err;
109  }
110  /**
111  * Restriction callback to verify an array value
112  * @param string $argVal argument value
113  * @param string $argName argument name
114  * @param ApiUsage $apiUsage current apiUsage object
115  * @return string
116  */
117  public static function isArray($argVal, $argName, $apiUsage)
118  {
119  $err = "";
120  if (!is_array($argVal)) {
121  $err = sprintf("Value type %s isn't authorized for argument, must be an array", gettype($argVal));
122  }
123  return $err;
124  }
125  /**
126  * add textual definition of program
127  *
128  * @see setDefinitionText
129  * @param string $text usage text
130  * @deprecated use { @link ApiUsage::setDefinitionText } instead
131  * @return void setText
132  */
133  public function setText($text)
134  {
136  $this->setDefinitionText($text);
137  }
138  /**
139  * add textual definition of program
140  *
141  * @api add textual definition of program
142  * @param string $text usage text
143  *
144  * @return void
145  */
146  public function setDefinitionText($text)
147  {
148  $this->text = $text;
149  }
150  /**
151  * add hidden argument (private arg not see them in usage)
152  *
153  * @see ApiUsage::addHiddenParameter
154  *
155  * @deprecated use { @link ApiUsage::addHiddenParameter } instead
156  *
157  * @param string $argName argument name
158  * @param string $argDefinition argument définition
159  *
160  * @return string argument value
161  */
162  public function addHidden($argName, $argDefinition)
163  {
165  return $this->addHiddenParameter($argName, $argDefinition);
166  }
167  /**
168  * add hidden argument (private arg not see them in usage)
169  *
170  * @api add an empty parameter
171  *
172  * @param string $argName argument name
173  * @param string $argDefinition argument définition
174  *
175  * @return string argument value
176  */
177  public function addHiddenParameter($argName, $argDefinition)
178  {
179  $this->hiddenArgs[] = array(
180  "name" => $argName,
181  "def" => $argDefinition
182  );
183  return $this->getArgumentValue($argName);
184  }
185  /**
186  * add needed argument
187  *
188  * @see ApiUsage::addRequiredParameter
189  *
190  * @deprecated use { @link ApiUsage::addRequiredParameter } instead
191  *
192  * @param string $argName argument name
193  * @param string $argDefinition argument définition
194  * @param array $restriction optional enumeration for argument
195  *
196  * @return string argument value
197  */
198  public function addNeeded($argName, $argDefinition, array $restriction = null)
199  {
201  return $this->addRequiredParameter($argName, $argDefinition, $restriction);
202  }
203  /**
204  * add needed argument
205  *
206  * @api add needed argument
207  *
208  * @param string $argName argument name
209  * @param string $argDefinition argument définition
210  * @param array|callable $restriction optional enumeration for argument
211  *
212  * @return string argument value
213  */
214  public function addRequiredParameter($argName, $argDefinition, $restriction = null)
215  {
216  $this->needArgs[] = array(
217  "name" => $argName,
218  "def" => $argDefinition,
219  "default" => null,
220  "restriction" => $restriction
221  );
222  return $this->getArgumentValue($argName);
223  }
224  /**
225  * add optional argument
226  *
227  * @see ApiUsage::addOptionParameter
228  *
229  * @deprecated use { @link ApiUsage::addOptionParameter } instead
230  * @param string $argName argument name
231  * @param string $argDefinition argument définition
232  * @param array $restriction optional enumeration for argument
233  * @param string $default default value if no value set
234  *
235  * @return string argument value
236  */
237  public function addOption($argName, $argDefinition, array $restriction = null, $default = null)
238  {
240  return $this->addOptionalParameter($argName, $argDefinition, $restriction, $default);
241  }
242  /**
243  * add optional argument
244  *
245  * @api add optional argument
246  *
247  * @param string $argName argument name
248  * @param string $argDefinition argument definition
249  * @param array|callable $restriction optional enumeration for argument
250  * @param string $default default value if no value set
251  *
252  * @return string argument value
253  */
254  public function addOptionalParameter($argName, $argDefinition, $restriction = null, $default = null)
255  {
256  $this->optArgs[] = array(
257  "name" => $argName,
258  "def" => $argDefinition,
259  "default" => $default,
260  "restriction" => $restriction
261  );
262  return $this->getArgumentValue($argName, $default);
263  }
264  /**
265  * add empty argument (argument with boolean value)
266  *
267  * @see ApiUsage::addEmptyParameter
268  *
269  * @deprecated use { @link ApiUsage::addEmptyParameter } instead
270  *
271  * @param string $argName argument name
272  * @param string $argDefinition argument definition
273  *
274  * @return string argument value
275  */
276  public function addEmpty($argName, $argDefinition = "")
277  {
279  return $this->addEmptyParameter($argName, $argDefinition);
280  }
281  /**
282  * add empty argument (argument with boolean value)
283  *
284  * @api add empty argument (argument with boolean value)
285  *
286  * @param string $argName argument name
287  * @param string $argDefinition argument definition
288  *
289  * @return string argument value
290  */
291  public function addEmptyParameter($argName, $argDefinition = "")
292  {
293  $this->emptyArgs[] = array(
294  "name" => $argName,
295  "def" => $argDefinition,
296  "default" => null,
297  "restriction" => null
298  );
299  return $this->getArgumentValue($argName, false);
300  }
301  /**
302  * Return value of argument key
303  * @param string $key the identifier
304  * @param string $defaultValue value to return if value is empty
305  * @return mixed|string
306  */
307  protected function getArgumentValue($key, $defaultValue = '')
308  {
309  return $this->action->getArgument($key, $defaultValue);
310  }
311  /**
312  * get usage for a specific argument
313  *
314  * @param array $args argument
315  * @param bool $empty flag to see if argument array as values or not
316  *
317  * @return string
318  */
319  private function getArgumentText(array $args, $empty = false)
320  {
321  $usage = '';
322  foreach ($args as $arg) {
323  $res = '';
324 
325  if ($this->isCallable($arg["restriction"])) {
326  $res = call_user_func($arg["restriction"], \ApiUsage::GET_USAGE, $arg["name"], $this);
327  } elseif (!empty($arg["restriction"]) && is_array($arg["restriction"])) {
328  $res = ' [' . implode('|', $arg["restriction"]) . ']';
329  }
330  $default = "";
331  if ($arg["default"] !== null) {
332  $default = sprintf(", default is '%s'", print_r($arg["default"], true));
333  }
334  $string = "\t--" . $arg["name"] . ($empty ? " (%s) " : "=<%s>");
335 
336  $usage.= sprintf("$string%s%s\n", $arg["def"], $res, $default);
337  }
338  return $usage;
339  }
340 
341  protected function isCallable($f)
342  {
343  if (empty($f)) {
344  return false;
345  }
346  if (!is_callable($f, true)) {
347  return false;
348  }
349  if (is_object($f) && ($f instanceof Closure)) {
350  return true;
351  }
352  if (is_array($f) && (is_scalar($f[0]))) {
353  return false;
354  }
355  if (is_callable($f, false)) { // many many time to search
356  return true;
357  }
358 
359  return false;
360  }
361  /**
362  * return usage text for the action
363  *
364  * @return string
365  */
366  public function getUsage()
367  {
368  $usage = $this->text;
369  $usage.= "\nUsage :\n";
370  $usage.= $this->getArgumentText($this->needArgs);
371  $usage.= " Options:\n";
372  $usage.= $this->getArgumentText($this->optArgs);
373  $usage.= $this->getArgumentText($this->emptyArgs, true);
374  return $usage;
375  }
376  /**
377  * exit when error
378  *
379  * @param string $error message error
380  * @throws Dcp\ApiUsage\Exception
381  * @return void
382  */
383  public function exitError($error = '')
384  {
385  if ($error != '') $error.= "\n";
386  $usage = $this->getUsage();
387 
388  if (!$this->useException) {
389  if (!empty($_SERVER['HTTP_HOST'])) {
390  $usage = str_replace('--', '&', $usage);
391  $error.= '<pre>' . htmlspecialchars($usage) . '</pre>';
392  } else {
393  $error.= $usage;
394  }
395  if ($this->getArgumentValue("help") == true) {
396  throw new \Dcp\ApiUsage\Exception("CORE0003", $error, $usage);
397  }
398  if (!empty($_SERVER['HTTP_HOST'])) {
399  $this->action->exitError($error);
400  } else {
401 
402  throw new \Dcp\ApiUsage\Exception("CORE0002", $error, $usage);
403  }
404  } else {
405  // no usage when use exception mode
406  throw new \Dcp\ApiUsage\Exception("CORE0002", $error, $usage);
407  }
408  }
409  /**
410  * list hidden keys
411  *
412  * @return array
413  */
414  protected function getHiddenKeys()
415  {
416  $keys = array();
417  foreach ($this->hiddenArgs as $v) {
418  $keys[] = $v["name"];
419  }
420  return $keys;
421  }
422  /**
423  * set strict mode
424  *
425  * @see ApiUsage::setStrictMode
426  *
427  * @deprecated use { @link Application::setStrictMode } instead
428  *
429  * @param boolean $strict strict mode
430  * @brief if false additionnal arguments are ignored, default is true
431  *
432  * @return void
433  */
434  public function strict($strict = true)
435  {
437  $this->setStrictMode($strict);
438  }
439  /**
440  * set strict mode
441  *
442  * @api set strict mode
443  *
444  * @param boolean $strict strict mode
445  * @brief if false additionnal arguments are ignored, default is true
446  *
447  * @return void
448  */
449  public function setStrictMode($strict = true)
450  {
451  $this->strict = $strict;
452  }
453  /**
454  * verify if wsh program argument are valids. If not wsh exit
455  *
456  * @api Verify if wsh's program arguments are valid
457  * @param bool $useException if true throw ApiUsageException when verify is not successful
458  *
459  * @return void
460  */
461  public function verify($useException = false)
462  {
463  $this->useException = $useException;
464  if ($this->getArgumentValue("help") == true) {
465  $this->exitError();
466  }
467  foreach ($this->needArgs as $arg) {
468  $value = $this->getArgumentValue($arg["name"]);
469  if ($value === '' || is_bool($value)) {
470  $error = sprintf("argument '%s' expected\n", $arg["name"]);
471 
472  $this->exitError($error);
473  }
474  }
475  $allArgs = array_merge($this->needArgs, $this->optArgs, $this->emptyArgs);
476  $argsKey = $this->getHiddenKeys();
477 
478  foreach ($allArgs as $arg) {
479  $value = $this->getArgumentValue($arg["name"], null);
480  if ($value !== null) {
481  if ($this->isCallable($arg["restriction"])) {
482  $error = call_user_func($arg["restriction"], $value, $arg["name"], $this);
483  } else {
484  $error = \ApiUsage::isScalar($value, $arg["name"], $this);
485  }
486  if ($error) $this->exitError(sprintf("Error checking argument \"%s\" : %s", $arg["name"], $error));
487 
488  if (is_array($arg["restriction"]) && !empty($arg["restriction"]) && !$this->isCallable($arg["restriction"])) {
489  $error = $this->matchValues($value, $arg["restriction"]);
490  if ($error) $this->exitError(sprintf("Error for argument '%s' : %s", $arg["name"], $error));
491  }
492  }
493  $argsKey[] = $arg["name"];
494  }
495  if ($this->strict) {
496  foreach ($_GET as $k => $v) {
497  if (!in_array($k, $argsKey)) {
498  $error = sprintf("argument '%s' is not defined\n", $k);
499 
500  $this->exitError($error);
501  }
502  }
503  }
504  }
505  /**
506  * @param $value
507  * @param $restrictions
508  * @return string
509  */
510  public static function matchValues($value, $restrictions)
511  {
512  $error = "";
513  $values = (!is_array($value)) ? array(
514  $value
515  ) : $value;
516  foreach ($values as $aValue) {
517  if (!in_array($aValue, $restrictions)) {
518  $error = sprintf("argument must be one of these values : %s\n", implode(", ", $restrictions));
519  }
520  }
521  return $error;
522  }
523  }
524 }
525 
526 namespace Dcp\ApiUsage
527 {
528  class Exception extends \Dcp\Exception
529  {
530  private $usage = '';
531 
532  public function __construct($code, $text, $usage = '')
533  {
534  parent::__construct($code, $text);
535  $this->usage = $usage;
536  }
537 
538  public function getUsage()
539  {
540  if ($this->usage) return $this->usage;
541  return null;
542  }
543  }
544 }
if(substr($wsh, 0, 1)!= '/') $args
addEmptyParameter($argName, $argDefinition="")
verify($useException=false)
Exception class use exceptionCode to identifiy correctly exception.
Definition: exceptions.php:19
addHidden($argName, $argDefinition)
exitError($error= '')
getArgumentValue($key, $defaultValue= '')
const THROW_EXITHELP
setStrictMode($strict=true)
if false additionnal arguments are ignored, default is true
const GET_USAGE
static isScalar($argVal, $argName, $apiUsage)
__construct($code, $text, $usage= '')
addOptionalParameter($argName, $argDefinition, $restriction=null, $default=null)
strict($strict=true)
if false additionnal arguments are ignored, default is true
setText($text)
addOption($argName, $argDefinition, array $restriction=null, $default=null)
global $_GET
Definition: wsh.php:37
usage()
setDefinitionText($text)
deprecatedFunction($msg= '')
Definition: Lib.Common.php:86
global $_SERVER
addHiddenParameter($argName, $argDefinition)
addEmpty($argName, $argDefinition="")
static matchValues($value, $restrictions)
if($file) if($subject==""&&$file) if($subject=="") $err
static isArray($argVal, $argName, $apiUsage)
addRequiredParameter($argName, $argDefinition, $restriction=null)
addNeeded($argName, $argDefinition, array $restriction=null)
$usage
$value
Verify arguments for wsh programs.
← centre documentaire © anakeen