netresearch /
kite
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
Loading history...
|
|||
| 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)) { |
|
| 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)) { |
|
| 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 |