Completed
Push — master ( a2c8d4...3a88fc )
by Nazar
07:08
created

Builder   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 352
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 55.77%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 352
rs 9.6
c 3
b 0
f 0
ccs 87
cts 156
cp 0.5577
wmc 32
lcom 1
cbo 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B get_htaccess() 0 26 1
C core() 0 124 7
B get_core_files() 0 31 4
A filter_and_add_components() 0 10 1
B get_component_files() 0 28 3
A module() 0 6 2
A theme() 0 6 2
C generic_package_creation() 0 62 11
1
<?php
2
/**
3
 * @package    CleverStyle Framework
4
 * @subpackage Builder
5
 * @author     Nazar Mokrynskyi <[email protected]>
6
 * @copyright  Copyright (c) 2011-2016, Nazar Mokrynskyi
7
 * @license    MIT License, see license.txt
8
 */
9
namespace cs;
10
use
11
	Phar;
12
13
class Builder {
14
	/**
15
	 * @var string
16
	 */
17
	protected $root;
18
	/**
19
	 * @var string
20
	 */
21
	protected $target;
22
	/**
23
	 * @param string $root
24
	 * @param string $target
25
	 */
26 11
	function __construct ($root, $target) {
27 11
		$this->root   = $root;
28 11
		$this->target = $target;
29 11
		@mkdir($target);
30 11
	}
31
	/**
32
	 * @param string[]    $modules
33
	 * @param string[]    $themes
34
	 * @param null|string $suffix
35
	 *
36
	 * @return string
37
	 */
38 4
	function core ($modules = [], $themes = [], $suffix = null) {
39 4
		$suffix      = $suffix ? "_$suffix" : '';
40 4
		$version     = file_get_json("$this->root/modules/System/meta.json")['version'];
41 4
		$target_file = "$this->target/CleverStyle_Framework_$version$suffix.phar.php";
42 4
		if (file_exists($target_file)) {
43
			unlink($target_file);
44
		}
45 4
		$phar = new Phar($target_file);
46 4
		unset($target_file);
47 4
		$phar->startBuffering();
48 4
		$length = strlen("$this->root/");
49 4
		foreach (get_files_list("$this->root/install", false, 'f', '', true) as $file) {
50 4
			$phar->addFile("$this->root/install/$file", $file);
51
		}
52 4
		unset($file);
53 4
		$phar->addFile("$this->root/includes/img/logo.svg", 'logo.svg');
54
		/**
55
		 * Core files to be included into installation package
56
		 */
57 4
		$core_files = $this->get_core_files();
58
		/**
59
		 * Add modules that should be built-in into package
60
		 */
61 4
		$components_files = [];
62 4
		$modules          = $this->filter_and_add_components("$this->root/modules", $modules, $components_files);
63 4
		$phar->addFromString('modules.json', _json_encode($modules));
64
		/**
65
		 * Add themes that should be built-in into package
66
		 */
67 4
		$themes = $this->filter_and_add_components("$this->root/themes", $themes, $components_files);
68 4
		$phar->addFromString('themes.json', _json_encode($themes));
69
		/**
70
		 * Joining system and components files
71
		 */
72 4
		$core_files = array_merge($core_files, $components_files);
73
		/**
74
		 * Addition of files into package
75
		 */
76 4
		foreach ($core_files as $index => &$file) {
77 4
			$phar->addFile($file, "fs/$index");
78 4
			$file = substr($file, $length);
79
		}
80 4
		unset($index, $file);
81
		/**
82
		 * Addition of separate files into package
83
		 */
84 4
		$phar->addFromString(
85 4
			'languages.json',
86
			_json_encode(
87
				array_merge(
88 4
					_substr(get_files_list("$this->root/core/languages", '/^.*?\.php$/i', 'f'), 0, -4) ?: [],
89 4
					_substr(get_files_list("$this->root/core/languages", '/^.*?\.json$/i', 'f'), 0, -5) ?: []
90
				)
91
			)
92
		);
93 4
		$phar->addFromString(
94 4
			'db_engines.json',
95
			_json_encode(
96 4
				_substr(get_files_list("$this->root/core/engines/DB", '/^[^_].*?\.php$/i', 'f'), 0, -4)
97
			)
98
		);
99
		/**
100
		 * Fixation of system files list (without components files), it is needed for future system updating
101
		 */
102 4
		$phar->addFromString(
103 4
			'fs.json',
104
			_json_encode(
105
				array_flip(
106
					array_diff(
107
						$core_files,
108
						_substr($components_files, $length)
109
					)
110
				)
111
			)
112
		);
113 4
		unset($components_files, $length);
114
		/**
115
		 * Addition of files, that are needed only for installation
116
		 */
117 4
		$phar->addFromString('fs/'.count($core_files), $this->get_htaccess());
118 4
		$core_files[] = '.htaccess';
119 4
		$phar->addFile("$this->root/config/main.php", 'fs/'.count($core_files));
120 4
		$core_files[] = 'config/main.php';
121 4
		$phar->addFile("$this->root/favicon.ico", 'fs/'.count($core_files));
122 4
		$core_files[] = 'favicon.ico';
123 4
		$phar->addFile("$this->root/.gitignore", 'fs/'.count($core_files));
124 4
		$core_files[] = '.gitignore';
125
		/**
126
		 * Flip array to have direct access to files by name during extracting and installation, and fixing of files list for installation
127
		 */
128 4
		$phar->addFromString(
129 4
			'fs_installer.json',
130
			_json_encode(
131
				array_flip($core_files)
132
			)
133
		);
134 4
		unset($core_files);
135
		/**
136
		 * Addition of supplementary files, that are needed directly for installation process: installer with GUI interface, readme, license, some additional
137
		 * information about available languages, themes, current version of system
138
		 */
139 4
		$phar->addFile("$this->root/license.txt", 'license.txt');
140 4
		$phar->addFile("$this->root/modules/System/meta.json", 'meta.json');
141 4
		$phar->setStub(
142
		/** @lang PHP */
143
			<<<STUB
144
<?php
145
if (version_compare(PHP_VERSION, '5.6', '<')) {
146
	echo 'CleverStyle Framework require PHP 5.6 or higher';
147
	return;
148
}
149
150
if (PHP_SAPI == 'cli') {
151
	Phar::mapPhar('cleverstyle_framework.phar');
152
	include 'phar://cleverstyle_framework.phar/cli.php';
153
} else {
154
	Phar::webPhar(null, 'web.php');
155
}
156 4
__HALT_COMPILER();
157
STUB
158
		);
159 4
		$phar->stopBuffering();
160 4
		return "Done! CleverStyle Framework $version";
161
	}
162
	/**
163
	 * Get array of files
164
	 *
165
	 * @return string[]
166
	 */
167 4
	protected function get_core_files () {
168
		$files_to_include = [
169 4
			"$this->root/modules/System",
170 4
			"$this->root/blocks/.gitkept",
171 4
			"$this->root/core",
172 4
			"$this->root/custom",
173 4
			"$this->root/includes",
174 4
			"$this->root/themes/CleverStyle",
175 4
			"$this->root/bower.json",
176 4
			"$this->root/cli",
177 4
			"$this->root/composer.json",
178 4
			"$this->root/composer.lock",
179 4
			"$this->root/index.php",
180 4
			"$this->root/license.txt",
181 4
			"$this->root/package.json",
182 4
			"$this->root/Storage.php"
183
		];
184 4
		$files            = [];
185 4
		foreach ($files_to_include as $s) {
186 4
			if (is_file($s)) {
187 4
				$files[] = $s;
188 4
			} elseif (is_dir($s)) {
189
				/** @noinspection SlowArrayOperationsInLoopInspection */
190 4
				$files = array_merge(
191
					$files,
192 4
					get_files_list($s, false, 'f', true, true, false, false, true)
193
				);
194
			}
195
		}
196 4
		return $files;
197
	}
198
	/**
199
	 * @param string   $dir
200
	 * @param string[] $components
201
	 * @param string[] $components_files
202
	 *
203
	 * @return string[]
204
	 */
205 4
	protected function filter_and_add_components ($dir, $components, &$components_files) {
206 4
		$components = array_filter(
207
			$components,
208 4
			function ($component) use ($dir, &$components_files) {
209
				return $this->get_component_files("$dir/$component", $components_files);
210 4
			}
211
		);
212 4
		sort($components);
213 4
		return $components;
214
	}
215
	/**
216
	 * @param string   $component_root
217
	 * @param string[] $files Array, where new files will be appended
218
	 *
219
	 * @return bool
220
	 */
221
	protected function get_component_files ($component_root, &$files) {
222
		/**
223
		 * Do not allow building System module and CleverStyle theme
224
		 */
225
		if (in_array(basename($component_root), ['System', 'CleverStyle'])) {
226
			return false;
227
		}
228
		/**
229
		 * Components without meta.json also not allowed
230
		 */
231
		if (!file_exists("$component_root/meta.json")) {
232
			return false;
233
		}
234
		@unlink("$component_root/fs.json");
235
		$local_files = get_files_list($component_root, false, 'f', true, true, false, false, true);
236
		$files       = array_merge($files, $local_files);
237
		file_put_json(
238
			"$component_root/fs.json",
239
			array_values(
240
				_substr(
241
					$local_files,
242
					strlen("$component_root/")
243
				)
244
			)
245
		);
246
		$files[] = "$component_root/fs.json";
247
		return true;
248
	}
249
	/**
250
	 * @return string
251
	 */
252 4
	protected function get_htaccess () {
253
		/** @lang ApacheConfig */
254
		return <<<HTACCESS
255
AddDefaultCharset utf-8
256
Options -Indexes -Multiviews +FollowSymLinks
257
IndexIgnore *.php *.pl *.cgi *.htaccess *.htpasswd
258
259
RewriteEngine On
260
RewriteBase /
261
262
<FilesMatch ".*/.*">
263
	Options -FollowSymLinks
264
</FilesMatch>
265
<FilesMatch "\.(css|js|gif|jpg|jpeg|png|ico|svg|svgz|ttc|ttf|otf|woff|woff2|eot)$">
266
	RewriteEngine Off
267
</FilesMatch>
268
<Files license.txt>
269
	RewriteEngine Off
270
</Files>
271
#<Files Storage.php>
272
#	RewriteEngine Off
273
#</Files>
274
275 4
RewriteRule .* index.php
276
HTACCESS;
277
	}
278
	/**
279
	 * @param string      $module
280
	 * @param null|string $suffix
281
	 *
282
	 * @return string
283
	 */
284
	function module ($module, $suffix = null) {
285
		if ($module == 'System') {
286
			return "Can't build module, System module is a part of core, it is not necessary to build it as separate module";
287
		}
288
		return $this->generic_package_creation("$this->root/modules/$module", $suffix);
289
	}
290
	/**
291
	 * @param string      $theme
292
	 * @param null|string $suffix
293
	 *
294
	 * @return string
295
	 */
296
	function theme ($theme, $suffix = null) {
297
		if ($theme == 'CleverStyle') {
298
			return "Can't build theme, CleverStyle theme is a part of core, it is not necessary to build it as separate theme";
299
		}
300
		return $this->generic_package_creation("$this->root/themes/$theme", $suffix);
301
	}
302
	protected function generic_package_creation ($source_dir, $suffix = null) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
303
		if (!file_exists("$source_dir/meta.json")) {
304
			$component = basename($source_dir);
305
			return "Can't build $component, meta information (meta.json) not found";
306
		}
307
		$meta = file_get_json("$source_dir/meta.json");
308
		$type = '';
309
		$Type = '';
310
		switch ($meta['category']) {
311
			case 'modules':
312
				$type = 'module_';
313
				$Type = 'Module';
314
				break;
315
			case 'themes':
316
				$type = 'theme_';
317
				$Type = 'Theme';
318
				break;
319
		}
320
		$suffix      = $suffix ? "_$suffix" : '';
321
		$target_file = "$this->target/$type$meta[package]_$meta[version]$suffix.phar.php";
322
		if (file_exists($target_file)) {
323
			unlink($target_file);
324
		}
325
		$phar = new Phar($target_file);
326
		unset($target_file);
327
		$phar->startBuffering();
328
		@unlink("$source_dir/fs.json");
329
		$files  = get_files_list($source_dir, false, 'f', true, true, false, false, true);
330
		$length = strlen("$source_dir/");
331
		foreach ($files as $index => &$file) {
332
			$phar->addFile($file, "fs/$index");
333
			$file = substr($file, $length);
334
		}
335
		unset($index, $file, $length);
336
		/**
337
		 * Flip array to have direct access to files by name during extraction
338
		 */
339
		$phar->addFromString(
340
			'fs.json',
341
			_json_encode(
342
				array_flip($files)
343
			)
344
		);
345
		unset($files);
346
		$phar->addFile("$source_dir/meta.json", 'meta.json');
347
		$readme = false;
348
		if (file_exists("$source_dir/readme.html")) {
349
			$phar->addFile("$source_dir/readme.html", 'readme.html');
350
			$readme = 'readme.html';
351
		} elseif (file_exists("$source_dir/readme.txt")) {
352
			$phar->addFile("$source_dir/readme.txt", 'readme.txt');
353
			$readme = 'readme.txt';
354
		}
355
		if ($readme) {
356
			$phar->setStub("<?php Phar::webPhar(null, '$readme'); __HALT_COMPILER();");
357
		} else {
358
			$phar->addFromString('index.html', isset($meta['description']) ? $meta['description'] : $meta['package']);
359
			$phar->setStub("<?php Phar::webPhar(null, 'index.html'); __HALT_COMPILER();");
360
		}
361
		$phar->stopBuffering();
362
		return "Done! $Type $meta[package] $meta[version]";
363
	}
364
}
365