Completed
Push — master ( c78c55...a2ae2e )
by Nazar
04:43
created

modules::get_module_storages()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 9
rs 9.6666
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
/**
3
 * @package    CleverStyle CMS
4
 * @subpackage System module
5
 * @category   modules
6
 * @author     Nazar Mokrynskyi <[email protected]>
7
 * @copyright  Copyright (c) 2015-2016, Nazar Mokrynskyi
8
 * @license    MIT License, see license.txt
9
 */
10
namespace cs\modules\System\api\Controller\admin;
11
use
12
	cs\Cache as System_cache,
13
	cs\Config,
14
	cs\Event,
15
	cs\ExitException,
16
	cs\Language\Prefix,
17
	cs\Page,
18
	cs\Permission,
19
	cs\Session,
20
	cs\modules\System\Packages_manipulation;
21
22
trait modules {
23
	/**
24
	 * @param \cs\Request $Request
25
	 *
26
	 * @throws ExitException
27
	 */
28
	static function admin_modules_get ($Request) {
29
		if ($Request->route_path(3)) {
30
			$route_path = $Request->route_path;
31
			switch ($route_path[3]) {
32
				/**
33
				 * Get dependent packages for module
34
				 */
35
				case 'dependent_packages':
36
					static::get_dependent_packages_for_module($route_path[2]);
37
					break;
38
				/**
39
				 * Get dependencies for module (packages, databases, storages)
40
				 */
41
				case 'dependencies':
42
					static::get_dependencies_for_module($route_path[2]);
43
					break;
44
				/**
45
				 * Get dependencies for module during update
46
				 */
47
				case 'update_dependencies':
48
					static::get_update_dependencies_for_module($route_path[2]);
49
					break;
50
				/**
51
				 * Get mapping of named module's databases to indexes of system databases
52
				 */
53
				case 'db':
54
					static::get_module_databases($route_path[2]);
55
					break;
56
				/**
57
				 * Get mapping of named module's storages to indexes of system storages
58
				 */
59
				case 'storage':
60
					static::get_module_storages($route_path[2]);
61
					break;
62
				default:
63
					throw new ExitException(400);
64
			}
65
		} elseif ($Request->route_path(2) == 'default') {
66
			/**
67
			 * Get current default module
68
			 */
69
			static::get_default_module();
70
		} else {
71
			/**
72
			 * Get array of modules in extended form
73
			 */
74
			static::get_modules_list();
75
		}
76
	}
77
	/**
78
	 * @param string $module
79
	 *
80
	 * @throws ExitException
81
	 */
82
	protected static function get_dependent_packages_for_module ($module) {
83
		if (!Config::instance()->module($module)) {
84
			throw new ExitException(404);
85
		}
86
		$meta_file = MODULES."/$module/meta.json";
87
		Page::instance()->json(
88
			file_exists($meta_file) ? Packages_manipulation::get_dependent_packages(file_get_json($meta_file)) : []
89
		);
90
	}
91
	/**
92
	 * @param string $module
93
	 *
94
	 * @throws ExitException
95
	 */
96
	protected static function get_dependencies_for_module ($module) {
97
		if (!Config::instance()->module($module)) {
98
			throw new ExitException(404);
99
		}
100
		$meta_file = MODULES."/$module/meta.json";
101
		Page::instance()->json(
102
			file_exists($meta_file) ? Packages_manipulation::get_dependencies(file_get_json($meta_file)) : []
103
		);
104
	}
105
	/**
106
	 * @param string $module
107
	 *
108
	 * @throws ExitException
109
	 */
110
	protected static function get_update_dependencies_for_module ($module) {
111
		if (!Config::instance()->module($module)) {
112
			throw new ExitException(404);
113
		}
114
		$tmp_location = TEMP.'/System/admin/'.Session::instance()->get_id().'.phar';
115
		$tmp_dir      = "phar://$tmp_location";
116
		if (
117
			!file_exists(MODULES."/$module/meta.json") ||
118
			!file_exists("$tmp_dir/meta.json")
119
		) {
120
			throw new ExitException(400);
121
		}
122
		$new_meta = file_get_json("$tmp_dir/meta.json");
123
		if (!static::is_same_module($new_meta, $module)) {
124
			throw new ExitException((new Prefix('system_admin_modules_'))->this_is_not_module_installer_file, 400);
125
		}
126
		Page::instance()->json(
127
			Packages_manipulation::get_dependencies($new_meta)
128
		);
129
	}
130
	/**
131
	 * @param array  $meta
132
	 * @param string $module
133
	 *
134
	 * @return bool
135
	 */
136
	protected static function is_same_module ($meta, $module) {
137
		return $meta['category'] == 'modules' && $meta['package'] == $module;
138
	}
139
	/**
140
	 * @param string $module
141
	 *
142
	 * @throws ExitException
143
	 */
144
	protected static function get_module_databases ($module) {
145
		$Config = Config::instance();
146
		if (!isset($Config->components['modules'][$module]['db'])) {
147
			throw new ExitException(404);
148
		}
149
		Page::instance()->json(
150
			$Config->components['modules'][$module]['db']
151
		);
152
	}
153
	/**
154
	 * @param string $module
155
	 *
156
	 * @throws ExitException
157
	 */
158
	protected static function get_module_storages ($module) {
159
		$Config = Config::instance();
160
		if (!isset($Config->components['modules'][$module]['storage'])) {
161
			throw new ExitException(404);
162
		}
163
		Page::instance()->json(
164
			$Config->components['modules'][$module]['storage']
165
		);
166
	}
167
	protected static function get_modules_list () {
168
		$Config       = Config::instance();
169
		$modules_list = [];
170
		foreach ($Config->components['modules'] as $module_name => &$module_data) {
171
			$module = [
172
				'active'            => $module_data['active'],
173
				'name'              => $module_name,
174
				'has_user_section'  => file_exists_with_extension(MODULES."/$module_name/index", ['php', 'html', 'json']),
175
				'has_admin_section' => file_exists_with_extension(MODULES."/$module_name/admin/index", ['php', 'json'])
176
			];
177
			/**
178
			 * Check if API available
179
			 */
180
			static::check_module_feature_availability($module, 'readme', 'api');
181
			/**
182
			 * Check if readme available
183
			 */
184
			static::check_module_feature_availability($module, 'readme');
185
			/**
186
			 * Check if license available
187
			 */
188
			static::check_module_feature_availability($module, 'license');
189
			if (file_exists(MODULES."/$module_name/meta.json")) {
190
				$module['meta'] = file_get_json(MODULES."/$module_name/meta.json");
191
			}
192
			$modules_list[] = $module;
193
		}
194
		unset($module_name, $module_data, $module);
195
		Page::instance()->json($modules_list);
196
	}
197
	/**
198
	 * @param array  $module
199
	 * @param string $feature
200
	 * @param string $dir
201
	 */
202
	protected static function check_module_feature_availability (&$module, $feature, $dir = '') {
203
		/**
204
		 * Check if feature available
205
		 */
206
		$file = file_exists_with_extension(MODULES."/$module[name]/$dir/$feature", ['txt', 'html']);
207
		if ($file) {
208
			$module[$dir ?: $feature] = [
209
				'type'    => substr($file, -3) == 'txt' ? 'txt' : 'html',
210
				'content' => file_get_contents($file)
211
			];
212
		} elseif ($dir && is_dir(MODULES."/$module[name]/$dir")) {
213
			$module[$dir ?: $feature] = [];
214
		}
215
	}
216
	protected static function get_default_module () {
217
		Page::instance()->json(
218
			Config::instance()->core['default_module']
219
		);
220
	}
221
	/**
222
	 * @param \cs\Request $Request
223
	 *
224
	 * @throws ExitException
225
	 */
226
	static function admin_modules_put ($Request) {
227
		if ($Request->route_path(3)) {
228
			$route_path = $Request->route_path;
229
			switch ($route_path[3]) {
230
				/**
231
				 * Set mapping of named module's databases to indexes of system databases
232
				 */
233
				case 'db':
234
					static::set_module_databases($route_path[2]);
235
					break;
236
				/**
237
				 * Set mapping of named module's storages to indexes of system storages
238
				 */
239
				case 'storage':
240
					static::set_module_storages($route_path[2]);
241
					break;
242
				default:
243
					throw new ExitException(400);
244
			}
245
		} elseif ($Request->route_path(2) == 'default') {
246
			/**
247
			 * Set current default module
248
			 */
249
			static::set_default_module($Request->data('module'));
250
		} else {
251
			throw new ExitException(400);
252
		}
253
	}
254
	/**
255
	 * @param string $module
256
	 *
257
	 * @throws ExitException
258
	 */
259
	protected static function set_module_databases ($module) {
260
		$Config = Config::instance();
261
		if (!isset($Config->components['modules'][$module]['db'], $_POST['db'])) {
262
			throw new ExitException(404);
263
		}
264
		$Config->components['modules'][$module]['db'] = _int($_POST['db']);
265
		static::admin_modules_save();
266
	}
267
	/**
268
	 * @param string $module
269
	 *
270
	 * @throws ExitException
271
	 */
272
	protected static function set_module_storages ($module) {
273
		$Config = Config::instance();
274
		if (!isset($Config->components['modules'][$module]['storage'], $_POST['storage'])) {
275
			throw new ExitException(404);
276
		}
277
		$Config->components['modules'][$module]['storage'] = _int($_POST['storage']);
278
		static::admin_modules_save();
279
	}
280
	/**
281
	 * @param string $module
282
	 *
283
	 * @throws ExitException
284
	 */
285
	protected static function set_default_module ($module) {
286
		$Config      = Config::instance();
287
		$module_data = $Config->module($module);
288
		if (!$module_data) {
289
			throw new ExitException(404);
290
		}
291
		if (
292
			$module == $Config->core['default_module'] ||
293
			!$module_data->enabled() ||
294
			!file_exists_with_extension(MODULES."/$module/index", ['php', 'html', 'json'])
295
		) {
296
			throw new ExitException(400);
297
		}
298
		if (!Event::instance()->fire('admin/System/components/modules/default', ['name' => $module])) {
299
			throw new ExitException(500);
300
		}
301
		$Config->core['default_module'] = $module;
302
		static::admin_modules_save();
303
	}
304
	/**
305
	 * Enable module
306
	 *
307
	 * Provides next events:
308
	 *  admin/System/components/modules/enable/before
309
	 *  ['name' => module_name]
310
	 *
311
	 *  admin/System/components/modules/enable/after
312
	 *  ['name' => module_name]
313
	 *
314
	 * @param \cs\Request $Request
315
	 *
316
	 * @throws ExitException
317
	 */
318
	static function admin_modules_enable ($Request) {
319
		$Config = Config::instance();
320
		$module = $Request->route_path(2);
321
		if (!$Config->module($module)->disabled()) {
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 320 can also be of type false; however, cs\Config::module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
322
			throw new ExitException(400);
323
		}
324
		if (!Event::instance()->fire('admin/System/components/modules/enable/before', ['name' => $module])) {
325
			throw new ExitException(500);
326
		}
327
		$Config->components['modules'][$module]['active'] = Config\Module_Properties::ENABLED;
328
		static::admin_modules_save();
329
		Event::instance()->fire('admin/System/components/modules/enable/after', ['name' => $module]);
330
		static::admin_modules_cleanup();
331
	}
332
	protected static function admin_modules_cleanup () {
333
		clean_pcache();
334
		$Cache = System_cache::instance();
335
		unset(
336
			$Cache->functionality,
337
			$Cache->languages,
338
			$Cache->events_files_paths
339
		);
340
		clean_classes_cache();
341
	}
342
	/**
343
	 * Disable module
344
	 *
345
	 * Provides next events:
346
	 *  admin/System/components/modules/disable/before
347
	 *  ['name' => module_name]
348
	 *
349
	 *  admin/System/components/modules/disable/after
350
	 *  ['name' => module_name]
351
	 *
352
	 * @param \cs\Request $Request
353
	 *
354
	 * @throws ExitException
355
	 */
356
	static function admin_modules_disable ($Request) {
357
		$Config = Config::instance();
358
		$module = $Request->route_path(2);
359
		if (
360
			$module == Config::SYSTEM_MODULE ||
361
			$Config->core['default_module'] == $module ||
362
			!$Config->module($module)->enabled()
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 358 can also be of type false; however, cs\Config::module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
363
		) {
364
			throw new ExitException(400);
365
		}
366
		if (!Event::instance()->fire('admin/System/components/modules/disable/before', ['name' => $module])) {
367
			throw new ExitException(500);
368
		}
369
		$Config->components['modules'][$module]['active'] = Config\Module_Properties::DISABLED;
370
		static::admin_modules_save();
371
		Event::instance()->fire('admin/System/components/modules/disable/after', ['name' => $module]);
372
		static::admin_modules_cleanup();
373
	}
374
	/**
375
	 * Install module
376
	 *
377
	 * Provides next events:
378
	 *  admin/System/components/modules/install/before
379
	 *  ['name' => module_name]
380
	 *
381
	 *  admin/System/components/modules/install/after
382
	 *  ['name' => module_name]
383
	 *
384
	 * @param \cs\Request $Request
385
	 *
386
	 * @throws ExitException
387
	 */
388
	static function admin_modules_install ($Request) {
389
		$Config = Config::instance();
390
		$module = $Request->route_path(2);
391
		if (!$Config->module($module)->uninstalled()) {
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 390 can also be of type false; however, cs\Config::module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
392
			throw new ExitException(400);
393
		}
394
		if (!Event::instance()->fire('admin/System/components/modules/install/before', ['name' => $module])) {
395
			throw new ExitException(500);
396
		}
397
		$module_data = &$Config->components['modules'][$module];
398
		if (isset($_POST['db'])) {
399
			$module_data['db'] = $_POST['db'];
400
			Packages_manipulation::execute_sql_from_directory(MODULES."/$module/meta/install_db", $module_data['db']);
401
		}
402
		if (isset($_POST['storage'])) {
403
			$module_data['storage'] = $_POST['storage'];
404
		}
405
		$module_data['active'] = Config\Module_Properties::DISABLED;
406
		static::admin_modules_save();
407
		Event::instance()->fire('admin/System/components/modules/install/after', ['name' => $module]);
408
		static::admin_modules_cleanup();
409
	}
410
	/**
411
	 * Uninstall module
412
	 *
413
	 * Provides next events:
414
	 *  admin/System/components/modules/uninstall/before
415
	 *  ['name' => module_name]
416
	 *
417
	 *  admin/System/components/modules/uninstall/after
418
	 *  ['name' => module_name]
419
	 *
420
	 * @param \cs\Request $Request
421
	 *
422
	 * @throws ExitException
423
	 */
424
	static function admin_modules_uninstall ($Request) {
425
		$Config  = Config::instance();
426
		$module  = $Request->route_path(2);
427
		$modules = &$Config->components['modules'];
428
		/**
429
		 * Do not allow to uninstall enabled module, it should be explicitly disabled first
430
		 */
431
		if (!$Config->module($module)->disabled()) {
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 426 can also be of type false; however, cs\Config::module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
432
			throw new ExitException(400);
433
		}
434
		if (!Event::instance()->fire('admin/System/components/modules/uninstall/before', ['name' => $module])) {
435
			throw new ExitException(500);
436
		}
437
		$module_data = &$modules[$module];
438
		if (isset($module_data['db'])) {
439
			Packages_manipulation::execute_sql_from_directory(MODULES."/$module/meta/uninstall_db", $module_data['db']);
440
		}
441
		static::delete_permissions_for_module($module);
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 426 can also be of type false; however, cs\modules\System\api\Co...ermissions_for_module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
442
		$modules[$module] = ['active' => Config\Module_Properties::UNINSTALLED];
443
		static::admin_modules_save();
444
		Event::instance()->fire('admin/System/components/modules/uninstall/after', ['name' => $module]);
445
		static::admin_modules_cleanup();
446
	}
447
	/**
448
	 * @param string $module
449
	 */
450
	protected static function delete_permissions_for_module ($module) {
451
		$Permission      = Permission::instance();
452
		$permissions_ids = array_merge(
453
			$Permission->get(null, $module),
454
			$Permission->get(null, "admin/$module"),
455
			$Permission->get(null, "api/$module")
456
		);
457
		if (!empty($permissions_ids)) {
458
			$Permission->del(
459
				array_column($permissions_ids, 'id')
460
			);
461
		}
462
	}
463
	/**
464
	 * Extract uploaded module
465
	 *
466
	 * @throws ExitException
467
	 */
468
	static function admin_modules_extract () {
469
		$Config       = Config::instance();
470
		$L            = new Prefix('system_admin_modules_');
471
		$tmp_location = TEMP.'/System/admin/'.Session::instance()->get_id().'.phar';
472
		$tmp_dir      = "phar://$tmp_location";
473
		if (
474
			!file_exists($tmp_location) ||
475
			!file_exists("$tmp_dir/meta.json")
476
		) {
477
			throw new ExitException(400);
478
		}
479
		$new_meta = file_get_json("$tmp_dir/meta.json");
480
		if ($new_meta['category'] !== 'modules') {
481
			throw new ExitException($L->this_is_not_module_installer_file, 400);
482
		}
483
		if (!Packages_manipulation::install_extract(MODULES."/$new_meta[package]", $tmp_location)) {
484
			throw new ExitException($L->module_files_unpacking_error, 500);
485
		}
486
		$Config->components['modules'][$new_meta['package']] = ['active' => Config\Module_Properties::UNINSTALLED];
487
		ksort($Config->components['modules'], SORT_STRING | SORT_FLAG_CASE);
488
		static::admin_modules_save();
489
		static::admin_modules_cleanup();
490
	}
491
	/**
492
	 * Update module (or system if module name is System)
493
	 *
494
	 * @param \cs\Request $Request
495
	 *
496
	 * @throws ExitException
497
	 */
498
	static function admin_modules_update ($Request) {
499
		$module = $Request->route_path(2);
500
		if (!Config::instance()->module($module)) {
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 499 can also be of type false; however, cs\Config::module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
501
			throw new ExitException(404);
502
		}
503
		$tmp_location = TEMP.'/System/admin/'.Session::instance()->get_id().'.phar';
504
		$tmp_dir      = "phar://$tmp_location";
505
		$module_dir   = MODULES."/$module";
506
		if (
507
			!file_exists($tmp_location) ||
508
			!file_exists("$module_dir/meta.json") ||
509
			!file_exists("$tmp_dir/meta.json")
510
		) {
511
			throw new ExitException(400);
512
		}
513
		$existing_meta = file_get_json("$module_dir/meta.json");
514
		$new_meta      = file_get_json("$tmp_dir/meta.json");
515
		if ($module == Config::SYSTEM_MODULE) {
516
			static::update_system($module, $existing_meta, $new_meta, $tmp_location);
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 499 can also be of type false; however, cs\modules\System\api\Co...odules::update_system() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
517
		} else {
518
			static::update_module($module, $existing_meta, $new_meta, $tmp_location, $Request);
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 499 can also be of type false; however, cs\modules\System\api\Co...odules::update_module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
519
		}
520
		static::admin_modules_cleanup();
521
	}
522
	/**
523
	 * Provides next events:
524
	 *  admin/System/components/modules/update/before
525
	 *  ['name' => module_name]
526
	 *
527
	 *  admin/System/components/modules/update/after
528
	 *  ['name' => module_name]
529
	 *
530
	 * @param string      $module
531
	 * @param array       $existing_meta
532
	 * @param array       $new_meta
533
	 * @param string      $tmp_location
534
	 * @param \cs\Request $Request
535
	 *
536
	 * @throws ExitException
537
	 */
538
	protected static function update_module ($module, $existing_meta, $new_meta, $tmp_location, $Request) {
539
		$Config     = Config::instance();
540
		$L          = new Prefix('system_admin_modules_');
541
		$module_dir = MODULES."/$module";
542
		$enabled    = $Config->module($module)->enabled();
543
		// If module is currently enabled - disable it temporary
544
		if ($enabled) {
545
			static::admin_modules_disable($Request);
546
		}
547
		if (!static::is_same_module($new_meta, $module)) {
548
			throw new ExitException($L->this_is_not_module_installer_file, 400);
549
		}
550
		if (!Event::instance()->fire('admin/System/components/modules/update/before', ['name' => $module])) {
551
			throw new ExitException(500);
552
		}
553
		if (!is_writable($module_dir)) {
554
			throw new ExitException($L->cant_unpack_module_no_write_permissions, 500);
555
		}
556
		if (!Packages_manipulation::update_extract($module_dir, $tmp_location)) {
557
			throw new ExitException($L->module_files_unpacking_error, 500);
558
		}
559
		$module_data = $Config->components['modules'][$module];
560
		// Run PHP update scripts and SQL queries if any
561
		Packages_manipulation::update_php_sql($module_dir, $existing_meta['version'], isset($module_data['db']) ? $module_data['db'] : null);
562
		Event::instance()->fire('admin/System/components/modules/update/after', ['name' => $module]);
563
		// If module was enabled before update - enable it back
564
		if ($enabled) {
565
			static::admin_modules_enable($Request);
566
		}
567
	}
568
	/**
569
	 * Provides next events:
570
	 *  admin/System/components/modules/update_system/before
571
	 *
572
	 *  admin/System/components/modules/update_system/after
573
	 *
574
	 * @param string $module
575
	 * @param array  $existing_meta
576
	 * @param array  $new_meta
577
	 * @param string $tmp_location
578
	 *
579
	 * @throws ExitException
580
	 */
581
	protected static function update_system ($module, $existing_meta, $new_meta, $tmp_location) {
582
		$Config     = Config::instance();
583
		$L          = new Prefix('system_admin_modules_');
584
		$module_dir = MODULES."/$module";
585
		/**
586
		 * Temporary close site
587
		 */
588
		$site_mode = $Config->core['site_mode'];
589
		if ($site_mode) {
590
			$Config->core['site_mode'] = 0;
591
			static::admin_modules_save();
592
		}
593
		if (!static::is_same_module($new_meta, Config::SYSTEM_MODULE)) {
594
			throw new ExitException($L->this_is_not_system_installer_file, 400);
595
		}
596
		if (!Event::instance()->fire('admin/System/components/modules/update_system/before')) {
597
			throw new ExitException(500);
598
		}
599
		if (!Packages_manipulation::update_extract(DIR, $tmp_location, DIR.'/core', $module_dir)) {
600
			throw new ExitException($L->system_files_unpacking_error, 500);
601
		}
602
		$module_data = $Config->components['modules'][$module];
603
		// Run PHP update scripts and SQL queries if any
604
		Packages_manipulation::update_php_sql($module_dir, $existing_meta['version'], isset($module_data['db']) ? $module_data['db'] : null);
605
		Event::instance()->fire('admin/System/components/modules/update_system/after');
606
		/**
607
		 * Restore previous site mode
608
		 */
609
		if ($site_mode) {
610
			$Config->core['site_mode'] = 1;
611
			static::admin_modules_save();
612
		}
613
		static::admin_modules_cleanup();
614
	}
615
	/**
616
	 * Delete module completely
617
	 *
618
	 * @param \cs\Request $Request
619
	 *
620
	 * @throws ExitException
621
	 */
622
	static function admin_modules_delete ($Request) {
623
		$Config = Config::instance();
624
		$module = $Request->route_path(2);
625
		if (
626
			$module == Config::SYSTEM_MODULE ||
627
			!$Config->module($module)->uninstalled()
0 ignored issues
show
Security Bug introduced by
It seems like $module defined by $Request->route_path(2) on line 624 can also be of type false; however, cs\Config::module() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
628
		) {
629
			throw new ExitException(400);
630
		}
631
		if (!rmdir_recursive(MODULES."/$module")) {
632
			throw new ExitException(500);
633
		}
634
		unset($Config->components['modules'][$module]);
635
		static::admin_modules_save();
636
	}
637
	/**
638
	 * Update information about present modules
639
	 *
640
	 * @throws ExitException
641
	 */
642
	static function admin_modules_update_list () {
643
		$Config = Config::instance();
644
		/**
645
		 * List of currently presented modules in file system
646
		 */
647
		$modules_in_fs = get_files_list(MODULES, false, 'd');
648
		$modules_list  = array_fill_keys(
649
			$modules_in_fs,
650
			[
651
				'active'  => -1,
652
				'db'      => [],
653
				'storage' => []
654
			]
655
		);
656
		/**
657
		 * Already known modules
658
		 */
659
		$modules       = &$Config->components['modules'];
660
		$known_modules = array_keys($modules);
661
		if ($modules_in_fs != $known_modules) {
662
			/**
663
			 * Delete permissions of modules that are mot present anymore
664
			 */
665
			foreach ($known_modules as $module) {
666
				if (!isset($modules_list[$module])) {
667
					static::delete_permissions_for_module($module);
668
				}
669
			}
670
			unset($module);
671
		}
672
		unset($modules_in_fs, $known_modules);
673
		$modules = array_merge($modules_list, array_intersect_key($modules, $modules_list));
674
		ksort($modules, SORT_STRING | SORT_FLAG_CASE);
675
		static::admin_modules_save();
676
		static::admin_modules_cleanup();
677
	}
678
	/**
679
	 * Save changes
680
	 *
681
	 * @throws ExitException
682
	 */
683
	protected static function admin_modules_save () {
684
		if (!Config::instance()->save()) {
685
			throw new ExitException(500);
686
		}
687
	}
688
}
689