This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * See class comment |
||
4 | * |
||
5 | * PHP Version 5 |
||
6 | * |
||
7 | * @category Netresearch |
||
8 | * @package Netresearch\Kite |
||
9 | * @author Christian Opitz <[email protected]> |
||
10 | * @license http://www.netresearch.de Netresearch Copyright |
||
11 | * @link http://www.netresearch.de |
||
12 | */ |
||
13 | |||
14 | namespace Netresearch\Kite; |
||
15 | |||
16 | |||
17 | use Netresearch\Kite\Service\Console; |
||
18 | use Symfony\Component\Console\Input\InputArgument; |
||
19 | use Symfony\Component\Console\Input\InputDefinition; |
||
20 | use Symfony\Component\Console\Input\InputOption; |
||
21 | |||
22 | /** |
||
23 | * Job - the outermost task object |
||
24 | * |
||
25 | * @category Netresearch |
||
26 | * @package Netresearch\Kite |
||
27 | * @author Christian Opitz <[email protected]> |
||
28 | * @license http://www.netresearch.de Netresearch Copyright |
||
29 | * @link http://www.netresearch.de |
||
30 | */ |
||
31 | class Job extends Tasks |
||
32 | { |
||
33 | /** |
||
34 | * @var array |
||
35 | */ |
||
36 | protected $definitions = array(); |
||
37 | |||
38 | /** |
||
39 | * @var bool |
||
40 | */ |
||
41 | protected $dryRun = false; |
||
42 | |||
43 | /** |
||
44 | * @var bool |
||
45 | */ |
||
46 | private $started = false; |
||
0 ignored issues
–
show
Comprehensibility
introduced
by
![]() |
|||
47 | |||
48 | /** |
||
49 | * @var bool |
||
50 | */ |
||
51 | private $initialized = false; |
||
0 ignored issues
–
show
|
|||
52 | |||
53 | /** |
||
54 | * Job constructor. |
||
55 | * |
||
56 | * @param Console $console Console |
||
57 | */ |
||
58 | public function __construct(Console $console) |
||
59 | { |
||
60 | static $kite, $composer; |
||
61 | |||
62 | $this->console = $console; |
||
63 | |||
64 | $this->offsetSet('job', $this); |
||
65 | $this->offsetSet('config', $console->getConfig()); |
||
66 | if (!$kite) { |
||
67 | $kite = array( |
||
68 | 'path' => $path = dirname(__DIR__), |
||
69 | 'dir' => $console->getFilesystem()->findShortestPath(getcwd(), $path) |
||
70 | ); |
||
71 | } |
||
72 | $this->offsetSet('kite', $kite); |
||
73 | |||
74 | parent::__construct($this); |
||
75 | |||
76 | if (!$composer) { |
||
77 | $composer = $this->factory->createTask('Netresearch\\Kite\\Service\\Composer', $this); |
||
78 | } |
||
79 | |||
80 | $this->offsetSet('composer', $composer); |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * Variable configuration |
||
85 | * |
||
86 | * @return array |
||
87 | */ |
||
88 | protected function configureVariables() |
||
89 | { |
||
90 | return [ |
||
91 | 'options' => [ |
||
92 | 'type' => 'array', |
||
93 | 'label' => 'Options to expose on the console app - keys are camelCase ' |
||
94 | . " variable names, which are used as option names lowercase-dashed.\n" |
||
95 | . "Values contain variable configuration with keys:\n" |
||
96 | . " 'type': Variable type (array, string, etc.)\n" |
||
97 | . " 'label': The label to show on --help\n" |
||
98 | . " 'default': Default value (if any, invalid for booleans without explicit mode)\n" |
||
99 | . " 'mode': Mode for the \\Symfony\\Component\\Console\\Input\\InputOption\n" |
||
100 | . " 'shortcut': Shortcut for the \\Symfony\\Component\\Console\\Input\\InputOption" |
||
101 | ], |
||
102 | 'arguments' => [ |
||
103 | 'type' => 'array', |
||
104 | 'label' => 'Arguments to expose on the console app - keys are camelCase ' |
||
105 | . " variable names, which are used as argument names lowercase-dashed.\n" |
||
106 | . "Values contain variable configuration with keys:\n" |
||
107 | . " 'type': Variable type (array, string, etc.)\n" |
||
108 | . " 'label': The label to show on --help\n" |
||
109 | . " 'default': Default value (if any, invalid for booleans without explicit mode)\n" |
||
110 | . " 'mode': Mode for the \\Symfony\\Component\\Console\\Input\\InputArgument" |
||
111 | ] |
||
112 | ] + parent::configureVariables(); |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Configure options and arguments |
||
117 | * |
||
118 | * @param string $name The name |
||
119 | * @param mixed $value The value |
||
120 | * |
||
121 | * @return void |
||
122 | */ |
||
123 | public function offsetSet($name, $value) |
||
124 | { |
||
125 | if ($name === 'options' || $name === 'arguments') { |
||
126 | $type = substr($name, 0, -1); |
||
127 | if (!is_array($value)) { |
||
128 | throw new Exception($name . ' must be array'); |
||
129 | } |
||
130 | foreach ($value as $variable => $config) { |
||
131 | $from = $this->camelCaseToLowerCaseDashed($variable); |
||
132 | $this->definitions[$from] = array( |
||
133 | 'context' => $this, |
||
134 | 'variable' => $variable, |
||
135 | 'type' => $type, |
||
136 | 'config' => $config |
||
137 | ); |
||
138 | } |
||
139 | return; |
||
140 | } |
||
141 | parent::offsetSet($name, $value); |
||
142 | } |
||
143 | |||
144 | |||
145 | /** |
||
146 | * Run an array of tasks |
||
147 | * |
||
148 | * @return $this |
||
149 | */ |
||
150 | public function run() |
||
151 | { |
||
152 | $this->started = true; |
||
153 | |||
154 | if (isset($this->console->getConfig()['workspace'])) { |
||
155 | $this->console->getFilesystem()->ensureDirectoryExists($this->expand('{config["workspace"]}')); |
||
156 | } |
||
157 | |||
158 | $input = $this->console->getInput(); |
||
159 | $this->dryRun = $input->getOption('dry-run'); |
||
160 | foreach ($this->definitions as $from => $info) { |
||
161 | $config = $info['config']; |
||
162 | if ($info['type'] === 'option') { |
||
163 | if ($input->hasOption($from)) { |
||
164 | $value = $input->getOption($from); |
||
165 | if (($value === null || is_array($value) && !isset($value[0]) && count($value) <= 1) |
||
166 | && preg_match('/(^|\|)bool(ean)?($|\|)/', $config['type']) && strpos($config['type'], '|') |
||
167 | ) { |
||
168 | if ($input->hasParameterOption($opt = '--' . $from) |
||
169 | || array_key_exists('shortcut', $config) |
||
170 | && $input->hasParameterOption($opt = '-' . $config['shortcut']) |
||
171 | ) { |
||
172 | // Set value to true, when option has no value |
||
173 | $value = true; |
||
174 | } |
||
175 | } |
||
176 | $info['context']->set($info['variable'], $value); |
||
177 | } |
||
178 | } elseif ($input->hasArgument($from)) { |
||
179 | $info['context']->set($info['variable'], $input->getArgument($from)); |
||
180 | } |
||
181 | } |
||
182 | |||
183 | return parent::run(); |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Override get the input options and arguments for the JobCommand |
||
188 | * |
||
189 | * @param \Netresearch\Kite\Task $task The task |
||
190 | * |
||
191 | * @return $this|mixed $this or the task return value when this is running |
||
192 | */ |
||
193 | public function addTask(Task $task) |
||
194 | { |
||
195 | if (!$this->started) { |
||
196 | $this->addVariablesFromTask($task); |
||
197 | } |
||
198 | |||
199 | return parent::addTask($task); |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * Add variables from the task to the job |
||
204 | * |
||
205 | * @param Task $task The task |
||
206 | * @param Variables $context Context to set the variable to, when job is run. |
||
207 | * When null, variable is set on task |
||
208 | * @param bool|null $overrideExisting Whether to override existing args (true), |
||
209 | * don't override them (false) or throw an |
||
210 | * exception (null) |
||
211 | * |
||
212 | * @return void |
||
213 | */ |
||
214 | public function addVariablesFromTask(Task $task, $context = null, $overrideExisting = null) |
||
215 | { |
||
216 | if ($task instanceof Job) { |
||
217 | foreach ($task->definitions as $from => $definition) { |
||
218 | if ($context) { |
||
219 | $definition['context'] = $context; |
||
220 | } |
||
221 | if (!array_key_exists($from, $this->definitions)) { |
||
222 | $this->definitions[$from] = $definition; |
||
223 | } |
||
224 | } |
||
225 | return; |
||
226 | } |
||
227 | |||
228 | $context = $context ?: $task; |
||
229 | foreach ($task->get('_variableConfiguration') as $variable => $config) { |
||
230 | if (!is_array($config)) { |
||
231 | continue; |
||
232 | } |
||
233 | $option = array_key_exists('option', $config) && $config['option']; |
||
234 | $argument = array_key_exists('argument', $config) && $config['argument']; |
||
235 | if ($argument && $option) { |
||
236 | throw new Exception('Variable can not be option and argument at the same time'); |
||
237 | } |
||
238 | if ($argument || $option) { |
||
239 | $setting = $argument ?: $option; |
||
240 | $from = is_string($setting) ? $setting : $this->camelCaseToLowerCaseDashed($variable); |
||
241 | if (array_key_exists($from, $this->definitions)) { |
||
242 | if ($overrideExisting === null) { |
||
243 | throw new Exception('Argument/option definitions must be unique'); |
||
244 | } elseif ($overrideExisting === false) { |
||
245 | continue; |
||
246 | } |
||
247 | } |
||
248 | $this->definitions[$from] = array( |
||
249 | 'context' => $context, |
||
250 | 'variable' => $variable, |
||
251 | 'type' => $option ? 'option' : 'argument', |
||
252 | 'config' => $config |
||
253 | ); |
||
254 | } |
||
255 | } |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * camelCase to lower-case-dashed |
||
260 | * |
||
261 | * @param string $string String |
||
262 | * |
||
263 | * @return string |
||
264 | */ |
||
265 | protected function camelCaseToLowerCaseDashed($string) |
||
266 | { |
||
267 | $string = preg_replace('/(?<=\\w)([A-Z])/', '-\\1', $string); |
||
268 | |||
269 | // Converts string to lowercase |
||
270 | // The function converts all Latin characters (A-Z, but no accents, etc) to |
||
271 | // lowercase. It is safe for all supported character sets (incl. utf-8). |
||
272 | // Unlike strtolower() it does not honour the locale. |
||
273 | return strtr($string, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * Add the retrieved options and arguments to a definition |
||
278 | * |
||
279 | * @return InputDefinition |
||
280 | */ |
||
281 | public function getDefinition() |
||
282 | { |
||
283 | if (!$this->initialized) { |
||
284 | $this->initialize(); |
||
285 | } |
||
286 | |||
287 | $definition = new InputDefinition(); |
||
288 | |||
289 | foreach ($this->definitions as $from => $info) { |
||
290 | $config = $info['config']; |
||
291 | $required = array_key_exists('required', $config) && $config['required']; |
||
292 | if ($info['type'] === 'option') { |
||
293 | $mode = array_key_exists('mode', $config) ? $config['mode'] : InputOption::VALUE_OPTIONAL; |
||
294 | if ($required) { |
||
295 | $mode |= InputOption::VALUE_REQUIRED; |
||
296 | } |
||
297 | View Code Duplication | if (in_array('array', explode('|', $config['type']), true)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
298 | $mode |= InputOption::VALUE_IS_ARRAY; |
||
299 | } |
||
300 | if (preg_match('/(^|\|)bool(ean)?($|\|)/', $config['type'])) { |
||
301 | if (strpos($config['type'], '|')) { |
||
302 | $mode |= InputOption::VALUE_NONE; |
||
303 | } else { |
||
304 | $mode = InputOption::VALUE_NONE; |
||
305 | } |
||
306 | } |
||
307 | $definition->addOption( |
||
308 | new InputOption( |
||
309 | $from, |
||
310 | array_key_exists('shortcut', $config) ? $config['shortcut'] : null, |
||
311 | $mode, |
||
312 | $config['label'], |
||
313 | array_key_exists('default', $config) ? $config['default'] : null |
||
314 | ) |
||
315 | ); |
||
316 | } else { |
||
317 | $mode = array_key_exists('mode', $config) ? $config['mode'] : InputArgument::OPTIONAL; |
||
318 | if ($required) { |
||
319 | $mode |= InputArgument::REQUIRED; |
||
320 | } |
||
321 | View Code Duplication | if (in_array('array', explode('|', $config['type']), true)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
322 | $mode |= InputArgument::IS_ARRAY; |
||
323 | } |
||
324 | $definition->addArgument( |
||
325 | new InputArgument($from, $mode, $config['label'], array_key_exists('default', $config) ? $config['default'] : null) |
||
326 | ); |
||
327 | } |
||
328 | } |
||
329 | |||
330 | return $definition; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Determine wether this job is dry run |
||
335 | * |
||
336 | * @return boolean |
||
337 | */ |
||
338 | public function isDryRun() |
||
339 | { |
||
340 | return $this->dryRun; |
||
341 | } |
||
342 | } |
||
343 | ?> |
||
344 |