Passed
Push — main ( 95b369...5c384e )
by Michiel
17:35 queued 12s
created

ApiGenTask   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 411
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 55
eloc 76
dl 0
loc 411
ccs 0
cts 102
cp 0
rs 6
c 0
b 0
f 0

31 Methods

Rating   Name   Duplication   Size   Complexity  
A setGoogleAnalytics() 0 3 1
A setSource() 0 3 1
A setSourceCode() 0 4 2
A setNoSourceCode() 0 3 1
A setMain() 0 3 1
A setPhp() 0 4 2
A setGroups() 0 3 1
A setExclude() 0 3 1
A setBaseUrl() 0 3 1
A setAccessLevels() 0 3 1
A setExtensions() 0 3 1
A setGoogleCseLabel() 0 3 1
A setDownload() 0 4 2
A setDebug() 0 4 2
A setDeprecated() 0 4 2
A setSkipDocPath() 0 3 1
A setCharset() 0 3 1
A setConfig() 0 3 1
A setTodo() 0 4 2
A setAction() 0 3 1
A setDestination() 0 3 1
A constructArguments() 0 16 6
A setTree() 0 4 2
A setInternal() 0 4 2
C main() 0 47 12
A setExecutable() 0 3 1
A setAnnotationGroups() 0 3 1
A setTemplateConfig() 0 3 1
A setGoogleCseId() 0 3 1
A setTitle() 0 3 1
A setTemplateTheme() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like ApiGenTask often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ApiGenTask, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the LGPL. For more information please see
18
 * <http://phing.info>.
19
 */
20
21
namespace Phing\Task\Ext;
22
23
use Phing\Exception\BuildException;
24
use Phing\Project;
25
use Phing\Task;
26
27
/**
28
 * ApiGen task (http://apigen.org).
29
 *
30
 * @package phing.tasks.ext.apigen
31
 * @author  Martin Srank <[email protected]>
32
 * @author  Jaroslav Hanslík <[email protected]>
33
 * @author  Lukáš Homza <[email protected]>
34
 */
35
class ApiGenTask extends Task
36
{
37
    /**
38
     * Default ApiGen executable name.
39
     *
40
     * @var string
41
     */
42
    private $executable = 'apigen';
43
44
    /**
45
     * Default ApiGen action.
46
     *
47
     * @var string
48
     */
49
    private $action = 'generate';
50
51
    /**
52
     * Default ApiGen options.
53
     *
54
     * @var array
55
     */
56
    private $options = [];
57
58
    /**
59
     * Sets the ApiGen executable name.
60
     *
61
     * @param string $executable
62
     */
63
    public function setExecutable(string $executable): void
64
    {
65
        $this->executable = $executable;
66
    }
67
68
    /**
69
     * Sets the ApiGen action to be executed.
70
     *
71
     * @param string $action
72
     */
73
    public function setAction(string $action): void
74
    {
75
        $this->action = $action;
76
    }
77
78
    /**
79
     * Sets the config file name.
80
     *
81
     * @param string $config
82
     */
83
    public function setConfig(string $config): void
84
    {
85
        $this->options['config'] = $config;
86
    }
87
88
    /**
89
     * Sets source files or directories.
90
     *
91
     * @param string $source
92
     */
93
    public function setSource(string $source): void
94
    {
95
        $this->options['source'] = explode(',', $source);
96
    }
97
98
    /**
99
     * Sets the destination directory.
100
     *
101
     * @param string $destination
102
     */
103
    public function setDestination(string $destination): void
104
    {
105
        $this->options['destination'] = $destination;
106
    }
107
108
    /**
109
     * Sets list of allowed file extensions.
110
     *
111
     * @param string $extensions
112
     */
113
    public function setExtensions(string $extensions): void
114
    {
115
        $this->options['extensions'] = explode(',', $extensions);
116
    }
117
118
    /**
119
     * Sets masks (case sensitive) to exclude files or directories from processing.
120
     *
121
     * @param string $exclude
122
     */
123
    public function setExclude(string $exclude): void
124
    {
125
        $this->options['exclude'] = explode(',', $exclude);
126
    }
127
128
    /**
129
     * Sets masks to exclude elements from documentation generating.
130
     *
131
     * @param string $skipDocPath
132
     */
133
    public function setSkipDocPath(string $skipDocPath): void
134
    {
135
        $this->options['skip-doc-path'] = explode(',', $skipDocPath);
136
    }
137
138
    /**
139
     * Sets the character set of source files.
140
     *
141
     * @param string $charset
142
     */
143
    public function setCharset(string $charset): void
144
    {
145
        $this->options['charset'] = explode(',', $charset);
146
    }
147
148
    /**
149
     * Sets the main project name prefix.
150
     *
151
     * @param string $main
152
     */
153
    public function setMain(string $main): void
154
    {
155
        $this->options['main'] = $main;
156
    }
157
158
    /**
159
     * Sets the title of generated documentation.
160
     *
161
     * @param string $title
162
     */
163
    public function setTitle(string $title): void
164
    {
165
        $this->options['title'] = $title;
166
    }
167
168
    /**
169
     * Sets the documentation base URL.
170
     *
171
     * @param string $baseUrl
172
     */
173
    public function setBaseUrl(string $baseUrl): void
174
    {
175
        $this->options['base-url'] = $baseUrl;
176
    }
177
178
    /**
179
     * Sets the Google Custom Search ID.
180
     *
181
     * @param string $googleCseId
182
     */
183
    public function setGoogleCseId(string $googleCseId): void
184
    {
185
        $this->options['google-cse-id'] = $googleCseId;
186
    }
187
188
    /**
189
     * Sets the Google Custom Search label.
190
     *
191
     * @param string $googleCseLabel
192
     */
193
    public function setGoogleCseLabel(string $googleCseLabel): void
194
    {
195
        $this->options['google-cse-label'] = $googleCseLabel;
196
    }
197
198
    /**
199
     * Sets the Google Analytics tracking code.
200
     *
201
     * @param string $googleAnalytics
202
     */
203
    public function setGoogleAnalytics(string $googleAnalytics): void
204
    {
205
        $this->options['google-analytics'] = $googleAnalytics;
206
    }
207
208
    /**
209
     * Sets the template config file name.
210
     *
211
     * @param string $templateConfig
212
     */
213
    public function setTemplateConfig(string $templateConfig): void
214
    {
215
        $this->options['template-config'] = $templateConfig;
216
    }
217
218
    /**
219
     * Sets the template config file name.
220
     *
221
     * @param string $templateTheme
222
     */
223
    public function setTemplateTheme(string $templateTheme): void
224
    {
225
        $this->options['template-theme'] = $templateTheme;
226
    }
227
228
    /**
229
     * Sets how elements should be grouped in the menu.
230
     *
231
     * @param string $groups
232
     */
233
    public function setGroups(string $groups): void
234
    {
235
        $this->options['groups'] = $groups;
236
    }
237
238
    /**
239
     * Sets the element access levels.
240
     *
241
     * Documentation only for methods and properties with the given access level will be generated.
242
     *
243
     * @param string $accessLevels
244
     */
245
    public function setAccessLevels(string $accessLevels): void
246
    {
247
        $this->options['access-levels'] = $accessLevels;
248
    }
249
250
    /**
251
     * Sets the element access levels.
252
     *
253
     * Documentation only for methods and properties with the given access level will be generated.
254
     *
255
     * @param string $annotationGroups
256
     */
257
    public function setAnnotationGroups(string $annotationGroups): void
258
    {
259
        $this->options['annotation-groups'] = $annotationGroups;
260
    }
261
262
    /**
263
     * Sets if documentation for elements marked as internal and internal documentation parts should be generated.
264
     *
265
     * @param boolean $internal
266
     */
267
    public function setInternal(bool $internal): void
268
    {
269
        if ($internal) {
270
            $this->options['internal'] = null;
271
        }
272
    }
273
274
    /**
275
     * Sets if documentation for PHP internal classes should be generated.
276
     *
277
     * @param boolean $php
278
     */
279
    public function setPhp(bool $php): void
280
    {
281
        if ($php) {
282
            $this->options['php'] = null;
283
        }
284
    }
285
286
    /**
287
     * Sets if tree view of classes, interfaces, traits and exceptions should be generated.
288
     *
289
     * @param boolean $tree
290
     */
291
    public function setTree(bool $tree): void
292
    {
293
        if ($tree) {
294
            $this->options['tree'] = null;
295
        }
296
    }
297
298
    /**
299
     * Sets if documentation for deprecated elements should be generated.
300
     *
301
     * @param boolean $deprecated
302
     */
303
    public function setDeprecated(bool $deprecated): void
304
    {
305
        if ($deprecated) {
306
            $this->options['deprecated'] = null;
307
        }
308
    }
309
310
    /**
311
     * Sets if documentation of tasks should be generated.
312
     *
313
     * @param boolean $todo
314
     */
315
    public function setTodo(bool $todo): void
316
    {
317
        if ($todo) {
318
            $this->options['todo'] = null;
319
        }
320
    }
321
322
    /**
323
     * Sets if highlighted source code files should not be generated.
324
     *
325
     * @param boolean $noSourceCode
326
     * @deprecated
327
     */
328
    public function setNoSourceCode(bool $noSourceCode): void
329
    {
330
        $this->setSourceCode(!$noSourceCode);
331
    }
332
333
    /**
334
     * Sets if highlighted source code files should be generated.
335
     *
336
     * @param boolean $noSourceCode
337
     */
338
    public function setSourceCode(bool $noSourceCode): void
339
    {
340
        if (!$noSourceCode) {
341
            $this->options['no-source-code'] = null;
342
        }
343
    }
344
345
    /**
346
     * Sets if a link to download documentation as a ZIP archive should be generated.
347
     *
348
     * @param boolean $download
349
     */
350
    public function setDownload(bool $download): void
351
    {
352
        if ($download) {
353
            $this->options['download'] = null;
354
        }
355
    }
356
357
    /**
358
     * Enables/disables the debug mode.
359
     *
360
     * @param boolean $debug
361
     */
362
    public function setDebug(bool $debug): void
363
    {
364
        if ($debug) {
365
            $this->options['debug'] = null;
366
        }
367
    }
368
369
    /**
370
     * Runs ApiGen.
371
     *
372
     * @throws BuildException If something is wrong.
373
     * @see    Task::main()
374
     */
375
    public function main()
376
    {
377
        if ('apigen' !== $this->executable && !is_file($this->executable)) {
378
            throw new BuildException(sprintf('Executable %s not found', $this->executable), $this->getLocation());
379
        }
380
381
        if (!empty($this->options['config'])) {
382
            // Config check
383
            if (!is_file($this->options['config'])) {
384
                throw new BuildException(
385
                    sprintf(
386
                        'Config file %s doesn\'t exist',
387
                        $this->options['config']
388
                    ),
389
                    $this->getLocation()
390
                );
391
            }
392
        } else {
393
            // Source check
394
            if (empty($this->options['source'])) {
395
                throw new BuildException('Source is not set', $this->getLocation());
396
            }
397
            // Destination check
398
            if (empty($this->options['destination'])) {
399
                throw new BuildException('Destination is not set', $this->getLocation());
400
            }
401
        }
402
403
        // Source check
404
        if (!empty($this->options['source'])) {
405
            foreach ($this->options['source'] as $source) {
406
                if (!file_exists($source)) {
407
                    throw new BuildException(sprintf('Source %s doesn\'t exist', $source), $this->getLocation());
408
                }
409
            }
410
        }
411
412
        // Execute ApiGen
413
        exec(
414
            escapeshellcmd($this->executable) . ' ' . escapeshellcmd($this->action) . ' ' . $this->constructArguments(),
415
            $output,
416
            $return
417
        );
418
419
        $logType = 0 === $return ? Project::MSG_INFO : Project::MSG_ERR;
420
        foreach ($output as $line) {
421
            $this->log($line, $logType);
422
        }
423
    }
424
425
    /**
426
     * Generates command line arguments for the ApiGen executable.
427
     *
428
     * @return string
429
     */
430
    protected function constructArguments(): string
431
    {
432
        $args = [];
433
        foreach ($this->options as $option => $value) {
434
            if (is_bool($value)) {
435
                $args[] = '--' . $option . '=' . ($value ? 'yes' : 'no');
436
            } elseif (is_array($value)) {
437
                foreach ($value as $v) {
438
                    $args[] = '--' . $option . '=' . escapeshellarg($v);
439
                }
440
            } else {
441
                $args[] = '--' . $option . '=' . escapeshellarg($value);
442
            }
443
        }
444
445
        return implode(' ', $args);
446
    }
447
}
448