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

includes/Console/Parser.php (1 issue)

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