├── .gitignore ├── LICENSE ├── README.md ├── composer.json └── src ├── Extension └── Loader.php └── Task ├── PhpCsAutoFixer.php ├── PhpCsAutoFixerV2.php └── Phpdoc.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | /vendor/ 3 | # Don't commit the lock file as this is a library 4 | composer.lock 5 | 6 | .idea/ 7 | grumphp.yml 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Just 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GrumPHP Extra tasks 2 | 3 | This package is brought alive to extend the functionalities of the already existing [GrumPHP](https://github.com/phpro/grumphp). 4 | 5 | ## Installation 6 | 7 | The easiest way to install this package is through composer: 8 | 9 | composer require --dev wearejust/grumphp-extra-tasks 10 | 11 | Add the extension loader to your `grumphp.yml` 12 | 13 | ```yaml 14 | parameters: 15 | extensions: 16 | - Wearejust\GrumPHPExtra\Extension\Loader 17 | ``` 18 | 19 | ## Usage 20 | 21 | ### PhpCsAutoFixer 22 | 23 | In [grumphp core](https://github.com/phpro/grumphp) 24 | it is not possible to use the php-cs-fixer [to auto fix your files according to your config](https://github.com/phpro/grumphp/issues/110). 25 | This package adds this missing feature. 26 | 27 | The configuration of this custom task is the same as [the already existing task](https://github.com/phpro/grumphp/blob/master/doc/tasks/php_cs_fixer.md), 28 | only specify the new `php_cs_auto_fixer` configuration key. For example: 29 | 30 | ```yaml 31 | parameters: 32 | tasks: 33 | php_cs_auto_fixer: 34 | config_file: .php_cs 35 | config: ~ 36 | fixers: [] 37 | level: ~ 38 | verbose: true 39 | ``` 40 | 41 | ### PhpCsAutoFixerV2 42 | 43 | In [grumphp core](https://github.com/phpro/grumphp) 44 | it is not possible to use the php-cs-fixer [to auto fix your files according to your config](https://github.com/phpro/grumphp/issues/110). 45 | This package adds this missing feature. 46 | 47 | The configuration of this custom task is the same as [the already existing task](https://github.com/phpro/grumphp/blob/master/doc/tasks/php_cs_fixer.md), 48 | only specify the new `php_cs_auto_fixerv2` configuration key. For example: 49 | 50 | ```yaml 51 | parameters: 52 | tasks: 53 | php_cs_auto_fixerv2: 54 | allow_risky: false 55 | cache_file: ~ 56 | config: ~ 57 | rules: [] 58 | using_cache: true 59 | path_mode: ~ 60 | verbose: true 61 | diff: false 62 | triggered_by: ['php'] 63 | ``` 64 | 65 | ### Phpdoc 66 | 67 | In [grumphp core](https://github.com/phpro/grumphp) 68 | there is no phpdoc tasks [to generate phpDoc if necessary (and add it) before commit](https://github.com/phpro/grumphp/pull/253). 69 | This package adds this missing feature. 70 | 71 | To use this task, just specify if inside `grumphp.yml` in the `tasks:` section. 72 | 73 | ```yaml 74 | parameters: 75 | tasks: 76 | phpdoc: 77 | config_file: ~ 78 | target_folder: ~ 79 | cache_folder: ~ 80 | filename: ~ 81 | directory: ~ 82 | encoding: ~ 83 | extensions: ~ 84 | ignore: ~ 85 | ignore_tags: ~ 86 | ignore_symlinks: ~ 87 | markers: ~ 88 | title: ~ 89 | force: ~ 90 | visibility: ~ 91 | default_package_name: ~ 92 | source_code: ~ 93 | progress_bar: ~ 94 | template: ~ 95 | quiet: ~ 96 | ansi: ~ 97 | no_ansi: ~ 98 | no_interaction: ~ 99 | ``` 100 | 101 | **config_file** 102 | *Default: `null`* 103 | 104 | Without config_file parameter phpdoc will search for a phpdoc.dist.xml config file. 105 | This file can be overload by phpdoc.xml. 106 | If no file found, no config file will be used. 107 | 108 | **target_folder** 109 | *Default: `null`* 110 | 111 | Without this parameter the doc will be generated in an `output/` folder. 112 | 113 | **cache_folder** 114 | *Default: `null`* 115 | 116 | Without this parameter, cache will be placed in the `target_folder`. 117 | 118 | **filename** 119 | *Default: `null`* 120 | 121 | Comma separated file list to documents. 122 | 123 | **directory** 124 | *Default: `null`* 125 | Comma separated directory list to documents. 126 | 127 | **encoding** 128 | *Default: `null`* 129 | 130 | Without this parameter, encoding will be `'UTF-8'`. 131 | 132 | **extensions** 133 | *Default: `null`* 134 | 135 | Comma separated file extension list. Contains extension of file to parse. 136 | Without this parameter, parsed file are : 137 | * php 138 | * php3 139 | * phtml 140 | 141 | **ignore** 142 | *Default: `null`* 143 | 144 | Comma separated list of paths to skip when parsing. 145 | 146 | **ignore_tags** 147 | *Default: `null`* 148 | 149 | Comma separated list of tags to skip when parsing. 150 | 151 | **ignore_symlinks** 152 | *Default: `false`* 153 | Tells the parser not to follow symlinks. 154 | 155 | **markers** 156 | *Default: `null`* 157 | 158 | Provide a comma-separated list of markers to parse (TODO ...). 159 | 160 | **title** 161 | *Default: `null`* 162 | 163 | Specify a title for the documentation. 164 | 165 | **force** 166 | *Default: `null`* 167 | 168 | Ignore exceptions and continue parsing. 169 | 170 | **visibility** 171 | *Default: `null`* 172 | 173 | Provide a comma-separated list of visibility scopes to parse. 174 | This parameter may be used to tell phpDocumentor to only parse public properties and methods, or public and protected. 175 | 176 | **default_package_name** 177 | *Default: `null`* 178 | 179 | Default package name 180 | 181 | **source_code** 182 | *Default: `null`* 183 | 184 | When this parameter is provided the parser will add a compressed, base64-encoded version of the parsed file’s source as child element of the element. 185 | This information can then be picked up by the transformer to generate a syntax highlighted view of the file’s source code and even have direct links to specific lines. 186 | 187 | **progress_bar** 188 | *Default: `null`* 189 | 190 | Display progress bar during the process. 191 | 192 | **template** 193 | *Default: `null`* 194 | 195 | Specify a template to use. Without this parameter the template named "clean" will be used. 196 | 197 | **quiet** 198 | *Default: `null`* 199 | 200 | With this option, only errors will be displayed. 201 | 202 | **ansi** 203 | *Default: `null`* 204 | 205 | Force ANSI output. 206 | 207 | **no_ansi** 208 | *Default: `null`* 209 | 210 | Disable ANSI output. 211 | 212 | **no_interaction** 213 | *Default: `null`* 214 | 215 | ##License 216 | This package is licensed under the MIT License. 217 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wearejust/grumphp-extra-tasks", 3 | "description": "A set of extra tasks for grumphp", 4 | "type": "library", 5 | "authors": [ 6 | { 7 | "name": "Cees van Egmond", 8 | "email": "cees.vanegmond@wearejust.com" 9 | } 10 | ], 11 | "autoload": { 12 | "psr-4": { 13 | "Wearejust\\GrumPHPExtra\\": "src/" 14 | } 15 | }, 16 | "require": { 17 | "php": ">=7.0", 18 | "phpro/grumphp": "~0.15" 19 | }, 20 | "suggest": { 21 | "friendsofphp/php-cs-fixer": "Allow auto fixing using PHP-CS-FIXER (v1 or v2).", 22 | "phpdocumentor/phpdocumentor": "Allow to generate phpDoc if necessary (and add it) before commit", 23 | "ext-simplexml": "Allow phpdocumentor/phpdocumentor to behave correctly" 24 | }, 25 | "license": "MIT", 26 | "minimum-stability": "stable" 27 | } 28 | -------------------------------------------------------------------------------- /src/Extension/Loader.php: -------------------------------------------------------------------------------- 1 | register('task.php_cs_auto_fixer', PhpCsAutoFixer::class) 20 | ->addArgument(new Reference('config')) 21 | ->addArgument(new Reference('process_builder')) 22 | ->addArgument(new Reference('formatter.phpcsfixer')) 23 | ->addTag('grumphp.task', ['config' => 'php_cs_auto_fixer']); 24 | 25 | $container->register('task.php_cs_auto_fixerv2', PhpCsAutoFixerV2::class) 26 | ->addArgument(new Reference('config')) 27 | ->addArgument(new Reference('process_builder')) 28 | ->addArgument(new Reference('formatter.phpcsfixer')) 29 | ->addTag('grumphp.task', ['config' => 'php_cs_auto_fixerv2']); 30 | 31 | $container->register('task.phpdoc', Phpdoc::class) 32 | ->addArgument(new Reference('config')) 33 | ->addArgument(new Reference('process_builder')) 34 | ->addArgument(new Reference('formatter.raw_process')) 35 | ->addTag('grumphp.task', ['config' => 'phpdoc']); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Task/PhpCsAutoFixer.php: -------------------------------------------------------------------------------- 1 | getFiles()->name('*.php'); 30 | if (0 === count($files)) { 31 | return TaskResult::createSkipped($this, $context); 32 | } 33 | 34 | $config = $this->getConfiguration(); 35 | $this->formatter->resetCounter(); 36 | 37 | $arguments = $this->processBuilder->createArgumentsForCommand('php-cs-fixer'); 38 | $arguments->add('--format=json'); 39 | $arguments->addOptionalArgument('--level=%s', $config['level']); 40 | $arguments->addOptionalArgument('--config=%s', $config['config']); 41 | $arguments->addOptionalArgument('--config-file=%s', $config['config_file']); 42 | $arguments->addOptionalArgument('--verbose', $config['verbose']); 43 | $arguments->addOptionalCommaSeparatedArgument('--fixers=%s', $config['fixers']); 44 | $arguments->add('fix'); 45 | 46 | if ($context instanceof RunContext && $config['config_file'] !== null) { 47 | return $this->runOnAllFiles($context, $arguments); 48 | } 49 | 50 | return $this->runOnChangedFiles($context, $arguments, $files); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Task/PhpCsAutoFixerV2.php: -------------------------------------------------------------------------------- 1 | getConfiguration(); 32 | $files = $context->getFiles()->extensions($config['triggered_by']); 33 | if (0 === count($files)) { 34 | return TaskResult::createSkipped($this, $context); 35 | } 36 | 37 | $this->formatter->resetCounter(); 38 | 39 | $process = $this->runProcess($context, $config, $files, true); 40 | 41 | if (!$process->isSuccessful()) { 42 | 43 | $toAdd = $files->map(function(SplFileInfo $file) { 44 | return $file->getRelativePathname(); 45 | }); 46 | 47 | $this->runProcess($context, $config, $files, false); 48 | 49 | exec(sprintf('git add %s', implode(' ', $toAdd->toArray()))); 50 | 51 | $process = $this->runProcess($context, $config, $files, false); 52 | $messages = [$this->formatter->format($process)]; 53 | $suggestions = [$this->formatter->formatSuggestion($process)]; 54 | $errorMessage = $this->formatter->formatErrorMessage($messages, $suggestions); 55 | 56 | return TaskResult::createNonBlockingFailed($this, $context, $errorMessage); 57 | } 58 | 59 | return TaskResult::createPassed($this, $context); 60 | } 61 | 62 | /** 63 | * @param \GrumPHP\Task\Context\ContextInterface $context 64 | * @param $config 65 | * @param $files 66 | * @param $dryRun 67 | * 68 | * @return \GrumPHP\Collection\ProcessArgumentsCollection 69 | */ 70 | private function runProcess(ContextInterface $context, $config, $files, $dryRun) 71 | { 72 | $arguments = $this->processBuilder->createArgumentsForCommand('php-cs-fixer'); 73 | $arguments->add('--format=json'); 74 | 75 | if ($dryRun) { 76 | $arguments->add('--dry-run'); 77 | } 78 | 79 | $arguments->addOptionalArgument('--allow-risky=%s', $config['allow_risky'] ? 'yes' : 'no'); 80 | $arguments->addOptionalArgument('--cache-file=%s', $config['cache_file']); 81 | $arguments->addOptionalArgument('--config=%s', $config['config']); 82 | 83 | if ($rules = $config['rules']) { 84 | $arguments->add(sprintf( 85 | '--rules=%s', 86 | // Comma-delimit rules if specified as a list; otherwise JSON-encode. 87 | array_values($rules) === $rules ? implode(',', $rules) : json_encode($rules) 88 | )); 89 | } 90 | 91 | $canUseIntersection = !($context instanceof RunContext) && $config['config_contains_finder']; 92 | 93 | $arguments->addOptionalArgument('--using-cache=%s', $config['using_cache'] ? 'yes' : 'no'); 94 | $arguments->addOptionalArgument('--path-mode=intersection', $canUseIntersection); 95 | $arguments->addOptionalArgument('--verbose', $config['verbose']); 96 | $arguments->addOptionalArgument('--diff', $config['diff']); 97 | $arguments->add('fix'); 98 | 99 | if ($context instanceof GitPreCommitContext || !$config['config_contains_finder']) { 100 | $arguments->addFiles($files); 101 | } 102 | 103 | $process = $this->processBuilder->buildProcess($arguments); 104 | 105 | $process->run(); 106 | 107 | return $process; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Task/Phpdoc.php: -------------------------------------------------------------------------------- 1 | setDefaults( 34 | [ 35 | 'config_file' => null, 36 | 'target_folder' => null, 37 | 'cache_folder' => null, 38 | 'filename' => null, 39 | 'directory' => null, 40 | 'encoding' => null, 41 | 'extensions' => null, 42 | 'ignore' => null, 43 | 'ignore_tags' => null, 44 | 'ignore_symlinks' => null, 45 | 'markers' => null, 46 | 'title' => null, 47 | 'force' => null, 48 | 'visibility' => null, 49 | 'default_package_name' => null, 50 | 'source_code' => null, 51 | 'progress_bar' => null, 52 | 'template' => null, 53 | 'quiet' => null, 54 | 'ansi' => null, 55 | 'no_ansi' => null, 56 | 'no_interaction' => null] 57 | ); 58 | 59 | $resolver->addAllowedTypes('config_file', ['null', 'string']); 60 | $resolver->addAllowedTypes('target_folder', ['null', 'string']); 61 | $resolver->addAllowedTypes('cache_folder', ['null', 'string']); 62 | $resolver->addAllowedTypes('filename', ['null', 'string']); 63 | $resolver->addAllowedTypes('directory', ['null', 'string']); 64 | $resolver->addAllowedTypes('encoding', ['null', 'string']); 65 | $resolver->addAllowedTypes('extensions', ['null', 'string']); 66 | $resolver->addAllowedTypes('ignore', ['null', 'string']); 67 | $resolver->addAllowedTypes('ignore_tags', ['null', 'string']); 68 | $resolver->addAllowedTypes('ignore_symlinks', ['null', 'string']); 69 | $resolver->addAllowedTypes('markers', ['null', 'string']); 70 | $resolver->addAllowedTypes('title', ['null', 'string']); 71 | $resolver->addAllowedTypes('force', ['null', 'bool']); 72 | $resolver->addAllowedTypes('visibility', ['null', 'string']); 73 | $resolver->addAllowedTypes('default_package_name', ['null', 'string']); 74 | $resolver->addAllowedTypes('source_code', ['null', 'bool']); 75 | $resolver->addAllowedTypes('progress_bar', ['null', 'bool']); 76 | $resolver->addAllowedTypes('template', ['null', 'string']); 77 | $resolver->addAllowedTypes('quiet', ['null', 'bool']); 78 | $resolver->addAllowedTypes('ansi', ['null', 'bool']); 79 | $resolver->addAllowedTypes('no_ansi', ['null', 'bool']); 80 | $resolver->addAllowedTypes('no_interaction', ['null', 'bool']); 81 | 82 | return $resolver; 83 | } 84 | 85 | /** 86 | * {@inheritdoc} 87 | */ 88 | public function canRunInContext(ContextInterface $context): bool 89 | { 90 | return ($context instanceof GitPreCommitContext || $context instanceof RunContext); 91 | } 92 | 93 | /** 94 | * {@inheritdoc} 95 | */ 96 | public function run(ContextInterface $context): TaskResultInterface 97 | { 98 | $config = $this->getConfiguration(); 99 | 100 | if ($context instanceof GitPreCommitContext) { 101 | $directoriesToDoc = $this->getDirectoriesToDoc($config); 102 | $filenamesToDoc = $this->getFilenamesToDoc($config); 103 | 104 | $filesMatchingContext = array(); 105 | 106 | array_walk( 107 | $directoriesToDoc, function (&$value) { 108 | $value = pathinfo($value)['basename']; 109 | $value = ltrim($value, './'); 110 | $value = rtrim($value, './'); 111 | } 112 | ); 113 | 114 | foreach ($filenamesToDoc as $filenameToDoc) { 115 | if ($context->getFiles()->name(pathinfo($filenameToDoc)['basename'])->count() > 0) { 116 | $filesMatchingContext[] = $context->getFiles()->name(pathinfo($filenameToDoc)['basename']); 117 | } 118 | } 119 | 120 | if ($context->getFiles()->paths($directoriesToDoc)->count() > 0) { 121 | $filesMatchingContext[] = $context->getFiles()->paths($directoriesToDoc); 122 | } 123 | 124 | if (empty($filesMatchingContext)) { 125 | return TaskResult::createSkipped($this, $context); 126 | } 127 | } 128 | 129 | $arguments = $this->processBuilder->createArgumentsForCommand('phpdoc'); 130 | $arguments->addOptionalArgumentWithSeparatedValue('--config', $config['config_file']); 131 | $arguments->addOptionalArgumentWithSeparatedValue('--target', $config['target_folder']); 132 | $arguments->addOptionalArgumentWithSeparatedValue('--cache-folder', $config['cache_folder']); 133 | $arguments->addOptionalArgumentWithSeparatedValue('--filename', $config['filename']); 134 | $arguments->addOptionalArgumentWithSeparatedValue('--directory', $config['directory']); 135 | $arguments->addOptionalArgumentWithSeparatedValue('--encoding', $config['encoding']); 136 | $arguments->addOptionalArgumentWithSeparatedValue('--extensions', $config['extensions']); 137 | $arguments->addOptionalArgumentWithSeparatedValue('--ignore', $config['ignore']); 138 | $arguments->addOptionalArgumentWithSeparatedValue('--ignore-tags', $config['ignore_tags']); 139 | $arguments->addOptionalArgument('--ignore-symlinks', $config['ignore_symlinks']); 140 | $arguments->addOptionalArgumentWithSeparatedValue('--markers', $config['markers']); 141 | $arguments->addOptionalArgumentWithSeparatedValue('--title', $config['title']); 142 | $arguments->addOptionalArgument('--force', $config['force']); 143 | $arguments->addOptionalArgumentWithSeparatedValue('--visibility', $config['visibility']); 144 | $arguments->addOptionalArgumentWithSeparatedValue('--defaultpackagename', $config['default_package_name']); 145 | $arguments->addOptionalArgument('--sourcecode', $config['source_code']); 146 | $arguments->addOptionalArgument('--progressbar', $config['progress_bar']); 147 | $arguments->addOptionalArgumentWithSeparatedValue('--template', $config['template']); 148 | $arguments->addOptionalArgument('--quiet', $config['progress_bar']); 149 | $arguments->addOptionalArgument('--ansi', $config['progress_bar']); 150 | $arguments->addOptionalArgument('--no-ansi', $config['progress_bar']); 151 | $arguments->addOptionalArgument('--no-interaction', $config['progress_bar']); 152 | 153 | $process = $this->processBuilder->buildProcess($arguments); 154 | $process->run(); 155 | 156 | if (!$process->isSuccessful()) { 157 | return TaskResult::createFailed($this, $context, $this->formatter->format($process)); 158 | } 159 | 160 | if ($process->isSuccessful() && $context instanceof GitPreCommitContext) { 161 | $trueTargetFolder = $this->getTrueTargetFolder($config); 162 | 163 | $argumentsGit = $this->processBuilder->createArgumentsForCommand('git'); 164 | $argumentsGit->addOptionalArgumentWithSeparatedValue('add', $trueTargetFolder . '*'); 165 | 166 | $processGit = $this->processBuilder->buildProcess($argumentsGit); 167 | $processGit->run(); 168 | 169 | if (!$processGit->isSuccessful()) { 170 | return TaskResult::createFailed($this, $context, $this->formatter->format($processGit)); 171 | } 172 | } 173 | 174 | return TaskResult::createPassed($this, $context); 175 | } 176 | 177 | /** 178 | * @param $config 179 | * @return array 180 | */ 181 | private function getFilenamesToDoc($config) 182 | { 183 | $filenames = array(); 184 | $configFileXML = null; 185 | 186 | if (empty($config['config_file']) && file_exists($config['config_file'])) { 187 | $configFileXML = new SimpleXMLElement(file_get_contents($config['config_file'])); 188 | $filenames = array_merge($filenames, (array)$configFileXML->files->filename); 189 | } elseif (file_exists('phpdoc.xml')) { 190 | $configFileXML = new SimpleXMLElement(file_get_contents('phpdoc.xml')); 191 | $filenames = array_merge($filenames, (array)$configFileXML->files->filename); 192 | } elseif (file_exists('phpdoc.dist.xml')) { 193 | $configFileXML = new SimpleXMLElement(file_get_contents('phpdoc.dist.xml')); 194 | $filenames = array_merge($filenames, (array)$configFileXML->files->filename); 195 | } 196 | 197 | if (!empty($config['filename'])) { 198 | $filenames = array_merge($filenames, explode(',', $config['filename'])); 199 | } 200 | 201 | return $filenames; 202 | } 203 | 204 | /** 205 | * @param $config 206 | * @return array 207 | */ 208 | private function getDirectoriesToDoc(&$config) 209 | { 210 | $directories = array(); 211 | $configFileXML = null; 212 | 213 | if (empty($config['config_file']) && file_exists($config['config_file'])) { 214 | $configFileXML = new SimpleXMLElement(file_get_contents($config['config_file'])); 215 | $directories = array_merge($directories, (array)$configFileXML->files->directory); 216 | } elseif (file_exists('phpdoc.xml')) { 217 | $configFileXML = new SimpleXMLElement(file_get_contents('phpdoc.xml')); 218 | $directories = array_merge($directories, (array)$configFileXML->files->directory); 219 | } elseif (file_exists('phpdoc.dist.xml')) { 220 | $configFileXML = new SimpleXMLElement(file_get_contents('phpdoc.dist.xml')); 221 | $directories = array_merge($directories, (array)$configFileXML->files->directory); 222 | } 223 | 224 | if (!empty($config['directory'])) { 225 | $directories = array_merge($directories, explode(',', $config['directory'])); 226 | } 227 | 228 | return $directories; 229 | } 230 | 231 | /** 232 | * @param $config 233 | * @return null|string 234 | */ 235 | private function getTrueTargetFolder(&$config) 236 | { 237 | $trueTargetFolder = null; 238 | $configFileXML = null; 239 | 240 | if (($config['target_folder'])) { 241 | $trueTargetFolder = $config['target_folder']; 242 | } elseif ($config['config_file'] && file_exists($config['config_file'])) { 243 | $configFileXML = new SimpleXMLElement(file_get_contents($config['config_file'])); 244 | $trueTargetFolder = $configFileXML->transformer->target; 245 | } elseif (file_exists('phpdoc.xml')) { 246 | $configFileXML = new SimpleXMLElement(file_get_contents('phpdoc.xml')); 247 | $trueTargetFolder = $configFileXML->transformer->target; 248 | } elseif (file_exists('phpdoc.dist.xml')) { 249 | $configFileXML = new SimpleXMLElement(file_get_contents('phpdoc.dist.xml')); 250 | $trueTargetFolder = $configFileXML->transformer->target; 251 | } else { 252 | $trueTargetFolder = 'output/'; 253 | } 254 | 255 | $trueTargetFolder .= (strlen($trueTargetFolder) - 1 === strrpos($trueTargetFolder, '/') ? '' : '/'); 256 | 257 | return $trueTargetFolder; 258 | } 259 | } 260 | --------------------------------------------------------------------------------