11ff764c21aa090e09794f68015676095e6b0a62
[yaffs-website] / vendor / consolidation / robo / src / Task / ApiGen / ApiGen.php
1 <?php
2 namespace Robo\Task\ApiGen;
3
4 use Robo\Contract\CommandInterface;
5 use Robo\Exception\TaskException;
6 use Robo\Task\BaseTask;
7 use Traversable;
8
9 /**
10  * Executes ApiGen command to generate documentation
11  *
12  * ``` php
13  * <?php
14  * // ApiGen Command
15  * $this->taskApiGen('./vendor/apigen/apigen.phar')
16  *      ->config('./apigen.neon')
17  *      ->templateConfig('vendor/apigen/apigen/templates/bootstrap/config.neon')
18  *      ->wipeout(true)
19  *       ->run();
20  * ?>
21  * ```
22  */
23 class ApiGen extends BaseTask implements CommandInterface
24 {
25     use \Robo\Common\ExecOneCommand;
26
27     const BOOL_NO = 'no';
28     const BOOL_YES = 'yes';
29
30     /**
31      * @var string
32      */
33     protected $command;
34     protected $operation = 'generate';
35
36     /**
37      * @param null|string $pathToApiGen
38      *
39      * @throws \Robo\Exception\TaskException
40      */
41     public function __construct($pathToApiGen = null)
42     {
43         $this->command = $pathToApiGen;
44         $command_parts = [];
45         preg_match('/((?:.+)?apigen(?:\.phar)?) ?( \w+)? ?(.+)?/', $this->command, $command_parts);
46         if (count($command_parts) === 3) {
47             list(, $this->command, $this->operation) = $command_parts;
48         }
49         if (count($command_parts) === 4) {
50             list(, $this->command, $this->operation, $arg) = $command_parts;
51             $this->arg($arg);
52         }
53         if (!$this->command) {
54             $this->command = $this->findExecutablePhar('apigen');
55         }
56         if (!$this->command) {
57             throw new TaskException(__CLASS__, "No apigen installation found");
58         }
59     }
60
61     /**
62      * Pass methods parameters as arguments to executable. Argument values
63      * are automatically escaped.
64      *
65      * @param string|string[] $args
66      *
67      * @return $this
68      */
69     public function args($args)
70     {
71         if (!is_array($args)) {
72             $args = func_get_args();
73         }
74         $args = array_map(function ($arg) {
75             if (preg_match('/^\w+$/', trim($arg)) === 1) {
76                 $this->operation = $arg;
77                 return null;
78             }
79             return $arg;
80         }, $args);
81         $args = array_filter($args);
82         $this->arguments .= ' ' . implode(' ', array_map('static::escape', $args));
83         return $this;
84     }
85
86     /**
87      * @param array|Traversable|string $arg a single object or something traversable
88      *
89      * @return array|Traversable the provided argument if it was already traversable, or the given
90      *                           argument returned as a one-element array
91      */
92     protected static function forceTraversable($arg)
93     {
94         $traversable = $arg;
95         if (!is_array($traversable) && !($traversable instanceof \Traversable)) {
96             $traversable = array($traversable);
97         }
98         return $traversable;
99     }
100
101     /**
102      * @param array|string $arg a single argument or an array of multiple string values
103      *
104      * @return string a comma-separated string of all of the provided arguments, suitable
105      *                as a command-line "list" type argument for ApiGen
106      */
107     protected static function asList($arg)
108     {
109         $normalized = is_array($arg) ? $arg : array($arg);
110         return implode(',', $normalized);
111     }
112
113     /**
114      * @param bool|string $val an argument to be normalized
115      * @param string $default one of self::BOOL_YES or self::BOOK_NO if the provided
116      *               value could not deterministically be converted to a
117      *               yes or no value
118      *
119      * @return string the given value as a command-line "yes|no" type of argument for ApiGen,
120      *                or the default value if none could be determined
121      */
122     protected static function asTextBool($val, $default)
123     {
124         if ($val === self::BOOL_YES || $val === self::BOOL_NO) {
125             return $val;
126         }
127         if (!$val) {
128             return self::BOOL_NO;
129         }
130         if ($val === true) {
131             return self::BOOL_YES;
132         }
133         if (is_numeric($val) && $val != 0) {
134             return self::BOOL_YES;
135         }
136         if (strcasecmp($val[0], 'y') === 0) {
137             return self::BOOL_YES;
138         }
139         if (strcasecmp($val[0], 'n') === 0) {
140             return self::BOOL_NO;
141         }
142         // meh, good enough, let apigen sort it out
143         return $default;
144     }
145
146     /**
147      * @param string $config
148      *
149      * @return $this
150      */
151     public function config($config)
152     {
153         $this->option('config', $config);
154         return $this;
155     }
156
157     /**
158      * @param array|string|Traversable $src one or more source values
159      *
160      * @return $this
161      */
162     public function source($src)
163     {
164         foreach (self::forceTraversable($src) as $source) {
165             $this->option('source', $source);
166         }
167         return $this;
168     }
169
170     /**
171      * @param string $dest
172      *
173      * @return $this
174      */
175     public function destination($dest)
176     {
177         $this->option('destination', $dest);
178         return $this;
179     }
180
181     /**
182      * @param array|string $exts one or more extensions
183      *
184      * @return $this
185      */
186     public function extensions($exts)
187     {
188         $this->option('extensions', self::asList($exts));
189         return $this;
190     }
191
192     /**
193      * @param array|string $exclude one or more exclusions
194      *
195      * @return $this
196      */
197     public function exclude($exclude)
198     {
199         foreach (self::forceTraversable($exclude) as $excl) {
200             $this->option('exclude', $excl);
201         }
202         return $this;
203     }
204
205     /**
206      * @param array|string|Traversable $path one or more skip-doc-path values
207      *
208      * @return $this
209      */
210     public function skipDocPath($path)
211     {
212         foreach (self::forceTraversable($path) as $skip) {
213             $this->option('skip-doc-path', $skip);
214         }
215         return $this;
216     }
217
218     /**
219      * @param array|string|Traversable $prefix one or more skip-doc-prefix values
220      *
221      * @return $this
222      */
223     public function skipDocPrefix($prefix)
224     {
225         foreach (self::forceTraversable($prefix) as $skip) {
226             $this->option('skip-doc-prefix', $skip);
227         }
228         return $this;
229     }
230
231     /**
232      * @param array|string $charset one or more charsets
233      *
234      * @return $this
235      */
236     public function charset($charset)
237     {
238         $this->option('charset', self::asList($charset));
239         return $this;
240     }
241
242     /**
243      * @param string $name
244      *
245      * @return $this
246      */
247     public function mainProjectNamePrefix($name)
248     {
249         $this->option('main', $name);
250         return $this;
251     }
252
253     /**
254      * @param string $title
255      *
256      * @return $this
257      */
258     public function title($title)
259     {
260         $this->option('title', $title);
261         return $this;
262     }
263
264     /**
265      * @param string $baseUrl
266      *
267      * @return $this
268      */
269     public function baseUrl($baseUrl)
270     {
271         $this->option('base-url', $baseUrl);
272         return $this;
273     }
274
275     /**
276      * @param string $id
277      *
278      * @return $this
279      */
280     public function googleCseId($id)
281     {
282         $this->option('google-cse-id', $id);
283         return $this;
284     }
285
286     /**
287      * @param string $trackingCode
288      *
289      * @return $this
290      */
291     public function googleAnalytics($trackingCode)
292     {
293         $this->option('google-analytics', $trackingCode);
294         return $this;
295     }
296
297     /**
298      * @param mixed $templateConfig
299      *
300      * @return $this
301      */
302     public function templateConfig($templateConfig)
303     {
304         $this->option('template-config', $templateConfig);
305         return $this;
306     }
307
308     /**
309      * @param array|string $tags one or more supported html tags
310      *
311      * @return $this
312      */
313     public function allowedHtml($tags)
314     {
315         $this->option('allowed-html', self::asList($tags));
316         return $this;
317     }
318
319     /**
320      * @param string $groups
321      *
322      * @return $this
323      */
324     public function groups($groups)
325     {
326         $this->option('groups', $groups);
327         return $this;
328     }
329
330     /**
331      * @param array|string $types or more supported autocomplete types
332      *
333      * @return $this
334      */
335     public function autocomplete($types)
336     {
337         $this->option('autocomplete', self::asList($types));
338         return $this;
339     }
340
341     /**
342      * @param array|string $levels one or more access levels
343      *
344      * @return $this
345      */
346     public function accessLevels($levels)
347     {
348         $this->option('access-levels', self::asList($levels));
349         return $this;
350     }
351
352     /**
353      * @param boolean|string $internal 'yes' or true if internal, 'no' or false if not
354      *
355      * @return $this
356      */
357     public function internal($internal)
358     {
359         $this->option('internal', self::asTextBool($internal, self::BOOL_NO));
360         return $this;
361     }
362
363     /**
364      * @param boolean|string $php 'yes' or true to generate documentation for internal php classes,
365      *                            'no' or false otherwise
366      *
367      * @return $this
368      */
369     public function php($php)
370     {
371         $this->option('php', self::asTextBool($php, self::BOOL_YES));
372         return $this;
373     }
374
375     /**
376      * @param bool|string $tree 'yes' or true to generate a tree view of classes, 'no' or false otherwise
377      *
378      * @return $this
379      */
380     public function tree($tree)
381     {
382         $this->option('tree', self::asTextBool($tree, self::BOOL_YES));
383         return $this;
384     }
385
386     /**
387      * @param bool|string $dep 'yes' or true to generate documentation for deprecated classes, 'no' or false otherwise
388      *
389      * @return $this
390      */
391     public function deprecated($dep)
392     {
393         $this->option('deprecated', self::asTextBool($dep, self::BOOL_NO));
394         return $this;
395     }
396
397     /**
398      * @param bool|string $todo 'yes' or true to document tasks, 'no' or false otherwise
399      *
400      * @return $this
401      */
402     public function todo($todo)
403     {
404         $this->option('todo', self::asTextBool($todo, self::BOOL_NO));
405         return $this;
406     }
407
408     /**
409      * @param bool|string $src 'yes' or true to generate highlighted source code, 'no' or false otherwise
410      *
411      * @return $this
412      */
413     public function sourceCode($src)
414     {
415         $this->option('source-code', self::asTextBool($src, self::BOOL_YES));
416         return $this;
417     }
418
419     /**
420      * @param bool|string $zipped 'yes' or true to generate downloadable documentation, 'no' or false otherwise
421      *
422      * @return $this
423      */
424     public function download($zipped)
425     {
426         $this->option('download', self::asTextBool($zipped, self::BOOL_NO));
427         return $this;
428     }
429
430     public function report($path)
431     {
432         $this->option('report', $path);
433         return $this;
434     }
435
436     /**
437      * @param bool|string $wipeout 'yes' or true to clear out the destination directory, 'no' or false otherwise
438      *
439      * @return $this
440      */
441     public function wipeout($wipeout)
442     {
443         $this->option('wipeout', self::asTextBool($wipeout, self::BOOL_YES));
444         return $this;
445     }
446
447     /**
448      * @param bool|string $quiet 'yes' or true for quiet, 'no' or false otherwise
449      *
450      * @return $this
451      */
452     public function quiet($quiet)
453     {
454         $this->option('quiet', self::asTextBool($quiet, self::BOOL_NO));
455         return $this;
456     }
457
458     /**
459      * @param bool|string $bar 'yes' or true to display a progress bar, 'no' or false otherwise
460      *
461      * @return $this
462      */
463     public function progressbar($bar)
464     {
465         $this->option('progressbar', self::asTextBool($bar, self::BOOL_YES));
466         return $this;
467     }
468
469     /**
470      * @param bool|string $colors 'yes' or true colorize the output, 'no' or false otherwise
471      *
472      * @return $this
473      */
474     public function colors($colors)
475     {
476         $this->option('colors', self::asTextBool($colors, self::BOOL_YES));
477         return $this;
478     }
479
480     /**
481      * @param bool|string $check 'yes' or true to check for updates, 'no' or false otherwise
482      *
483      * @return $this
484      */
485     public function updateCheck($check)
486     {
487         $this->option('update-check', self::asTextBool($check, self::BOOL_YES));
488         return $this;
489     }
490
491     /**
492      * @param bool|string $debug 'yes' or true to enable debug mode, 'no' or false otherwise
493      *
494      * @return $this
495      */
496     public function debug($debug)
497     {
498         $this->option('debug', self::asTextBool($debug, self::BOOL_NO));
499         return $this;
500     }
501
502     /**
503      * {@inheritdoc}
504      */
505     public function getCommand()
506     {
507         return "$this->command $this->operation$this->arguments";
508     }
509
510     /**
511      * {@inheritdoc}
512      */
513     public function run()
514     {
515         $this->printTaskInfo('Running ApiGen {args}', ['args' => $this->arguments]);
516         return $this->executeCommand($this->getCommand());
517     }
518 }