These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of phpDocumentor. |
||
4 | * |
||
5 | * For the full copyright and license information, please view the LICENSE |
||
6 | * file that was distributed with this source code. |
||
7 | * |
||
8 | * @copyright 2010-2015 Mike van Riel<[email protected]> |
||
9 | * @license http://www.opensource.org/licenses/mit-license.php MIT |
||
10 | * @link http://phpdoc.org |
||
11 | */ |
||
12 | |||
13 | namespace phpDocumentor\Application\Console\Command; |
||
14 | |||
15 | use League\Event\Emitter; |
||
16 | use League\Tactician\CommandBus; |
||
17 | use phpDocumentor\Application\Configuration\ConfigurationFactory; |
||
18 | use phpDocumentor\DomainModel\Parse; |
||
19 | use phpDocumentor\DomainModel\Dsn; |
||
20 | use phpDocumentor\DomainModel\Parser\Documentation; |
||
21 | use phpDocumentor\DomainModel\Parser\DocumentationRepository; |
||
22 | use phpDocumentor\Infrastructure\FileSystemFactory; |
||
23 | use phpDocumentor\Infrastructure\Parser\Documentation\Api\FlySystemDefinition; |
||
24 | use phpDocumentor\DomainModel\Parser\ApiFileParsed; |
||
25 | use phpDocumentor\DomainModel\Parser\ApiParsingStarted; |
||
26 | use phpDocumentor\DomainModel\ConfigureCache; |
||
27 | use phpDocumentor\DomainModel\MergeConfigurationWithCommandLineOptions; |
||
28 | use phpDocumentor\DomainModel\Render; |
||
29 | use phpDocumentor\DomainModel\Parser\Version\DefinitionRepository; |
||
30 | use phpDocumentor\DomainModel\Renderer\RenderActionCompleted; |
||
31 | use phpDocumentor\DomainModel\Renderer\RenderingFinished; |
||
32 | use phpDocumentor\DomainModel\Renderer\RenderingStarted; |
||
33 | use Stash\Driver\FileSystem; |
||
34 | use Symfony\Component\Console\Command\Command; |
||
35 | use Symfony\Component\Console\Helper\HelperInterface; |
||
36 | use Symfony\Component\Console\Helper\ProgressBar; |
||
37 | use Symfony\Component\Console\Input\ArrayInput; |
||
38 | use Symfony\Component\Console\Input\InputArgument; |
||
39 | use Symfony\Component\Console\Input\InputInterface; |
||
40 | use Symfony\Component\Console\Input\InputOption; |
||
41 | use Symfony\Component\Console\Output\OutputInterface; |
||
42 | |||
43 | /** |
||
44 | * Parse and transform the given directory (-d|-f) to the given location (-t). |
||
45 | * |
||
46 | * phpDocumentor creates documentation from PHP source files. The simplest way |
||
47 | * to use it is: |
||
48 | * |
||
49 | * $ phpdoc run -d <directory to parse> -t <output directory> |
||
50 | * |
||
51 | * This will parse every file ending with .php, .php3 and .phtml in <directory |
||
52 | * to parse> and then output a HTML site containing easily readable documentation |
||
53 | * in <output directory>. |
||
54 | * |
||
55 | * phpDocumentor will try to look for a phpdoc.dist.xml or phpdoc.xml file in your |
||
56 | * current working directory and use that to override the default settings if |
||
57 | * present. In the configuration file can you specify the same settings (and |
||
58 | * more) as the command line provides. |
||
59 | */ |
||
60 | final class RunCommand extends Command |
||
61 | { |
||
62 | /** @var CommandBus */ |
||
63 | private $commandBus; |
||
64 | |||
65 | /** @var Emitter */ |
||
66 | private $emitter; |
||
67 | |||
68 | /** @var DefinitionRepository */ |
||
69 | private $definitionRepository; |
||
70 | |||
71 | /** @var DocumentationRepository */ |
||
72 | private $documentationRepository; |
||
73 | |||
74 | /** @var ConfigurationFactory */ |
||
75 | private $configurationFactory; |
||
76 | |||
77 | /** @var FileSystemFactory */ |
||
78 | private $fileSystemFactory; |
||
79 | |||
80 | /** |
||
81 | * Initializes the command with all necessary dependencies |
||
82 | * |
||
83 | * @param DefinitionRepository $definitionRepository |
||
84 | * @param DocumentationRepository $documentationRepository |
||
85 | * @param CommandBus $commandBus |
||
86 | * @param Emitter $emitter |
||
87 | * @param ConfigurationFactory $configurationFactory |
||
88 | * @param FileSystemFactory $fileSystemFactory |
||
89 | */ |
||
90 | public function __construct( |
||
91 | DefinitionRepository $definitionRepository, |
||
92 | DocumentationRepository $documentationRepository, |
||
93 | CommandBus $commandBus, |
||
94 | Emitter $emitter, |
||
95 | ConfigurationFactory $configurationFactory, |
||
96 | FileSystemFactory $fileSystemFactory |
||
97 | ) { |
||
98 | $this->commandBus = $commandBus; |
||
99 | $this->emitter = $emitter; |
||
100 | $this->definitionRepository = $definitionRepository; |
||
101 | $this->documentationRepository = $documentationRepository; |
||
102 | $this->configurationFactory = $configurationFactory; |
||
103 | $this->fileSystemFactory = $fileSystemFactory; |
||
104 | |||
105 | parent::__construct('project:run'); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Initializes this command and sets the name, description, options and |
||
110 | * arguments. |
||
111 | * |
||
112 | * @return void |
||
113 | */ |
||
114 | protected function configure() |
||
115 | { |
||
116 | $this |
||
117 | ->setAliases(array('run')) |
||
118 | ->setDescription( |
||
119 | 'Parses and transforms the given files to a specified location' |
||
120 | ) |
||
121 | ->setHelp( |
||
122 | <<<HELP |
||
123 | phpDocumentor creates documentation from PHP source files. The simplest way |
||
124 | to use it is: |
||
125 | |||
126 | <info>$ phpdoc run -d [directory to parse] -t [output directory]</info> |
||
127 | |||
128 | This will parse every file ending with .php, .php3 and .phtml in <directory |
||
129 | to parse> and then output a HTML site containing easily readable documentation |
||
130 | in <output directory>. |
||
131 | |||
132 | phpDocumentor will try to look for a phpdoc.dist.xml or phpdoc.xml file in your |
||
133 | current working directory and use that to override the default settings if |
||
134 | present. In the configuration file can you specify the same settings (and |
||
135 | more) as the command line provides. |
||
136 | |||
137 | <comment>Other commands</comment> |
||
138 | In addition to this command phpDocumentor also supports additional commands: |
||
139 | |||
140 | <comment>Available commands:</comment> |
||
141 | <info> help |
||
142 | list |
||
143 | parse |
||
144 | run |
||
145 | transform |
||
146 | <comment>project</comment> |
||
147 | project:parse |
||
148 | project:run |
||
149 | project:transform |
||
150 | <comment>template</comment> |
||
151 | template:generate |
||
152 | template:list |
||
153 | template:package</info> |
||
154 | |||
155 | You can get a more detailed listing of the commands using the <info>list</info> |
||
156 | command and get help by prepending the word <info>help</info> to the command |
||
157 | name. |
||
158 | HELP |
||
159 | ) |
||
160 | ->addOption( |
||
161 | 'target', |
||
162 | 't', |
||
163 | InputOption::VALUE_OPTIONAL, |
||
164 | 'Path where to store the generated output' |
||
165 | ) |
||
166 | ->addOption( |
||
167 | 'cache-folder', |
||
168 | null, |
||
169 | InputOption::VALUE_OPTIONAL, |
||
170 | 'Path where to store the cache files' |
||
171 | ) |
||
172 | ->addOption( |
||
173 | 'filename', |
||
174 | 'f', |
||
175 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||
176 | 'Comma-separated list of files to parse. The wildcards ? and * are supported' |
||
177 | ) |
||
178 | ->addOption( |
||
179 | 'directory', |
||
180 | 'd', |
||
181 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||
182 | 'Comma-separated list of directories to (recursively) parse' |
||
183 | ) |
||
184 | ->addOption( |
||
185 | 'encoding', |
||
186 | null, |
||
187 | InputOption::VALUE_OPTIONAL, |
||
188 | 'encoding to be used to interpret source files with' |
||
189 | ) |
||
190 | ->addOption( |
||
191 | 'extensions', |
||
192 | 'e', |
||
193 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||
194 | 'Comma-separated list of extensions to parse, defaults to php, php3 and phtml' |
||
195 | ) |
||
196 | ->addOption( |
||
197 | 'ignore', |
||
198 | 'i', |
||
199 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||
200 | 'Comma-separated list of file(s) and directories (relative to the source-code directory) that will be ' |
||
201 | . 'ignored. Wildcards * and ? are supported' |
||
202 | ) |
||
203 | ->addOption( |
||
204 | 'markers', |
||
205 | 'm', |
||
206 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||
207 | 'Comma-separated list of markers/tags to filter' |
||
208 | ) |
||
209 | ->addOption( |
||
210 | 'title', |
||
211 | null, |
||
212 | InputOption::VALUE_OPTIONAL, |
||
213 | 'Sets the title for this project; default is the phpDocumentor logo' |
||
214 | ) |
||
215 | ->addOption( |
||
216 | 'force', |
||
217 | null, |
||
218 | InputOption::VALUE_NONE, |
||
219 | 'Forces a full build of the documentation, does not increment existing documentation' |
||
220 | ) |
||
221 | ->addOption( |
||
222 | 'visibility', |
||
223 | null, |
||
224 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||
225 | 'Specifies the parse visibility that should be displayed in the documentation (comma separated e.g. ' |
||
226 | . '"public,protected")' |
||
227 | ) |
||
228 | ->addOption( |
||
229 | 'defaultpackagename', |
||
230 | null, |
||
231 | InputOption::VALUE_OPTIONAL, |
||
232 | 'Name to use for the default package.' |
||
233 | ) |
||
234 | ->addOption( |
||
235 | 'sourcecode', |
||
236 | null, |
||
237 | InputOption::VALUE_NONE, |
||
238 | 'Whether to include syntax highlighted source code' |
||
239 | ) |
||
240 | ->addOption( |
||
241 | 'progressbar', |
||
242 | 'p', |
||
243 | InputOption::VALUE_NONE, |
||
244 | 'Whether to show a progress bar; will automatically quiet logging to stdout' |
||
245 | ) |
||
246 | ->addOption( |
||
247 | 'template', |
||
248 | null, |
||
249 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||
250 | 'Name of the template to use (optional)' |
||
251 | ) |
||
252 | ->addOption( |
||
253 | 'parseprivate', |
||
254 | null, |
||
255 | InputOption::VALUE_NONE, |
||
256 | 'Whether to parse DocBlocks marked with @internal tag' |
||
257 | ) |
||
258 | ->addArgument( |
||
259 | 'paths', |
||
260 | InputArgument::OPTIONAL | InputArgument::IS_ARRAY, |
||
261 | 'One or more files and folders to process', |
||
262 | array() |
||
263 | ); |
||
264 | |||
265 | parent::configure(); |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * Executes the business logic involved with this command. |
||
270 | * |
||
271 | * @param InputInterface $input |
||
272 | * @param OutputInterface $output |
||
273 | * |
||
274 | * @return int |
||
275 | */ |
||
276 | protected function execute(InputInterface $input, OutputInterface $output) |
||
277 | { |
||
278 | $this->outputHeader($output); |
||
279 | $this->attachListeners($input, $output); |
||
280 | |||
281 | $this->mergeArgumentsIntoConfiguration($input); |
||
282 | $destination = $this->getDestination(); |
||
283 | |||
284 | $this->configureCache(); |
||
285 | $this->renderDocumentationTo($destination); |
||
286 | |||
287 | $this->outputFooter($output, $destination); |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Connect a series of output messages to various events to display progress. |
||
292 | * |
||
293 | * @param InputInterface $input |
||
294 | * @param OutputInterface $output |
||
295 | * |
||
296 | * @return void |
||
297 | */ |
||
298 | private function attachListeners(InputInterface $input, OutputInterface $output) |
||
299 | { |
||
300 | $this->emitter->addListener( |
||
301 | ApiParsingStarted::class, |
||
302 | function (ApiParsingStarted $event) use ($output) { |
||
303 | /** @var FlySystemDefinition $definition */ |
||
304 | $definition = $event->definition(); |
||
305 | $output->writeln( |
||
306 | sprintf('Parsing <info>%d</info> files', count($definition->getFiles())) |
||
307 | ); |
||
308 | } |
||
309 | ); |
||
310 | $this->emitter->addListener( |
||
311 | ApiFileParsed::class, |
||
312 | function (ApiFileParsed $event) use ($output) { |
||
313 | $output->writeln(sprintf(' Parsed <info>%s</info>', (string)$event->filename())); |
||
314 | } |
||
315 | ); |
||
316 | $this->emitter->addListener( |
||
317 | RenderingStarted::class, |
||
318 | function (RenderingStarted $event) use ($output) { |
||
319 | $output->writeln('Started rendering'); |
||
320 | } |
||
321 | ); |
||
322 | $this->emitter->addListener( |
||
323 | RenderingFinished::class, |
||
324 | function (RenderingFinished $event) use ($output) { |
||
325 | $output->writeln('Completed rendering'); |
||
326 | } |
||
327 | ); |
||
328 | $this->emitter->addListener( |
||
329 | RenderActionCompleted::class, |
||
330 | function (RenderActionCompleted $event) use ($output) { |
||
331 | $output->writeln(sprintf(' %s', (string)$event->action())); |
||
332 | } |
||
333 | ); |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * @return Dsn |
||
338 | */ |
||
339 | private function getDestination() |
||
340 | { |
||
341 | $config = $this->configurationFactory->get(); |
||
342 | |||
343 | return $config['phpdocumentor']['paths']['output']; |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Returns the destination as a string and expands it to show the absolute path if the destination is on disk. |
||
348 | * |
||
349 | * Because the destination location is created during rendering we can only expand the path using realpath |
||
350 | * because realpath will return false on a non-existent location. |
||
351 | * |
||
352 | * @param Dsn $destination |
||
353 | * |
||
354 | * @return string |
||
355 | */ |
||
356 | private function getExpandedDestination($destination) |
||
357 | { |
||
358 | return $destination->getScheme() == 'file' |
||
359 | ? realpath($destination->getPath()) |
||
360 | : $destination; |
||
361 | } |
||
362 | |||
363 | private function getTemplates() |
||
364 | { |
||
365 | $config = $this->configurationFactory->get(); |
||
366 | |||
367 | return $config['phpdocumentor']['templates']; |
||
368 | } |
||
369 | |||
370 | private function configureCache() |
||
371 | { |
||
372 | $config = $this->configurationFactory->get(); |
||
373 | |||
374 | $cacheLocation = $config['phpdocumentor']['paths']['cache']; |
||
375 | $cacheEnabled = $config['phpdocumentor']['use-cache']; |
||
376 | |||
377 | $this->commandBus->handle(new ConfigureCache($cacheLocation, $cacheEnabled)); |
||
378 | } |
||
379 | |||
380 | /** |
||
381 | * @param OutputInterface $output |
||
382 | */ |
||
383 | protected function outputHeader(OutputInterface $output) |
||
384 | { |
||
385 | $output->writeln( |
||
386 | sprintf( |
||
387 | '<info>%s</info> version <comment>%s</comment>' . PHP_EOL, |
||
388 | $this->getApplication()->getName(), |
||
389 | $this->getApplication()->getVersion() |
||
390 | ) |
||
391 | ); |
||
392 | } |
||
393 | |||
394 | private function mergeArgumentsIntoConfiguration(InputInterface $input) |
||
395 | { |
||
396 | $this->commandBus->handle( |
||
397 | new MergeConfigurationWithCommandLineOptions($input->getOptions(), $input->getArguments()) |
||
398 | ); |
||
399 | } |
||
400 | |||
401 | private function renderDocumentationTo($destination) |
||
402 | { |
||
403 | $destinationFilesystem = $this->fileSystemFactory->create($destination); |
||
404 | $templates = $this->getTemplates(); |
||
405 | |||
406 | foreach ($this->definitionRepository->fetchAll() as $definition) { |
||
407 | // TODO: Does this mean that once cached it is never refreshed? |
||
408 | if (!$this->documentationRepository->hasForVersionNumber($definition->getVersionNumber())) { |
||
0 ignored issues
–
show
|
|||
409 | $this->commandBus->handle(new Parse($definition)); |
||
410 | } |
||
411 | |||
412 | $documentation = $this->documentationRepository->findByVersionNumber($definition->getVersionNumber()); |
||
0 ignored issues
–
show
$definition->getVersionNumber() is of type integer|double , but the function expects a object<phpDocumentor\Dom...\Parser\Version\Number> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
413 | |||
414 | $this->commandBus->handle(new Render($documentation, $destinationFilesystem, $templates)); |
||
0 ignored issues
–
show
It seems like
$documentation defined by $this->documentationRepo...on->getVersionNumber()) on line 412 can be null ; however, phpDocumentor\DomainModel\Render::__construct() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
Loading history...
|
|||
415 | } |
||
416 | } |
||
417 | |||
418 | private function outputFooter(OutputInterface $output, $destination) |
||
419 | { |
||
420 | $expandedDestination = $this->getExpandedDestination($destination); |
||
421 | $output->writeln(sprintf(PHP_EOL . '<fg=black;bg=green>OK (%s)</>', $expandedDestination)); |
||
422 | } |
||
423 | } |
||
424 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: