Completed
Push — master ( 22b422...fbd4ac )
by Peter
05:54
created

NsCache::setOptions()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 14
ccs 12
cts 12
cp 1
rs 8.8571
cc 5
eloc 6
nc 4
nop 1
crap 5
1
<?php
2
3
/**
4
 * This software package is licensed under AGPL, Commercial license.
5
 *
6
 * @package maslosoft/addendum
7
 * @licence AGPL, Commercial
8
 * @copyright Copyright (c) Piotr Masełkowski <[email protected]> (Meta container, further improvements, bugfixes)
9
 * @copyright Copyright (c) Maslosoft (Meta container, further improvements, bugfixes)
10
 * @copyright Copyright (c) Jan Suchal (Original version, builder, parser)
11
 * @link http://maslosoft.com/addendum/ - maslosoft addendum
12
 * @link https://code.google.com/p/addendum/ - original addendum project
13
 */
14
15
namespace Maslosoft\Addendum\Cache;
16
17
use Maslosoft\Addendum\Addendum;
18
use Maslosoft\Addendum\Helpers\SoftIncluder;
19
use Maslosoft\Addendum\Options\MetaOptions;
20
use Maslosoft\Cli\Shared\Helpers\PhpExporter;
21
22
/**
23
 * Meta Namespaces cache
24
 *
25
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
26
 */
27
class NsCache
28
{
29
30
	const FileName = '_ns.php';
31
32
	private $file = '';
33
34
	/**
35
	 * Addendum instance
36
	 * @var Addendum
37
	 */
38
	private $ad = null;
39
40
	/**
41
	 *
42
	 * @var
43
	 */
44
	private static $nsCache = [];
45
46
	/**
47
	 * Hash map of namespaces.
48
	 * Namespaces is key, while value is boolean and is not really relevant
49
	 * @var array
50
	 */
51
	private $namespaces;
52
53
	/**
54
	 * @internal Flag that will trigger cache validity check for namespaces cache
55
	 * @var bool
56
	 */
57
	public static $addeNs = true;
58
59 50
	public function __construct($path, Addendum $addendum, MetaOptions $options = null)
60
	{
61 50
		$this->file = sprintf('%s/%s', $path, self::FileName);
62 50
		$this->namespaces = $addendum->nameKeys;
63 50
		$this->ad = $addendum;
64 50
		$this->setOptions($options);
65 50
	}
66
67 54
	public function setOptions(MetaOptions $options = null)
68
	{
69 54
		if (!empty($options) && !empty($options->namespaces))
70 54
		{
71 4
			foreach ($options->namespaces as $ns)
72
			{
73 4
				if (empty($this->namespaces[$ns]))
74 4
				{
75 2
					self::$addeNs = true;
76 2
					$this->namespaces[$ns] = true;
77 2
				}
78 4
			}
79 4
		}
80 54
	}
81
82 2
	public function valid()
83
	{
84 2
		$ns = $this->get();
85 2
		$valid = $this->isValid($ns);
86
87
		// Ovverride existing cache if not valid
88 2
		if (!$valid)
89 2
		{
90 1
			$this->set();
91 1
		}
92 2
		return $valid;
93
	}
94
95 2
	public function get()
96
	{
97 2
		if (!empty(self::$nsCache[$this->file]))
98 2
		{
99 2
			return self::$nsCache[$this->file];
100
		}
101
		self::$nsCache[$this->file] = SoftIncluder::includeFile($this->file);
102
		return self::$nsCache[$this->file];
103
	}
104
105 47
	public function set()
106
	{
107 47
		foreach (array_keys($this->namespaces) as $name)
108
		{
109 47
			$ns[$name] = true;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ns was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ns = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
110 47
		}
111 47
		$data = PhpExporter::export($ns);
0 ignored issues
show
Bug introduced by
The variable $ns 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...
112 47
		$mask = umask(0);
113 47
		file_put_contents($this->file, $data);
114 47
		umask($mask);
115 47
		self::$nsCache[$this->file] = $ns;
116 47
	}
117
118
	public function remove()
119
	{
120
		unset(self::$nsCache[$this->file]);
121
		if (file_exists($this->file))
122
		{
123
			unlink($this->file);
124
		}
125
	}
126
127 2
	private function isValid($ns)
128
	{
129
		// Fresh data
130 2
		if (empty($ns))
131 2
		{
132
			return true;
133
		}
134
135
		// Additional check if added namespace manually
136 2
		if (self::$addeNs)
137 2
		{
138 2
			$addendumDiff = array_diff_key($this->ad->nameKeys, $this->namespaces);
139 2
			if (!empty($addendumDiff))
140 2
			{
141
				// Add missing namespaces to cache them
142 1
				foreach (array_keys($addendumDiff) as $ns)
143
				{
144 1
					$this->namespaces[$ns] = true;
145 1
				}
146 1
				self::$addeNs = false;
147 1
				return false;
148
			}
149 2
		}
150
		// Check if has all namespaces
151 2
		$cachedDiff = array_diff_key($this->namespaces, $ns);
152 2
		if (empty($cachedDiff))
153 2
		{
154 2
			self::$addeNs = false;
155 2
			return true;
156
		}
157 1
		return false;
158
	}
159
160
}
161