Arg.php 4.9 KB

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