Completed
Pull Request — master (#29)
by Rick
04:56
created

Cli::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 35
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 6
cts 6
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 25
nc 1
nop 1
crap 1
1
<?php
2
3
namespace PhpAssumptions;
4
5
use League\CLImate\CLImate;
6
use PhpAssumptions\Output\PrettyOutput;
7
use PhpAssumptions\Output\XmlOutput;
8
use PhpAssumptions\Parser\NodeVisitor;
9
use PhpParser\NodeTraverser;
10
use PhpParser\ParserFactory;
11
12
class Cli
13
{
14
    const VERSION = '0.7.1';
15
16
    /**
17
     * @var CLImate
18
     */
19
    private $cli;
20
21
    /**
22
     * @var \PhpParser\Parser
23
     */
24
    private $parser;
25
26 8
    private function createParser()
27
    {
28 8
        $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
29 8
        return $parser;
30
    }
31
32 8
    public function __construct(CLImate $cli)
33
    {
34 8
        $this->cli = $cli;
35 8
        $this->cli->arguments->add(
36
            [
37 8
                'path' => [
38
                    'description' => 'The path to analyse',
39
                    'required' => false,
40
                ],
41
                'format' => [
42
                    'prefix' => 'f',
43
                    'longPrefix' => 'format',
44
                    'description' => 'Format (pretty, xml)',
45
                    'defaultValue' => 'pretty',
46
                ],
47
                'exclude' => [
48
                    'prefix' => 'e',
49
                    'longPrefix' => 'exclude',
50
                    'description' => 'List of files/directories (separate by ",") to exclude from the analyse',
51
                    'defaultValue' => ''
52
                ],
53
                'output' => [
54
                    'prefix' => 'o',
55
                    'longPrefix' => 'output',
56
                    'description' => 'Output file',
57
                    'defaultValue' => 'phpa.xml',
58
                ],
59
                'version' => [
60
                    'longPrefix' => 'version',
61
                    'description' => 'Show the version'
62
                ],
63
            ]
64
        );
65 8
        $this->parser = self::createParser();
66 8
    }
67
68
    /**
69
     * @param array $args
70
     * @return int
71
     */
72 8
    public function handle(array $args)
73
    {
74
        try {
75 8
            $this->cli->arguments->parse($args);
76 1
        } catch (\Exception $e) {
77 1
            $this->cli->usage($args);
78 1
            return 100;
79
        }
80
81 7
        if ($this->cli->arguments->defined('version')) {
82 1
            $this->cli->out(Cli::VERSION);
83 1
            return 0;
84
        }
85
86 6
        $this->cli->out(sprintf('PHPAssumptions analyser v%s by @rskuipers', Cli::VERSION))->br();
87
88 6
        $target = $this->cli->arguments->get('path');
89
90 6
        if (!is_string($target)) {
91
            $this->cli->error('Missing target path')->br();
92
            $this->cli->usage($args);
93
            return 100;
94
        }
95
96 6
        switch ($this->cli->arguments->get('format')) {
97 6
            case 'xml':
98 1
                $output = new XmlOutput($this->cli, $this->cli->arguments->get('output'));
99 1
                break;
100
            default:
101 5
                $output = new PrettyOutput($this->cli);
102 5
                break;
103
        }
104
105 6
        $excludes = $this->getPathsFromList($this->cli->arguments->get('exclude'));
106
107 6
        $nodeTraverser = new NodeTraverser();
108
109 6
        $analyser = new Analyser(
110 6
            $this->parser,
0 ignored issues
show
Compatibility introduced by
$this->parser of type object<PhpParser\Parser> is not a sub-type of object<PhpParser\Parser\Multiple>. It seems like you assume a concrete implementation of the interface PhpParser\Parser to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
111 6
            $nodeTraverser,
112 6
            $excludes
113
        );
114
115 6
        $nodeTraverser->addVisitor(new NodeVisitor($analyser, new Detector()));
116
117 6
        $target = $this->cli->arguments->get('path');
118 6
        $targets = $this->getPaths($target);
119
120 6
        $result = $analyser->analyse($targets);
121
122 6
        $output->output($result);
123
124 6
        if ($result->getAssumptionsCount() > 0) {
125 4
            return 110;
126
        }
127
128 2
        return 0;
129
    }
130
131
    /**
132
     * @param string $list
133
     * @return array
134
     */
135 6
    private function getPathsFromList($list)
136
    {
137 6
        $paths = [];
138 6
        if (strlen($list) > 0) {
139 3
            $items = explode(',', $list);
140 3
            foreach ($items as $item) {
141 3
                $paths = array_merge($paths, $this->getPaths($item));
142
            }
143
        }
144
145 6
        return $paths;
146
    }
147
148
    /**
149
     * @param string $fromPath
150
     * @return array
151
     */
152 6
    private function getPaths($fromPath)
153
    {
154 6
        $paths = [];
155 6
        if (is_file($fromPath)) {
156 4
            $paths[] = $fromPath;
157
        } else {
158 3
            $directory = new \RecursiveDirectoryIterator($fromPath);
159 3
            $iterator = new \RecursiveIteratorIterator($directory);
160 3
            $regex = new \RegexIterator($iterator, '/^.+\.php$/i', \RecursiveRegexIterator::GET_MATCH);
161
162 3
            foreach ($regex as $file) {
163 3
                $paths[] = $file[0];
164
            }
165
        }
166
167 6
        return $paths;
168
    }
169
}
170