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

plugins::get_plugins_list()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 25
rs 8.8571
cc 3
eloc 15
nc 3
nop 0
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\Session,
19
	cs\modules\System\Packages_manipulation;
20
21
trait plugins {
22
	/**
23
	 * @param \cs\Request $Request
24
	 *
25
	 * @throws ExitException
26
	 */
27
	static function admin_plugins_get ($Request) {
28
		if ($Request->route_path(3)) {
29
			$route_path = $Request->route_path;
30
			switch ($route_path[3]) {
31
				/**
32
				 * Get dependent packages for plugin
33
				 */
34
				case 'dependent_packages':
35
					static::get_dependent_packages_for_plugin($route_path[2]);
36
					return;
37
				/**
38
				 * Get dependencies for plugin
39
				 */
40
				case 'dependencies':
41
					static::get_dependencies_for_plugin($route_path[2]);
42
					return;
43
				/**
44
				 * Get dependencies for plugin during update
45
				 */
46
				case 'update_dependencies':
47
					static::get_update_dependencies_for_plugin($route_path[2]);
48
					return;
49
				default:
50
					throw new ExitException(400);
51
			}
52
		}
53
		/**
54
		 * Get array of plugins in extended form
55
		 */
56
		static::get_plugins_list();
57
	}
58
	/**
59
	 * @param string $plugin
60
	 *
61
	 * @throws ExitException
62
	 */
63
	protected static function get_dependent_packages_for_plugin ($plugin) {
64
		if (!in_array($plugin, Config::instance()->components['plugins'])) {
65
			throw new ExitException(404);
66
		}
67
		$meta_file = PLUGINS."/$plugin/meta.json";
68
		Page::instance()->json(
69
			file_exists($meta_file) ? Packages_manipulation::get_dependent_packages(file_get_json($meta_file)) : []
70
		);
71
	}
72
	/**
73
	 * @param string $plugin
74
	 *
75
	 * @throws ExitException
76
	 */
77
	protected static function get_dependencies_for_plugin ($plugin) {
78
		$plugins = get_files_list(PLUGINS, false, 'd');
79
		if (!in_array($plugin, $plugins, true)) {
80
			throw new ExitException(404);
81
		}
82
		$meta_file = PLUGINS."/$plugin/meta.json";
83
		Page::instance()->json(
84
			file_exists($meta_file) ? Packages_manipulation::get_dependencies(file_get_json($meta_file)) : []
85
		);
86
	}
87
	/**
88
	 * @param string $plugin
89
	 *
90
	 * @throws ExitException
91
	 */
92
	protected static function get_update_dependencies_for_plugin ($plugin) {
93
		$plugins = get_files_list(PLUGINS, false, 'd');
94
		if (!in_array($plugin, $plugins, true)) {
95
			throw new ExitException(404);
96
		}
97
		$tmp_location = TEMP.'/System/admin/'.Session::instance()->get_id().'.phar';
98
		if (!file_exists($tmp_location) || !file_exists(PLUGINS."/$plugin/meta.json")) {
99
			throw new ExitException(400);
100
		}
101
		$tmp_dir = "phar://$tmp_location";
102
		if (!file_exists("$tmp_dir/meta.json")) {
103
			throw new ExitException(400);
104
		}
105
		$existing_meta = file_get_json(PLUGINS."/$plugin/meta.json");
106
		$new_meta      = file_get_json("$tmp_dir/meta.json");
107
		if (
108
			$existing_meta['package'] !== $new_meta['package'] ||
109
			$existing_meta['category'] !== $new_meta['category']
110
		) {
111
			throw new ExitException((new Prefix('system_admin_modules_'))->this_is_not_plugin_installer_file, 400);
112
		}
113
		Page::instance()->json(
114
			Packages_manipulation::get_dependencies($new_meta)
115
		);
116
	}
117
	protected static function get_plugins_list () {
118
		$Config       = Config::instance();
119
		$plugins      = get_files_list(PLUGINS, false, 'd');
120
		$plugins_list = [];
121
		foreach ($plugins as $plugin_name) {
122
			$plugin = [
123
				'active' => (int)in_array($plugin_name, $Config->components['plugins']),
124
				'name'   => $plugin_name
125
			];
126
			/**
127
			 * Check if readme available
128
			 */
129
			static::check_plugin_feature_availability($plugin, 'readme');
130
			/**
131
			 * Check if license available
132
			 */
133
			static::check_plugin_feature_availability($plugin, 'license');
134
			if (file_exists(PLUGINS."/$plugin_name/meta.json")) {
135
				$plugin['meta'] = file_get_json(PLUGINS."/$plugin_name/meta.json");
136
			}
137
			$plugins_list[] = $plugin;
138
		}
139
		unset($plugin_name, $plugin);
140
		Page::instance()->json($plugins_list);
141
	}
142
	/**
143
	 * @param array  $plugin
144
	 * @param string $feature
145
	 */
146
	protected static function check_plugin_feature_availability (&$plugin, $feature) {
147
		/**
148
		 * Check if feature available
149
		 */
150
		$file = file_exists_with_extension(PLUGINS."/$plugin[name]/$feature", ['txt', 'html']);
151
		if ($file) {
152
			$plugin[$feature] = [
153
				'type'    => substr($file, -3) == 'txt' ? 'txt' : 'html',
154
				'content' => file_get_contents($file)
155
			];
156
		}
157
	}
158
	/**
159
	 * Disable plugin
160
	 *
161
	 * Provides next events:
162
	 *  admin/System/components/plugins/enable/before
163
	 *  ['name' => plugin_name]
164
	 *
165
	 *  admin/System/components/plugins/enable/after
166
	 *  ['name' => plugin_name]
167
	 *
168
	 * @param \cs\Request $Request
169
	 *
170
	 * @throws ExitException
171
	 */
172
	static function admin_plugins_enable ($Request) {
173
		$Config  = Config::instance();
174
		$plugin  = $Request->route_path(2);
175
		$plugins = get_files_list(PLUGINS, false, 'd');
176
		if (!in_array($plugin, $plugins, true) || in_array($plugin, $Config->components['plugins'])) {
177
			throw new ExitException(400);
178
		}
179
		if (!Event::instance()->fire(
180
			'admin/System/components/plugins/enable/before',
181
			[
182
				'name' => $plugin
183
			]
184
		)
185
		) {
186
			throw new ExitException(500);
187
		}
188
		$Config->components['plugins'][] = $plugin;
189
		if (!$Config->save()) {
190
			throw new ExitException(500);
191
		}
192
		Event::instance()->fire(
193
			'admin/System/components/plugins/enable/before',
194
			[
195
				'name' => $plugin
196
			]
197
		);
198
		static::admin_plugins_cleanup();
199
	}
200
	protected static function admin_plugins_cleanup () {
201
		clean_pcache();
202
		$Cache = System_cache::instance();
203
		unset(
204
			$Cache->functionality,
205
			$Cache->events_files_paths
206
		);
207
		clean_classes_cache();
208
	}
209
	/**
210
	 * Disable plugin
211
	 *
212
	 * Provides next events:
213
	 *  admin/System/components/plugins/disable/before
214
	 *  ['name' => plugin_name]
215
	 *
216
	 *  admin/System/components/plugins/disable/after
217
	 *  ['name' => plugin_name]
218
	 *
219
	 * @param \cs\Request $Request
220
	 *
221
	 * @throws ExitException
222
	 */
223
	static function admin_plugins_disable ($Request) {
224
		$Config       = Config::instance();
225
		$plugin       = $Request->route_path(2);
226
		$plugin_index = array_search($plugin, $Config->components['plugins'], true);
227
		if ($plugin_index === false) {
228
			throw new ExitException(400);
229
		}
230
		if (!Event::instance()->fire(
231
			'admin/System/components/plugins/disable/before',
232
			[
233
				'name' => $plugin
234
			]
235
		)
236
		) {
237
			throw new ExitException(500);
238
		}
239
		unset($Config->components['plugins'][$plugin_index]);
240
		if (!$Config->save()) {
241
			throw new ExitException(500);
242
		}
243
		Event::instance()->fire(
244
			'admin/System/components/plugins/disable/after',
245
			[
246
				'name' => $plugin
247
			]
248
		);
249
		static::admin_plugins_cleanup();
250
	}
251
	/**
252
	 * Extract uploaded plugin
253
	 *
254
	 * @throws ExitException
255
	 */
256
	static function admin_plugins_extract () {
257
		$L            = new Prefix('system_admin_modules_');
258
		$tmp_location = TEMP.'/System/admin/'.Session::instance()->get_id().'.phar';
259
		$tmp_dir      = "phar://$tmp_location";
260
		if (
261
			!file_exists($tmp_location) ||
262
			!file_exists("$tmp_dir/meta.json")
263
		) {
264
			throw new ExitException(400);
265
		}
266
		$new_meta = file_get_json("$tmp_dir/meta.json");
267
		if ($new_meta['category'] !== 'plugins') {
268
			throw new ExitException($L->this_is_not_plugin_installer_file, 400);
269
		}
270
		if (!Packages_manipulation::install_extract(PLUGINS."/$new_meta[package]", $tmp_location)) {
271
			throw new ExitException($L->plugin_files_unpacking_error, 500);
272
		}
273
		static::admin_plugins_cleanup();
274
	}
275
	/**
276
	 * Update plugin
277
	 *
278
	 * Provides next events:
279
	 *  admin/System/components/plugins/update/before
280
	 *  ['name' => plugin_name]
281
	 *
282
	 *  admin/System/components/plugins/update/after
283
	 *  ['name' => plugin_name]
284
	 *
285
	 * @param \cs\Request $Request
286
	 *
287
	 * @throws ExitException
288
	 */
289
	static function admin_plugins_update ($Request) {
290
		$Config  = Config::instance();
291
		$L       = new Prefix('system_admin_modules_');
292
		$plugin  = $Request->route_path(2);
293
		$plugins = get_files_list(PLUGINS, false, 'd');
294
		if (!in_array($plugin, $plugins, true)) {
295
			throw new ExitException(404);
296
		}
297
		$tmp_location = TEMP.'/System/admin/'.Session::instance()->get_id().'.phar';
298
		$tmp_dir      = "phar://$tmp_location";
299
		$plugin_dir   = PLUGINS."/$plugin";
300
		if (
301
			!file_exists($tmp_location) ||
302
			!file_exists("$plugin_dir/meta.json") ||
303
			!file_exists("$tmp_dir/meta.json")
304
		) {
305
			throw new ExitException(400);
306
		}
307
		$existing_meta = file_get_json("$plugin_dir/meta.json");
308
		$new_meta      = file_get_json("$tmp_dir/meta.json");
309
		$active        = in_array($plugin, $Config->components['plugins']);
310
		// If plugin is currently enabled - disable it temporary
311
		if ($active) {
312
			static::admin_plugins_disable($Request);
313
		}
314
		if (
315
			$new_meta['package'] !== $plugin ||
316
			$new_meta['category'] !== 'plugins'
317
		) {
318
			throw new ExitException($L->this_is_not_plugin_installer_file, 400);
319
		}
320
		if (!Event::instance()->fire(
321
			'admin/System/components/plugins/update/before',
322
			[
323
				'name' => $plugin
324
			]
325
		)
326
		) {
327
			throw new ExitException(500);
328
		}
329
		if (!is_writable($plugin_dir)) {
330
			throw new ExitException($L->cant_unpack_plugin_no_write_permissions, 500);
331
		}
332
		if (!Packages_manipulation::update_extract(PLUGINS."/$plugin", $tmp_location)) {
333
			throw new ExitException($L->plugin_files_unpacking_error, 500);
334
		}
335
		// Run PHP update scripts if any
336
		Packages_manipulation::update_php_sql(PLUGINS."/$plugin", $existing_meta['version']);
337
		Event::instance()->fire(
338
			'admin/System/components/plugins/update/after',
339
			[
340
				'name' => $plugin
341
			]
342
		);
343
		// If plugin was enabled before update - enable it back
344
		if ($active) {
345
			static::admin_plugins_enable($Request);
346
		}
347
	}
348
	/**
349
	 * Delete plugin completely
350
	 *
351
	 * @param \cs\Request $Request
352
	 *
353
	 * @throws ExitException
354
	 */
355
	static function admin_plugins_delete ($Request) {
356
		$Config  = Config::instance();
357
		$plugin  = $Request->route_path(2);
358
		$plugins = get_files_list(PLUGINS, false, 'd');
359
		if (
360
			!in_array($plugin, $plugins, true) ||
361
			in_array($plugin, $Config->components['plugins'])
362
		) {
363
			throw new ExitException(400);
364
		}
365
		if (!rmdir_recursive(PLUGINS."/$plugin")) {
366
			throw new ExitException(500);
367
		}
368
	}
369
}
370