Arg.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. namespace MrClay\Cli;
  3. use BadMethodCallException;
  4. /**
  5. * An argument for a CLI app. This specifies the argument, what values it expects and
  6. * how it's treated during validation.
  7. *
  8. * By default, the argument will be assumed to be an optional letter flag with no value following.
  9. *
  10. * If the argument may receive a value, call mayHaveValue(). If there's whitespace after the
  11. * flag, the value will be returned as true instead of the string.
  12. *
  13. * If the argument MUST be accompanied by a value, call mustHaveValue(). In this case, whitespace
  14. * is permitted between the flag and its value.
  15. *
  16. * Use assertFile() or assertDir() to indicate that the argument must return a string value
  17. * specifying a file or directory. During validation, the value will be resolved to a
  18. * full file/dir path (not necessarily existing!) and the original value will be accessible
  19. * via a "*.raw" key. E.g. $cli->values['f.raw']
  20. *
  21. * Use assertReadable()/assertWritable() to cause the validator to test the file/dir for
  22. * read/write permissions respectively.
  23. *
  24. * @method \MrClay\Cli\Arg mayHaveValue() Assert that the argument, if present, may receive a string value
  25. * @method \MrClay\Cli\Arg mustHaveValue() Assert that the argument, if present, must receive a string value
  26. * @method \MrClay\Cli\Arg assertFile() Assert that the argument's value must specify a file
  27. * @method \MrClay\Cli\Arg assertDir() Assert that the argument's value must specify a directory
  28. * @method \MrClay\Cli\Arg assertReadable() Assert that the specified file/dir must be readable
  29. * @method \MrClay\Cli\Arg assertWritable() Assert that the specified file/dir must be writable
  30. *
  31. * @property-read bool mayHaveValue
  32. * @property-read bool mustHaveValue
  33. * @property-read bool assertFile
  34. * @property-read bool assertDir
  35. * @property-read bool assertReadable
  36. * @property-read bool assertWritable
  37. * @property-read bool useAsInfile
  38. * @property-read bool useAsOutfile
  39. *
  40. * @author Steve Clay <steve@mrclay.org>
  41. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  42. */
  43. class Arg {
  44. /**
  45. * @return array
  46. */
  47. public function getDefaultSpec()
  48. {
  49. return array(
  50. 'mayHaveValue' => false,
  51. 'mustHaveValue' => false,
  52. 'assertFile' => false,
  53. 'assertDir' => false,
  54. 'assertReadable' => false,
  55. 'assertWritable' => false,
  56. 'useAsInfile' => false,
  57. 'useAsOutfile' => false,
  58. );
  59. }
  60. /**
  61. * @var array
  62. */
  63. protected $spec = array();
  64. /**
  65. * @var bool
  66. */
  67. protected $required = false;
  68. /**
  69. * @var string
  70. */
  71. protected $description = '';
  72. /**
  73. * @param bool $isRequired
  74. */
  75. public function __construct($isRequired = false)
  76. {
  77. $this->spec = $this->getDefaultSpec();
  78. $this->required = (bool) $isRequired;
  79. if ($isRequired) {
  80. $this->spec['mustHaveValue'] = true;
  81. }
  82. }
  83. /**
  84. * Assert that the argument's value points to a writable file. When
  85. * Cli::openOutput() is called, a write pointer to this file will
  86. * be provided.
  87. * @return Arg
  88. */
  89. public function useAsOutfile()
  90. {
  91. $this->spec['useAsOutfile'] = true;
  92. return $this->assertFile()->assertWritable();
  93. }
  94. /**
  95. * Assert that the argument's value points to a readable file. When
  96. * Cli::openInput() is called, a read pointer to this file will
  97. * be provided.
  98. * @return Arg
  99. */
  100. public function useAsInfile()
  101. {
  102. $this->spec['useAsInfile'] = true;
  103. return $this->assertFile()->assertReadable();
  104. }
  105. /**
  106. * @return array
  107. */
  108. public function getSpec()
  109. {
  110. return $this->spec;
  111. }
  112. /**
  113. * @param string $desc
  114. * @return Arg
  115. */
  116. public function setDescription($desc)
  117. {
  118. $this->description = $desc;
  119. return $this;
  120. }
  121. /**
  122. * @return string
  123. */
  124. public function getDescription()
  125. {
  126. return $this->description;
  127. }
  128. /**
  129. * @return bool
  130. */
  131. public function isRequired()
  132. {
  133. return $this->required;
  134. }
  135. /**
  136. * Note: magic methods declared in class PHPDOC
  137. *
  138. * @param string $name
  139. * @param array $args
  140. * @return Arg
  141. * @throws BadMethodCallException
  142. */
  143. public function __call($name, array $args = array())
  144. {
  145. if (array_key_exists($name, $this->spec)) {
  146. $this->spec[$name] = true;
  147. if ($name === 'assertFile' || $name === 'assertDir') {
  148. $this->spec['mustHaveValue'] = true;
  149. }
  150. } else {
  151. throw new BadMethodCallException('Method does not exist');
  152. }
  153. return $this;
  154. }
  155. /**
  156. * Note: magic properties declared in class PHPDOC
  157. *
  158. * @param string $name
  159. * @return bool|null
  160. */
  161. public function __get($name)
  162. {
  163. if (array_key_exists($name, $this->spec)) {
  164. return $this->spec[$name];
  165. }
  166. return null;
  167. }
  168. }