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 | * For the full copyright and license information, please view the LICENSE.md |
||
4 | * file that was distributed with this source code. |
||
5 | */ |
||
6 | |||
7 | namespace Notamedia\ConsoleJedi\Environment\Command; |
||
8 | |||
9 | use Bitrix\Main\Application; |
||
10 | use Bitrix\Main\Config\Configuration; |
||
11 | use Bitrix\Main\Config\Option; |
||
12 | use Bitrix\Main\IO\File; |
||
13 | use Bitrix\Main\Loader; |
||
14 | use Notamedia\ConsoleJedi\Application\Command\Command; |
||
15 | use Notamedia\ConsoleJedi\Application\Exception\BitrixException; |
||
16 | use Notamedia\ConsoleJedi\Module\Command\ModuleCommand; |
||
17 | use Notamedia\ConsoleJedi\Module\Exception\ModuleException; |
||
18 | use Notamedia\ConsoleJedi\Module\Exception\ModuleInstallException; |
||
19 | use Notamedia\ConsoleJedi\Module\Module; |
||
20 | use Symfony\Component\Console\Input\InputArgument; |
||
21 | use Symfony\Component\Console\Input\InputInterface; |
||
22 | use Symfony\Component\Console\Output\OutputInterface; |
||
23 | use Symfony\Component\Console\Question\ChoiceQuestion; |
||
24 | use Symfony\Component\Console\Helper\ProgressBar; |
||
25 | use Symfony\Component\Filesystem\Filesystem; |
||
26 | |||
27 | /** |
||
28 | * Installation environment settings. |
||
29 | * |
||
30 | * @author Nik Samokhvalov <[email protected]> |
||
31 | */ |
||
32 | class InitCommand extends Command |
||
33 | { |
||
34 | /** |
||
35 | * @var string Path to the environment directory. |
||
36 | */ |
||
37 | protected $dir; |
||
38 | /** |
||
39 | * @var array Settings for current environment. The contents of the file `config.php`. |
||
40 | */ |
||
41 | protected $config = []; |
||
42 | /** |
||
43 | * @var array Methods which be running in the first place. |
||
44 | */ |
||
45 | protected $bootstrap = ['copyFiles', 'initializeBitrix']; |
||
46 | /** |
||
47 | * @var array Files that do not need to copy to the application when initializing the environment settings. |
||
48 | */ |
||
49 | protected $excludedFiles = ['config.php']; |
||
50 | /** |
||
51 | * @var string Type of the initialized environment. |
||
52 | */ |
||
53 | private $type; |
||
54 | |||
55 | /** |
||
56 | * {@inheritdoc} |
||
57 | */ |
||
58 | protected function configure() |
||
59 | { |
||
60 | parent::configure(); |
||
61 | |||
62 | $this->setName('env:init') |
||
63 | ->setDescription('Installation environment settings') |
||
64 | ->setHelp('Run command and select environment from the list') |
||
65 | ->addArgument('type', InputArgument::OPTIONAL, 'Type of the environments') |
||
66 | ->addOption('memcache-cold-start', null, null, 'All memcache servers adds with status "ready"'); |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * {@inheritdoc} |
||
71 | */ |
||
72 | protected function initialize(InputInterface $input, OutputInterface $output) |
||
73 | { |
||
74 | parent::initialize($input, $output); |
||
75 | |||
76 | if (!$this->getApplication()->getConfiguration()['env-dir']) { |
||
77 | throw new \Exception('Config env-dir is missing'); |
||
78 | } |
||
79 | |||
80 | $dir = $this->getApplication()->getRoot() . '/' . $this->getApplication()->getConfiguration()['env-dir']; |
||
81 | |||
82 | if (!is_dir($dir)) { |
||
83 | throw new \Exception('Directory ' . $dir . ' is missing'); |
||
84 | } |
||
85 | |||
86 | $environments = include $dir . '/index.php'; |
||
87 | |||
88 | if (!is_array($environments)) { |
||
89 | throw new \Exception('File with description of environments is missing'); |
||
90 | } elseif (count($environments) == 0) { |
||
91 | throw new \Exception('Environments not found in description file'); |
||
92 | } |
||
93 | |||
94 | if ($input->getArgument('type')) { |
||
95 | $type = $input->getArgument('type'); |
||
96 | |||
97 | if (!isset($environments[$type])) { |
||
98 | throw new \Exception('Invalid environment code!'); |
||
99 | } |
||
100 | } else { |
||
101 | foreach ($environments as $type => $environment) { |
||
102 | $choices[$type] = $environment['name']; |
||
0 ignored issues
–
show
|
|||
103 | } |
||
104 | |||
105 | $questionHelper = $this->getHelper('question'); |
||
106 | $question = new ChoiceQuestion('<info>Which environment install?</info>', $choices, false); |
||
0 ignored issues
–
show
The variable
$choices 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
![]() |
|||
107 | $type = $questionHelper->ask($input, $output, $question); |
||
108 | } |
||
109 | |||
110 | if (!isset($environments[$type]['path'])) { |
||
111 | throw new \Exception('Environment path not found!'); |
||
112 | } |
||
113 | |||
114 | $this->type = $type; |
||
115 | $this->dir = $dir . '/' . $environments[$type]['path']; |
||
116 | $this->config = include $this->dir . '/config.php'; |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * {@inheritdoc} |
||
121 | */ |
||
122 | protected function execute(InputInterface $input, OutputInterface $output) |
||
123 | { |
||
124 | foreach ($this->bootstrap as $method) { |
||
125 | $this->$method($input, $output); |
||
126 | } |
||
127 | |||
128 | foreach ($this->config as $config => $settings) { |
||
129 | $method = 'configure' . ucfirst($config); |
||
130 | |||
131 | if (!in_array($method, $this->bootstrap) && method_exists($this, $method)) { |
||
132 | $output->writeln('<comment>Setup "' . $config . '"</comment>'); |
||
133 | $this->$method($input, $output, $settings); |
||
134 | } |
||
135 | } |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Copy files and directories from the environment directory to application. |
||
140 | * |
||
141 | * @param InputInterface $input |
||
142 | * @param OutputInterface $output |
||
143 | */ |
||
144 | protected function copyFiles(InputInterface $input, OutputInterface $output) |
||
0 ignored issues
–
show
|
|||
145 | { |
||
146 | $output->writeln('<comment>Copy files from the environment directory</comment>'); |
||
147 | |||
148 | $fs = new Filesystem(); |
||
149 | |||
150 | $directoryIterator = new \RecursiveDirectoryIterator($this->dir, \RecursiveDirectoryIterator::SKIP_DOTS); |
||
151 | $iterator = new \RecursiveIteratorIterator($directoryIterator, \RecursiveIteratorIterator::SELF_FIRST); |
||
152 | |||
153 | foreach ($iterator as $item) { |
||
154 | if (in_array($iterator->getSubPathName(), $this->excludedFiles)) { |
||
155 | continue; |
||
156 | } |
||
157 | |||
158 | $itemPath = $this->getApplication()->getRoot() . '/' . $iterator->getSubPathName(); |
||
159 | |||
160 | if ($item->isDir()) { |
||
161 | $fs->mkdir($itemPath); |
||
162 | } else { |
||
163 | $fs->copy($item, $itemPath, true); |
||
164 | } |
||
165 | |||
166 | $output->writeln(' ' . $itemPath); |
||
167 | } |
||
168 | } |
||
169 | |||
170 | protected function initializeBitrix() |
||
171 | { |
||
172 | $this->getApplication()->initializeBitrix(); |
||
173 | |||
174 | $connections = Configuration::getValue('connections'); |
||
175 | |||
176 | foreach ($connections as $name => $parameters) { |
||
177 | Application::getInstance()->getConnectionPool()->cloneConnection($name, $name, $parameters); |
||
178 | } |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Sets license key Bitrix CMS. |
||
183 | * |
||
184 | * @param InputInterface $input |
||
185 | * @param OutputInterface $output |
||
186 | * @param string $licenseKey |
||
187 | */ |
||
188 | protected function configureLicenseKey(InputInterface $input, OutputInterface $output, $licenseKey) |
||
0 ignored issues
–
show
|
|||
189 | { |
||
190 | if (!is_string($licenseKey)) { |
||
191 | throw new \InvalidArgumentException('Config "licenseKey" must be string type.'); |
||
192 | } |
||
193 | |||
194 | $licenseFileContent = "<" . "? $" . "LICENSE_KEY = \"" . EscapePHPString($licenseKey) . "\"; ?" . ">"; |
||
195 | File::putFileContents(Application::getDocumentRoot() . BX_ROOT . '/license_key.php', $licenseFileContent); |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * Installation modules. |
||
200 | * |
||
201 | * @param InputInterface $input |
||
202 | * @param OutputInterface $output |
||
203 | * @param array $modules |
||
204 | * @throws BitrixException |
||
205 | * @throws \LogicException |
||
206 | * @throws ModuleException |
||
207 | */ |
||
208 | protected function configureModules(InputInterface $input, OutputInterface $output, array $modules) |
||
0 ignored issues
–
show
|
|||
209 | { |
||
210 | $app = $this->getApplication(); |
||
211 | if ($app->getConfiguration()) { |
||
212 | $app->addCommands(ModuleCommand::getCommands()); |
||
213 | if ($app->getBitrixStatus() != \Notamedia\ConsoleJedi\Application\Application::BITRIX_STATUS_COMPLETE) { |
||
214 | throw new BitrixException('Bitrix core is not available'); |
||
215 | } |
||
216 | } else { |
||
217 | throw new BitrixException('No configuration loaded'); |
||
218 | } |
||
219 | |||
220 | if (!is_array($modules)) { |
||
221 | throw new \LogicException('Incorrect modules configuration'); |
||
222 | } |
||
223 | |||
224 | if (!count($modules)) { |
||
225 | return; |
||
226 | } |
||
227 | |||
228 | $bar = new ProgressBar($output, count($modules)); |
||
229 | $bar->setRedrawFrequency(1); |
||
230 | $bar->setFormat('verbose'); |
||
231 | |||
232 | foreach ($modules as $moduleName) { |
||
233 | $message = "\r" . ' module:load ' . $moduleName . ': '; |
||
234 | |||
235 | try { |
||
236 | if (isset($bar)) { |
||
237 | $bar->setMessage($message); |
||
238 | $bar->display(); |
||
239 | } |
||
240 | |||
241 | (new Module($moduleName))->load()->register(); |
||
242 | |||
243 | $bar->clear(); |
||
244 | $output->writeln($message . '<info>ok</info>'); |
||
245 | } catch (ModuleInstallException $e) { |
||
246 | $bar->clear(); |
||
247 | $output->writeln($e->getMessage(), OutputInterface::VERBOSITY_VERBOSE); |
||
248 | $output->writeln($message . '<comment>not registered</comment> (install it in admin panel)'); |
||
249 | } catch (ModuleException $e) { |
||
250 | $bar->clear(); |
||
251 | $output->writeln($e->getMessage(), OutputInterface::VERBOSITY_VERBOSE); |
||
252 | $output->writeln($message . '<error>FAILED</error>'); |
||
253 | } |
||
254 | $bar->advance(); |
||
255 | } |
||
256 | $bar->finish(); |
||
257 | $bar->clear(); |
||
258 | $output->write("\r"); |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * Sets configs to .settings.php. |
||
263 | * |
||
264 | * @param InputInterface $input |
||
265 | * @param OutputInterface $output |
||
266 | * @param array $settings |
||
267 | */ |
||
268 | protected function configureSettings(InputInterface $input, OutputInterface $output, array $settings) |
||
0 ignored issues
–
show
|
|||
269 | { |
||
270 | $configuration = Configuration::getInstance(); |
||
271 | |||
272 | foreach ($settings as $name => $value) { |
||
273 | $configuration->setValue($name, $value); |
||
274 | } |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Installation config to module "cluster". |
||
279 | * |
||
280 | * @param InputInterface $input |
||
281 | * @param OutputInterface $output |
||
282 | * @param array $cluster |
||
283 | * |
||
284 | * @throws \Bitrix\Main\LoaderException |
||
285 | * @throws \Exception |
||
286 | */ |
||
287 | protected function configureCluster(InputInterface $input, OutputInterface $output, array $cluster) |
||
288 | { |
||
289 | global $APPLICATION; |
||
0 ignored issues
–
show
Compatibility
Best Practice
introduced
by
Use of
global functionality is not recommended; it makes your code harder to test, and less reusable.
Instead of relying on 1. Pass all data via parametersfunction myFunction($a, $b) {
// Do something
}
2. Create a class that maintains your stateclass MyClass {
private $a;
private $b;
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
public function myFunction() {
// Do something
}
}
![]() |
|||
290 | |||
291 | if (!Loader::includeModule('cluster')) { |
||
292 | throw new \Exception('Failed to load module "cluster"'); |
||
293 | } |
||
294 | |||
295 | $memcache = new \CClusterMemcache; |
||
296 | |||
297 | if (isset($cluster['memcache'])) { |
||
298 | $output->writeln(' <comment>memcache</comment>'); |
||
299 | |||
300 | if (!is_array($cluster['memcache'])) { |
||
301 | throw new \Exception('Server info must be an array'); |
||
302 | } |
||
303 | |||
304 | $rsServers = $memcache->GetList(); |
||
305 | |||
306 | while ($server = $rsServers->Fetch()) { |
||
307 | $memcache->Delete($server['ID']); |
||
308 | } |
||
309 | |||
310 | foreach ($cluster['memcache'] as $index => $server) { |
||
311 | $serverId = $memcache->Add($server); |
||
312 | |||
313 | if ($serverId && !$input->getOption('memcache-cold-start')) { |
||
314 | $memcache->Resume($serverId); |
||
315 | } else { |
||
316 | $exception = $APPLICATION->GetException(); |
||
317 | $message = 'Invalid memcache config with index ' . $index; |
||
318 | |||
319 | if ($exception->GetString()) { |
||
320 | $message = str_replace('<br>', "\n", $exception->GetString()); |
||
321 | } |
||
322 | |||
323 | $output->writeln('<error>' . $message . '</error>'); |
||
324 | } |
||
325 | } |
||
326 | } |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * Installation of option modules. |
||
331 | * |
||
332 | * @param InputInterface $input |
||
333 | * @param OutputInterface $output |
||
334 | * @param array $options |
||
335 | */ |
||
336 | protected function configureOptions(InputInterface $input, OutputInterface $output, array $options) |
||
0 ignored issues
–
show
|
|||
337 | { |
||
338 | if (empty($options)) { |
||
339 | return; |
||
340 | } |
||
341 | |||
342 | foreach ($options as $module => $moduleOptions) { |
||
343 | if (!is_array($moduleOptions) || empty($moduleOptions)) { |
||
344 | continue; |
||
345 | } |
||
346 | |||
347 | foreach ($moduleOptions as $code => $value) { |
||
348 | if (is_array($value)) { |
||
349 | if (isset($value['value']) && isset($value['siteId'])) { |
||
350 | Option::set($module, $code, $value['value'], $value['siteId']); |
||
351 | } else { |
||
352 | $output->writeln('<error>Invalid option for module "' . $module . '" with code "' . $code . '"</error>'); |
||
353 | } |
||
354 | } else { |
||
355 | Option::set($module, $code, $value); |
||
356 | |||
357 | $output->writeln(' option: "' . $code . '", module: "' . $module . '"'); |
||
358 | } |
||
359 | } |
||
360 | } |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * Gets type of initialized environment. |
||
365 | * |
||
366 | * @return string |
||
367 | */ |
||
368 | public function getType() |
||
369 | { |
||
370 | return $this->type; |
||
371 | } |
||
372 | } |
||
373 |
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:
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 thebar
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.