Completed
Push — master ( 4eb4a8...a52438 )
by Henry
07:48
created

includes/Console/Parser.php (1 issue)

a variable is defined regardless of execution path.

Bug Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Redaxscript\Console;
3
4
use Redaxscript\Request;
5
use function array_filter;
6
use function array_key_exists;
7
use function explode;
8
use function is_array;
9
use function next;
10
use function strpos;
11
use function substr;
12
13
/**
14
 * parent class to parse the command line interface
15
 *
16
 * @since 3.0.0
17
 *
18
 * @package Redaxscript
19
 * @category Console
20
 * @author Henry Ruhs
21
 */
22
23
class Parser
24
{
25
	/**
26
	 * instance of the request class
27
	 *
28
	 * @var Request
29
	 */
30
31
	protected $_request;
32
33
	/**
34
	 * array of parsed arguments
35
	 *
36
	 * @var array
37
	 */
38
39
	protected $_argumentArray = [];
40
41
	/**
42
	 * array of parsed options
43
	 *
44
	 * @var array
45
	 */
46
47
	protected $_optionArray = [];
48
49
	/**
50
	 * constructor of the class
51
	 *
52
	 * @since 3.0.0
53
	 *
54
	 * @param Request $request instance of the request class
55
	 */
56
57 13
	public function __construct(Request $request)
58
	{
59 13
		$this->_request = $request;
60 13
	}
61
62
	/**
63
	 * init the class
64
	 *
65
	 * @param string $mode name of the mode
66
	 *
67
	 * @since 3.0.0
68
	 */
69
70 11
	public function init(string $mode = null) : void
71
	{
72 11
		if ($mode === 'cli')
73
		{
74 11
			$argumentArray = $this->_request->getServer('argv');
75 11
			unset($argumentArray[0]);
76
		}
77 11
		if ($mode === 'template')
78
		{
79
			$argumentArray = array_filter(explode(' ', $this->_request->getStream('argv')));
80
		}
81 11
		$this->_parseArgument($argumentArray);
0 ignored issues
show
The variable $argumentArray 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...
82 11
	}
83
84
	/**
85
	 * get the value from arguments
86
	 *
87
	 * @since 3.0.0
88
	 *
89
	 * @param string $key key of the item
90
	 *
91
	 * @return string|null
92
	 */
93
94 2
	public function getArgument(string $key = null) : ?string
95
	{
96 2
		if (is_array($this->_argumentArray) && array_key_exists($key, $this->_argumentArray))
97
		{
98 1
			return $this->_argumentArray[$key];
99
		}
100 1
		return null;
101
	}
102
103
	/**
104
	 * get the array from arguments
105
	 *
106
	 * @since 4.0.0
107
	 *
108
	 * @return array
109
	 */
110
111 5
	public function getArgumentArray() : array
112
	{
113 5
		return $this->_argumentArray;
114
	}
115
116
	/**
117
	 * get the value from options
118
	 *
119
	 * @since 3.0.0
120
	 *
121
	 * @param string $key key of the item
122
	 *
123
	 * @return string|null
124
	 */
125
126 2
	public function getOption(string $key = null) : ?string
127
	{
128 2
		if (is_array($this->_optionArray) && array_key_exists($key, $this->_optionArray))
129
		{
130 1
			return $this->_optionArray[$key];
131
		}
132 1
		return null;
133
	}
134
135
	/**
136
	 * get the array from options
137
	 *
138
	 * @since 4.0.0
139
	 *
140
	 * @return array
141
	 */
142
143 4
	public function getOptionArray() : array
144
	{
145 4
		return $this->_optionArray;
146
	}
147
148
	/**
149
	 * set the value to arguments
150
	 *
151
	 * @since 3.0.0
152
	 *
153
	 * @param string $key key of the item
154
	 * @param string|int $value value of the item
155
	 */
156
157 7
	public function setArgument(string $key = null, $value = null) : void
158
	{
159 7
		$this->_argumentArray[$key] = $value;
160 7
	}
161
162
	/**
163
	 * set the value to options
164
	 *
165
	 * @since 3.0.0
166
	 *
167
	 * @param string $key key of the item
168
	 * @param string|int $value value of the item
169
	 */
170
171 5
	public function setOption(string $key = null, $value = null) : void
172
	{
173 5
		$this->_optionArray[$key] = $value;
174 5
	}
175
176
	/**
177
	 * parse raw argument
178
	 *
179
	 * @since 3.0.0
180
	 *
181
	 * @param array|null $argumentArray raw argument to be parsed
182
	 */
183
184 11
	protected function _parseArgument(?array $argumentArray = []) : void
185
	{
186 11
		$doSkip = false;
187 11
		$argumentKey = 0;
188 11
		if (is_array($argumentArray))
189
		{
190 8
			foreach ($argumentArray as $value)
191
			{
192 8
				$next = next($argumentArray);
193 8
				if (strpos($value, '-') === 0)
194
				{
195 4
					$offset = strpos($value, '--') === 0 ? 2 : 1;
196 4
					$optionArray = $this->_parseOption($value, $next, $offset);
197 4
					$doSkip = $optionArray['value'] === $next;
198 4
					$this->setOption($optionArray['key'], $optionArray['value']);
199
				}
200 8
				else if ($value && !$doSkip)
201
				{
202 6
					$this->setArgument($argumentKey++, $value);
203
				}
204
			}
205
		}
206 11
	}
207
208
	/**
209
	 * parse raw option
210
	 *
211
	 * @since 3.0.0
212
	 *
213
	 * @param string $option raw option to be parsed
214
	 * @param string $next raw next to be parsed
215
	 * @param int $offset offset of the raw option
216
	 *
217
	 * @return array
218
	 */
219
220 4
	protected function _parseOption(string $option = null, string $next = null, int $offset = null) : array
221
	{
222 4
		$equalPosition = strpos($option, '=');
223 4
		if ($equalPosition)
224
		{
225
			return
226
			[
227 4
				'key' => substr($option, $offset, $equalPosition - $offset),
228 4
				'value' => substr($option, $equalPosition + 1)
229
			];
230
		}
231
		return
232
		[
233 4
			'key' => substr($option, $offset),
234 4
			'value' => !$next || strpos($next, '-') === 0 ? true : $next
235
		];
236
	}
237
}
238