Completed
Push — master ( 8b1d72...c8f3ab )
by Jonathan
02:39
created

Configuration::setWatchDirectories()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 1
crap 3
1
<?php
2
3
namespace PHPChunkit;
4
5
use InvalidArgumentException;
6
use Symfony\Component\EventDispatcher\EventDispatcher;
7
8
/**
9
 * @testClass PHPChunkit\Test\ConfigurationTest
10
 */
11
class Configuration
12
{
13
    /**
14
     * @var string
15
     */
16
    private $rootDir = '';
17
18
    /**
19
     * @var array
20
     */
21
    private $watchDirectories = [];
22
23
    /**
24
     * @var string
25
     */
26
    private $testsDirectory = '';
27
28
    /**
29
     * @var string
30
     */
31
    private $bootstrapPath = '';
32
33
    /**
34
     * @var string
35
     */
36
    private $phpunitPath = 'vendor/bin/phpunit';
37
38
    /**
39
     * @var null|EventDispatcher
40
     */
41
    private $eventDispatcher;
42
43
    /**
44
     * @var null|DatabaseSandbox
45
     */
46
    private $databaseSandbox;
47
48
    /**
49
     * @var string
50
     */
51
    private $memoryLimit = '256M';
52
53
    /**
54
     * @var int
55
     */
56
    private $numChunks = 1;
57
58 3
    public static function createFromXmlFile(string $path) : self
59
    {
60 3
        if (!file_exists($path)) {
61 1
            throw new \InvalidArgumentException(sprintf('XML file count not be found at path "%s"', $path));
62
        }
63
64 2
        $configuration = new self();
65
66 2
        $xml = simplexml_load_file($path);
67 2
        $attributes = $xml->attributes();
68
69
        $xmlMappings = [
70
            'root-dir' => [
71
                'type' => 'string',
72
                'setter' => 'setRootDir'
73 2
            ],
74
            'bootstrap' => [
75
                'type' => 'string',
76
                'setter' => 'setBootstrapPath'
77
            ],
78
            'tests-dir' => [
79
                'type' => 'string',
80
                'setter' => 'setTestsDirectory'
81
            ],
82
            'phpunit-path' => [
83
                'type' => 'string',
84
                'setter' => 'setPhpunitPath'
85
            ],
86
            'memory-limit' => [
87
                'type' => 'string',
88
                'setter' => 'setMemoryLimit'
89
            ],
90
            'num-chunks' => [
91
                'type' => 'integer',
92
                'setter' => 'setNumChunks'
93
            ],
94
            'watch-directories' => [
95
                'type' => 'array',
96
                'setter' => 'setWatchDirectories',
97
                'xmlName' => 'watch-directory',
98
            ],
99
            'database-names' => [
100
                'type' => 'array',
101
                'setter' => 'setDatabaseNames',
102
                'xmlName' => 'database-name',
103
            ],
104
        ];
105
106 2
        foreach ($xmlMappings as $name => $mapping) {
107 2
            if ($mapping['type'] === 'array') {
108 2
                $value = (array) $xml->{$name}->{$mapping['xmlName']};
109 2
            } elseif (isset($attributes[$name])) {
110 2
                $value = $attributes[$name];
111
112 2
                settype($value, $mapping['type']);
113
            }
114
115 2
            $configuration->{$mapping['setter']}($value);
0 ignored issues
show
Bug introduced by
The variable $value does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
116
        }
117
118 2
        $events = (array) $xml->{'events'};
119 2
        $listeners = $events['listener'] ?? null;
120
121 2
        if ($listeners) {
122 2
            foreach ($listeners as $listener) {
123 2
                $configuration->addListener(
124 2
                    (string) $listener->attributes()['event'],
125 2
                    (string) $listener->class
126
                );
127
            }
128
        }
129
130 2
        return $configuration;
131
    }
132
133 2
    public function addListener(
134
        string $eventName,
135
        string $className,
136
        int $priority = 0) : ListenerInterface
0 ignored issues
show
Unused Code introduced by
The parameter $priority is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
137
    {
138 2
        $listener = new $className($this);
139
140 2
        if (!$listener instanceof ListenerInterface) {
141
            throw new InvalidArgumentException(
142
                sprintf('%s does not implement %s', $className, ListenerInterface::class)
143
            );
144
        }
145
146 2
        $this->getEventDispatcher()->addListener(
147 2
            $eventName, [$listener, 'execute']
148
        );
149
150 2
        return $listener;
151
    }
152
153 10 View Code Duplication
    public function setRootDir(string $rootDir) : self
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
    {
155 10
        if (!is_dir($rootDir)) {
156 1
            throw new \InvalidArgumentException(
157 1
                sprintf('Root directory "%s" does not exist.', $rootDir)
158
            );
159
        }
160
161 9
        $this->rootDir = realpath($rootDir);
162
163 9
        return $this;
164
    }
165
166 4
    public function getRootDir() : string
167
    {
168 4
        return $this->rootDir;
169
    }
170
171 5
    public function setWatchDirectories(array $watchDirectories) : self
172
    {
173 5
        foreach ($watchDirectories as $key => $watchDirectory) {
174 5
            if (!is_dir($watchDirectory)) {
175 1
                throw new \InvalidArgumentException(
176 1
                    sprintf('Watch directory "%s" does not exist.', $watchDirectory)
177
                );
178
            }
179
180 4
            $watchDirectories[$key] = realpath($watchDirectory);
181
        }
182
183 4
        $this->watchDirectories = $watchDirectories;
184
185 4
        return $this;
186
    }
187
188 3
    public function getWatchDirectories() : array
189
    {
190 3
        return $this->watchDirectories;
191
    }
192
193 5 View Code Duplication
    public function setTestsDirectory(string $testsDirectory) : self
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
    {
195 5
        if (!is_dir($testsDirectory)) {
196 1
            throw new \InvalidArgumentException(
197 1
                sprintf('Tests directory "%s" does not exist.', $testsDirectory)
198
            );
199
        }
200
201 4
        $this->testsDirectory = realpath($testsDirectory);
202
203 4
        return $this;
204
    }
205
206 3
    public function getTestsDirectory() : string
207
    {
208 3
        return $this->testsDirectory;
209
    }
210
211 4 View Code Duplication
    public function setBootstrapPath(string $bootstrapPath) : self
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
212
    {
213 4
        if (!file_exists($bootstrapPath)) {
214 1
            throw new \InvalidArgumentException(
215 1
                sprintf('Bootstrap path "%s" does not exist.', $bootstrapPath)
216
            );
217
        }
218
219 3
        $this->bootstrapPath = realpath($bootstrapPath);
220
221 3
        return $this;
222
    }
223
224 3
    public function getBootstrapPath() : string
225
    {
226 3
        return $this->bootstrapPath;
227
    }
228
229 10 View Code Duplication
    public function setPhpunitPath(string $phpunitPath) : self
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
    {
231 10
        if (!file_exists($phpunitPath)) {
232 1
            throw new \InvalidArgumentException(
233 1
                sprintf('PHPUnit path "%s" does not exist.', $phpunitPath)
234
            );
235
        }
236
237 9
        $this->phpunitPath = realpath($phpunitPath);
238
239 9
        return $this;
240
    }
241
242 3
    public function getPhpunitPath() : string
243
    {
244 3
        return $this->phpunitPath;
245
    }
246
247 1
    public function setDatabaseSandbox(DatabaseSandbox $databaseSandbox) : self
248
    {
249 1
        $this->databaseSandbox = $databaseSandbox;
250
251 1
        return $this;
252
    }
253
254 4
    public function getDatabaseSandbox() : DatabaseSandbox
255
    {
256 4
        if ($this->databaseSandbox === null) {
257 4
            $this->databaseSandbox = new DatabaseSandbox();
258
        }
259
260 4
        return $this->databaseSandbox;
261
    }
262
263 3
    public function setDatabaseNames(array $databaseNames) : self
264
    {
265 3
        $this->getDatabaseSandbox()->setDatabaseNames($databaseNames);
266
267 3
        return $this;
268
    }
269
270 1
    public function setSandboxEnabled(bool $sandboxEnabled) : self
271
    {
272 1
        $this->getDatabaseSandbox()->setSandboxEnabled($sandboxEnabled);
273
274 1
        return $this;
275
    }
276
277 2
    public function setMemoryLimit(string $memoryLimit) : self
278
    {
279 2
        $this->memoryLimit = $memoryLimit;
280
281 2
        return $this;
282
    }
283
284 2
    public function getMemoryLimit() : string
285
    {
286 2
        return $this->memoryLimit;
287
    }
288
289 2
    public function setNumChunks(int $numChunks) : self
290
    {
291 2
        $this->numChunks = $numChunks;
292
293 2
        return $this;
294
    }
295
296 1
    public function getNumChunks() : int
297
    {
298 1
        return $this->numChunks;
299
    }
300
301 1
    public function setEventDispatcher(EventDispatcher $eventDispatcher) : self
302
    {
303 1
        $this->eventDispatcher = $eventDispatcher;
304
305 1
        return $this;
306
    }
307
308 3
    public function getEventDispatcher() : EventDispatcher
309
    {
310 3
        if ($this->eventDispatcher === null) {
311 3
            $this->eventDispatcher = new EventDispatcher();
312
        }
313
314 3
        return $this->eventDispatcher;
315
    }
316
317 2
    public function throwExceptionIfConfigurationIncomplete()
318
    {
319 2
        if (!$this->rootDir) {
320 1
            throw new \InvalidArgumentException('You must configure a root directory.');
321
        }
322
323 1
        if (empty($this->watchDirectories)) {
324
            throw new \InvalidArgumentException('You must configure a watch directory.');
325
        }
326
327 1
        if (!$this->testsDirectory) {
328
            throw new \InvalidArgumentException('You must configure a tests directory.');
329
        }
330
331 1
        if (!$this->phpunitPath) {
332
            throw new \InvalidArgumentException('You must configure a phpunit path.');
333
        }
334
335 1
        return true;
336
    }
337
}
338