GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 61de95...83d765 )
by Miles
03:23
created

Vars   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 359
Duplicated Lines 4.46 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 97.69%

Importance

Changes 7
Bugs 2 Features 2
Metric Value
wmc 42
c 7
b 2
f 2
lcom 1
cbo 4
dl 16
loc 359
ccs 127
cts 130
cp 0.9769
rs 8.2951

17 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 24 3
B parseOptions() 0 22 5
A makeCache() 0 5 1
A makePaths() 0 9 3
A makeLoader() 0 5 1
A makeVariables() 0 14 3
A loadFromCache() 0 23 3
B pathsLoadedCheck() 0 18 5
A getBasePath() 0 4 1
A setBasePath() 16 16 3
A addResource() 0 7 1
A updateResource() 0 5 1
B resourceImported() 0 11 6
A getResource() 0 10 3
A getResources() 0 4 1
A getVariables() 0 4 1
A getCache() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Vars 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 Vars, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * This file is part of the m1\vars library
5
 *
6
 * (c) m1 <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @package     m1/vars
12
 * @version     0.1.0
13
 * @author      Miles Croxford <[email protected]>
14
 * @copyright   Copyright (c) Miles Croxford <[email protected]>
15
 * @license     http://github.com/m1/vars/blob/master/LICENSE
16
 * @link        http://github.com/m1/vars/blob/master/README.MD Documentation
17
 */
18
19
namespace M1\Vars;
20
21
use M1\Vars\Cache\CacheProvider;
22
use M1\Vars\Loader\LoaderProvider;
23
use M1\Vars\Resource\AbstractResource;
24
use M1\Vars\Resource\ResourceProvider;
25
use M1\Vars\Resource\VariableResource;
26
27
/**
28
 * Vars core class
29
 *
30
 * @since 0.1.0
31
 */
32
class Vars extends AbstractResource
33
{
34
    /**
35
     * The base path for the Vars config and cache folders
36
     *
37
     * @var string $base_path
38
     */
39
    private $base_path;
40
41
    /**
42
     * The cache object if the cache is wanted, else false
43
     *
44
     * @var \M1\Vars\Cache\CacheProvider $cache
45
     */
46
    public $cache;
47
48
    /**
49
     * The default options for Vars
50
     *
51
     * @var array $default_options
52
     */
53
    private $default_options = array(
54
        'base_path' => null,
55
        'cache' => true,
56
        'cache_path' => null,
57
        'cache_expire' => 300, // 5 minutes
58
        'loaders' => array('ini', 'json', 'php', 'toml', 'yaml', 'xml',)
59
    );
60
61
    /**
62
     * The loaderProvider for Vars supplies the file loaders and the extensions that are supported
63
     *
64
     * @var \M1\Vars\Loader\LoaderProvider $loader
65
     */
66
    public $loader;
67
68
    /**
69
     * Have the base and cache paths been set
70
     *
71
     * @var bool $paths_loaded
72
     */
73
    private $paths_loaded = false;
74
75
    /**
76
     * The imported resources
77
     *
78
     * @var array $resources
79
     */
80
    private $resources = array();
81
82
    /**
83
     * The words to be replaced in the config files
84
     *
85
     * @var array $variables
86
     */
87
    private $variables = array();
88
89
    /**
90
     * Creates a new instance of Vars
91
     *
92
     * @param string|array $resource The main configuration resource
93
     * @param array        $options  The options being used for Vars
94
     */
95
    public function __construct($resource, $options = array())
96
    {
97
        $options = $this->parseOptions($options);
98
        $this->makeCache($options, $resource);
99
        $this->makePaths($options);
100
101 63
        if (!$this->cache->checkCache()) {
102
            $this->makeLoader($options);
103 63
            $this->makeVariables($options);
104 63
105 62
            $resource = new ResourceProvider($this, $resource);
106
        }
107 61
108 61
        if ($this->cache->isHit()) {
109 59
            $this->loadFromCache();
110
        } else {
111 58
            $resource->mergeParentContent();
0 ignored issues
show
Bug introduced by
It seems like $resource is not always an object, but can also be of type string|array. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
112 47
            $this->content = $resource->getContent();
113
114 47
            $this->cache->setTime(time());
115 2
            $this->cache->makeCache($this);
116 2
117 47
        }
118 47
    }
119
120 47
    /**
121 47
     * Parses the options so Vars can use them
122
     *
123
     * @param array $options  The options being used for Vars
124 47
     *
125
     * @return array The parsed options
126
     */
127
    private function parseOptions(array $options)
128
    {
129
        $parsed_options = array_merge($this->default_options, $options);
130
131
        if (isset($options['loaders'])) {
132
            $loaders = array();
133 63
134
            if (is_array($options['loaders']) && !empty($options['loaders'])) {
135 63
                $loaders = $options['loaders'];
136 1
            } elseif (is_string($options['loaders'])) {
137 1
                $loaders[] = $options['loaders'];
138 62
            } else {
139
                $loaders = $this->default_options['loaders'];
140 62
            }
141 8
142 3
            $parsed_options['loaders'] = $loaders;
143 8
        } else {
144 4
            $parsed_options['loaders'] = $this->default_options['loaders'];
145 4
        }
146 1
147
        return $parsed_options;
148
    }
149 8
150 54
    /**
151
     * Makes the CacheProvider with the options
152
     *
153 62
     * @param array        $options  The options being used for Vars
154
     * @param array|string $resource The main configuration resource
155
     */
156 63
    private function makeCache($options, $resource)
157
    {
158
        $cache = new CacheProvider($resource, $options);
159
        $this->cache = $cache;
160
    }
161
162
    /**
163
     * Sets the base path if the options have been set and the cache path if the cache path has not been set but the
164
     * base path has
165 63
     *
166
     * @param array $options The options being used for Vars
167 63
     */
168 62
    private function makePaths($options)
169 62
    {
170
        $this->setBasePath($options['base_path']);
171
172
        if (is_null($options['cache_path']) && !is_null($options['base_path'])) {
173
            $this->cache->setPath($options['base_path']);
174
            $this->paths_loaded = true;
175
        }
176
    }
177 62
178
    /**
179 62
     * Makes the LoaderProvider with the options
180
     *
181 61
     * @param array $options  The options being used for Vars
182 1
     */
183 1
    private function makeLoader($options)
184 1
    {
185 61
        $loader = new LoaderProvider($options, $this->default_options['loaders']);
186
        $this->loader = $loader;
187
    }
188
    /**
189
     * Sets the replacement variables if the option has been set
190
     *
191
     * @param array|null $options The options being used for Vars
192
     */
193 61
    private function makeVariables($options)
194
    {
195 61
        if (isset($options['variables'])) {
196
            $variables = new VariableResource($this, $options['variables']);
197 61
198 61
            $v = array();
199 2
200 2
            foreach ($variables->getVariables() as $variable_key => $variable_value) {
201 60
                $v["%".$variable_key.'%'] = $variable_value;
202
            }
203 61
204
            $this->variables = $v;
205 61
        }
206
    }
207 61
208 60
    /**
209 59
     * Loads the cached file into the current class
210
     */
211
    private function loadFromCache()
212
    {
213
        $this->cache->load();
214
215
        $passed_keys = array(
216
            'base_path',
217
            'content',
218
            'extensions',
219
            'loaders',
220
            'resources',
221 61
            'variables',
222
        );
223 61
224
        $loaded_vars = get_object_vars($this->cache->getLoadedVars());
225 61
226 61
        foreach ($loaded_vars as $key => $value) {
227 58
            if (in_array($key, $passed_keys)) {
228 58
                $this->$key = $value;
229
            }
230 61
        }
231 1
232
        $this->cache->setTime($loaded_vars['cache']->getTime());
233
    }
234 60
235 60
    /**
236
     * Checks if the base and cache paths have been set, if not set then will use the $resource as the base path
237
     *
238 60
     * @param string $resource The resource to use to set the paths if they haven't been set
239
     */
240
    public function pathsLoadedCheck($resource)
241
    {
242 60
        if (!$this->paths_loaded) {
243
            $base_path = $this->getBasePath();
244
245
            if (!$base_path) {
246
                $file = pathinfo(realpath($resource));
247
                $base_path = $file['dirname'];
248
                $this->setBasePath($base_path);
249
            }
250 59
251
            if ($this->cache->getProvide() && !$this->cache->getPath()) {
252 59
                $this->cache->setPath($base_path);
253 4
            }
254
255 3
            $this->paths_loaded = true;
256
        }
257 3
    }
258 3
259 3
    /**
260
     * Get the Vars base path
261 3
     *
262 3
     * @return string The Vars base path
263 58
     */
264
    public function getBasePath()
265
    {
266
        return $this->base_path;
267
    }
268 2
269
    /**
270 2
     * Set the Vars base path
271
     *
272
     * @param string $base_path The base path to set
273 2
     *
274 2
     * @throws \InvalidArgumentException If the base path does not exist or is not writable
275 2
     *
276 2
     * @return \M1\Vars\Vars
277 2
     */
278 2 View Code Duplication
    public function setBasePath($base_path)
0 ignored issues
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...
279 2
    {
280
        if (is_null($base_path)) {
281 2
            return;
282
        }
283 2
284 2
        if (!is_dir($base_path)) {
285 2
            throw new \InvalidArgumentException(sprintf(
286 2
                "'%s' base path does not exist or is not writable",
287 2
                $base_path
288
            ));
289 2
        }
290 2
291
        $this->base_path = realpath($base_path);
292
        return $this;
293
    }
294
    
295
    /**
296
     * Adds a resource to $this->resources
297
     *
298
     * @param string $resource Resource to add to the stack
299
     *
300
     * @return int The position of the added resource
301
     */
302
    public function addResource($resource)
303 60
    {
304
        $r = realpath($resource);
305 60
        $pos = count($this->resources);
306
        $this->resources[$pos] = $r;
307 60
        return $pos;
308 60
    }
309 60
310
    /**
311 60
     * Updates the string resource with the FileResource
312 1
     *
313
     * @param \M1\Vars\Resource\FileResource $resource The FileResource to add
314
     * @param int                            $pos      The position of the string resource
315 59
     *
316
     * @return \M1\Vars\Vars
317
     */
318
    public function updateResource($resource, $pos)
319
    {
320
        $this->resources[$pos] = $resource;
321
        return $this;
322
    }
323 53
324
    /**
325 53
     * Tests to see if the resource has been imported already -- this is to avoid getting into a infinite loop
326 52
     *
327
     * @param \M1\Vars\Resource\FileResource|string $resource Resource to check
328 52
     *
329 50
     * @return bool Has resource already been imported
330 50
     */
331 50
    public function resourceImported($resource)
332 50
    {
333
        $resource = realpath($resource);
334 52
        foreach ($this->getResources() as $r) {
335
            if ((is_a($r, 'M1\Vars\Resource\FileResource') && $resource === $r->getFile()) ||
336
                (is_string($r) && $resource === $r)) {
337
                return true;
338 52
            }
339 52
        }
340 53
        return false;
341
    }
342
343
    /**
344
     * Searches the resource stack for a certain resource
345
     *
346
     * @param string $resource The resource to search for
347 53
     *
348
     * @return bool Returns the resource if found
349 53
     */
350
    public function getResource($resource)
351
    {
352
        foreach ($this->getResources() as $r) {
353
            if ($resource === $r->getFilename()) {
354
                return $r;
355
            }
356
        }
357 4
358
        return false;
359 4
    }
360
361
    /**
362
     * Returns the imported resources
363
     *
364
     * @return array The Vars imported resources
365
     */
366
    public function getResources()
367 53
    {
368
        return $this->resources;
369 53
    }
370
371
    /**
372
     * Returns the Vars replacement variables
373
     *
374
     * @return array The Vars replacement variables
375
     */
376
    public function getVariables()
377
    {
378
        return $this->variables;
379
    }
380
381 62
    /**
382
     * Returns the CacheProvider if set, if not return false
383 62
     *
384 58
     * @return \M1\Vars\Cache\CacheProvider|false The CacheProvider or false
385
     */
386
    public function getCache()
387 54
    {
388 1
        return $this->cache;
389 1
    }
390
}
391