Completed
Push — master ( 265d0d...5b91fe )
by Nazar
07:12
created

Builder::generic_package_creation()   C

Complexity

Conditions 11
Paths 145

Size

Total Lines 62
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 11.5269

Importance

Changes 0
Metric Value
cc 11
eloc 49
nc 145
nop 2
dl 0
loc 62
ccs 41
cts 49
cp 0.8367
crap 11.5269
rs 5.7264
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @package    CleverStyle Framework
4
 * @subpackage Builder
5
 * @author     Nazar Mokrynskyi <[email protected]>
6
 * @copyright  Copyright (c) 2011-2017, 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 15
	public function __construct ($root, $target) {
27 15
		$this->root   = $root;
28 15
		$this->target = $target;
29
		/** @noinspection MkdirRaceConditionInspection */
30 15
		@mkdir($target);
31 15
	}
32
	/**
33
	 * @param string[]    $modules
34
	 * @param string[]    $themes
35
	 * @param null|string $suffix
36
	 *
37
	 * @return string
38
	 *
39
	 * @throws \UnexpectedValueException
40
	 * @throws \BadMethodCallException
41
	 */
42 8
	public function core ($modules = [], $themes = [], $suffix = null) {
43 8
		$suffix      = $suffix ? "_$suffix" : '';
44 8
		$version     = file_get_json("$this->root/modules/System/meta.json")['version'];
45 8
		$target_file = "$this->target/CleverStyle_Framework_$version$suffix.phar.php";
46 8
		if (file_exists($target_file)) {
47
			unlink($target_file);
48
		}
49 8
		$phar = new Phar($target_file);
50 8
		unset($target_file);
51 8
		$phar->startBuffering();
52 8
		$length = strlen("$this->root/");
53
		/** @noinspection ForeachSourceInspection */
54 8
		foreach (get_files_list("$this->root/install", false, 'f', '', true) as $file) {
55 8
			$phar->addFile("$this->root/install/$file", $file);
56
		}
57 8
		unset($file);
58 8
		$phar->addFile("$this->root/assets/img/logo.svg", 'logo.svg');
59
		/**
60
		 * Core files to be included into installation package
61
		 */
62 8
		$core_files = $this->get_core_files();
63
		/**
64
		 * Add modules that should be built-in into package
65
		 */
66 8
		$components_files = [];
67 8
		$modules          = $this->filter_and_add_components("$this->root/modules", $modules, $components_files);
68 8
		$phar->addFromString('modules.json', _json_encode($modules));
69
		/**
70
		 * Add themes that should be built-in into package
71
		 */
72 8
		$themes = $this->filter_and_add_components("$this->root/themes", $themes, $components_files);
73 8
		$phar->addFromString('themes.json', _json_encode($themes));
74
		/**
75
		 * Joining system and components files
76
		 */
77 8
		$core_files = array_merge($core_files, $components_files);
78
		/**
79
		 * Addition of files into package
80
		 */
81 8
		foreach ($core_files as $index => &$file) {
82 8
			$phar->addFile($file, "fs/$index");
83 8
			$file = substr($file, $length);
84
		}
85 8
		unset($index, $file);
86
		/**
87
		 * Add license under the file `license-cleverstyle-framework.txt` rather than `license.txt`, so that license is not enforced on projects using it and is
88
		 * not overridden on framework update
89
		 */
90 8
		$phar->addFile("$this->root/license.txt", 'fs/'.count($core_files));
91 8
		$core_files[] = 'license-cleverstyle-framework.txt';
92
		/**
93
		 * Addition of separate files into package
94
		 */
95 8
		$phar->addFromString(
96 8
			'languages.json',
97 8
			_json_encode(
98 8
				array_merge(
99 8
					_substr(get_files_list("$this->root/core/languages", '/^.*?\.php$/i', 'f'), 0, -4) ?: [],
0 ignored issues
show
Bug introduced by
It seems like _substr(get_files_list(E...'f'), 0, -4) ?: array() can also be of type string; however, parameter $array1 of array_merge() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

99
					/** @scrutinizer ignore-type */ _substr(get_files_list("$this->root/core/languages", '/^.*?\.php$/i', 'f'), 0, -4) ?: [],
Loading history...
100 8
					_substr(get_files_list("$this->root/core/languages", '/^.*?\.json$/i', 'f'), 0, -5) ?: []
0 ignored issues
show
Bug introduced by
It seems like _substr(get_files_list(E...'f'), 0, -5) ?: array() can also be of type string; however, parameter $array2 of array_merge() does only seem to accept null|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

100
					/** @scrutinizer ignore-type */ _substr(get_files_list("$this->root/core/languages", '/^.*?\.json$/i', 'f'), 0, -5) ?: []
Loading history...
101
				)
102
			)
103
		);
104 8
		$phar->addFromString(
105 8
			'db_drivers.json',
106 8
			_json_encode(
107 8
				_substr(get_files_list("$this->root/core/drivers/DB", '/^[^_].*?\.php$/i', 'f'), 0, -4)
108
			)
109
		);
110
		/**
111
		 * Fixation of system files list (without components files), it is needed for future system updating
112
		 */
113 8
		$phar->addFromString(
114 8
			'fs.json',
115 8
			_json_encode(
116 8
				array_flip(
117 8
					array_diff(
118 8
						$core_files,
119 8
						_substr($components_files, $length)
0 ignored issues
show
Bug introduced by
It seems like _substr($components_files, $length) can also be of type string; however, parameter $array2 of array_diff() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

119
						/** @scrutinizer ignore-type */ _substr($components_files, $length)
Loading history...
120
					)
121
				)
122
			)
123
		);
124 8
		unset($components_files, $length);
125
		/**
126
		 * Addition of files, that are needed only for installation
127
		 */
128 8
		$phar->addFromString('fs/'.count($core_files), $this->get_htaccess());
129 8
		$core_files[] = '.htaccess';
130 8
		$phar->addFile("$this->root/config/main.php", 'fs/'.count($core_files));
131 8
		$core_files[] = 'config/main.php';
132 8
		$phar->addFile("$this->root/favicon.ico", 'fs/'.count($core_files));
133 8
		$core_files[] = 'favicon.ico';
134 8
		$phar->addFile("$this->root/.gitignore", 'fs/'.count($core_files));
135 8
		$core_files[] = '.gitignore';
136
		/**
137
		 * Flip array to have direct access to files by name during extracting and installation, and fixing of files list for installation
138
		 */
139 8
		$phar->addFromString(
140 8
			'fs_installer.json',
141 8
			_json_encode(
142 8
				array_flip($core_files)
143
			)
144
		);
145 8
		unset($core_files);
146
		/**
147
		 * Addition of supplementary files, that are needed directly for installation process: installer with GUI interface, readme, license, some additional
148
		 * information about available languages, themes, current version of system
149
		 */
150 8
		$phar->addFile("$this->root/license.txt", 'license.txt');
151 8
		$phar->addFile("$this->root/modules/System/meta.json", 'meta.json');
152 8
		$phar->setStub(
153
		/** @lang PHP */
154
			<<<STUB
155 8
<?php
156
if (version_compare(PHP_VERSION, '7.0', '<')) {
157
	echo 'CleverStyle Framework requires PHP 7.0 or higher';
158
	return;
159
}
160
161
if (php_sapi_name() == 'cli') {
162
	Phar::mapPhar('cleverstyle_framework.phar');
163
	include 'phar://cleverstyle_framework.phar/cli.php';
164
} else {
165
	Phar::webPhar(null, 'web.php');
166
}
167
__HALT_COMPILER();
168
STUB
169
		);
170 8
		$phar->stopBuffering();
171 8
		return "Done! CleverStyle Framework $version";
172
	}
173
	/**
174
	 * Get array of files
175
	 *
176
	 * @return string[]
177
	 */
178 8
	protected function get_core_files () {
179
		$files_to_include = [
180 8
			"$this->root/assets",
181 8
			"$this->root/blocks/.gitkept",
182 8
			"$this->root/core",
183 8
			"$this->root/custom",
184 8
			"$this->root/modules/System",
185 8
			"$this->root/storage/.htaccess",
186 8
			"$this->root/storage/public_cache/.htaccess",
187 8
			"$this->root/storage/public/.htaccess",
188 8
			"$this->root/storage/temp/.htaccess",
189 8
			"$this->root/themes/CleverStyle",
190 8
			"$this->root/bower.json",
191 8
			"$this->root/cli",
192 8
			"$this->root/composer.json",
193 8
			"$this->root/composer.lock",
194 8
			"$this->root/index.php",
195 8
			"$this->root/package.json"
196
		];
197 8
		$files            = [];
198 8
		foreach ($files_to_include as $s) {
199 8
			if (is_file($s)) {
200 8
				$files[] = $s;
201 8
			} elseif (is_dir($s)) {
202
				/** @noinspection SlowArrayOperationsInLoopInspection */
203 8
				$files = array_merge(
204 8
					$files,
205 8
					get_files_list($s, false, 'f', true, true, false, false, true)
206
				);
207
			}
208
		}
209 8
		return $files;
210
	}
211
	/**
212
	 * @param string   $dir
213
	 * @param string[] $components
214
	 * @param string[] $components_files
215
	 *
216
	 * @return string[]
217
	 */
218 8
	protected function filter_and_add_components ($dir, $components, &$components_files) {
219 8
		$components = array_filter(
220 8
			$components,
221 8
			function ($component) use ($dir, &$components_files) {
222 1
				return $this->get_component_files("$dir/$component", $components_files);
223 8
			}
224
		);
225 8
		sort($components);
226 8
		return $components;
227
	}
228
	/**
229
	 * @param string   $component_root
230
	 * @param string[] $files Array, where new files will be appended
231
	 *
232
	 * @return bool
233
	 */
234 1
	protected function get_component_files ($component_root, &$files) {
235
		/**
236
		 * Do not allow building System module and CleverStyle theme
237
		 */
238 1
		if (in_array(basename($component_root), ['System', 'CleverStyle'])) {
239 1
			return false;
240
		}
241
		/**
242
		 * Components without meta.json also not allowed
243
		 */
244 1
		if (!file_exists("$component_root/meta.json")) {
245 1
			return false;
246
		}
247 1
		@unlink("$component_root/fs.json");
248 1
		$local_files = get_files_list($component_root, false, 'f', true, true, false, false, true);
249 1
		$files       = array_merge($files, $local_files);
250 1
		file_put_json(
251 1
			"$component_root/fs.json",
252 1
			array_values(
253 1
				_substr(
0 ignored issues
show
Bug introduced by
It seems like _substr($local_files, strlen(EncapsedNode)) can also be of type string; however, parameter $input of array_values() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

253
				/** @scrutinizer ignore-type */ _substr(
Loading history...
254 1
					$local_files,
255 1
					strlen("$component_root/")
256
				)
257
			)
258
		);
259 1
		$files[] = "$component_root/fs.json";
260 1
		return true;
261
	}
262
	/**
263
	 * @return string
264
	 */
265 8
	protected function get_htaccess () {
266
		/** @lang ApacheConfig */
267
		return <<<HTACCESS
268 8
AddDefaultCharset utf-8
269
Options -Indexes -Multiviews +FollowSymLinks
270
IndexIgnore *.php *.pl *.cgi *.htaccess *.htpasswd
271
FileETag None
272
273
RewriteEngine On
274
RewriteBase /
275
276
<FilesMatch ".*/.*">
277
	Options -FollowSymLinks
278
</FilesMatch>
279
<FilesMatch "\.(css|js|gif|jpg|jpeg|png|ico|svg|svgz|ttc|ttf|otf|woff|woff2|eot)$">
280
	RewriteEngine Off
281
</FilesMatch>
282
<FilesMatch "\.(css|js|gif|jpg|jpeg|png|ico|svg|svgz|ttc|ttf|otf|woff|woff2|eot|html)$">
283
	<ifModule mod_expires.c>
284
		ExpiresActive On
285
		ExpiresDefault "access plus 1 month"
286
	</ifModule>
287
	<ifModule mod_headers.c>
288
		Header set Cache-Control "max-age=2592000, immutable"
289
	</ifModule>
290
</FilesMatch>
291
<Files license.txt>
292
	RewriteEngine Off
293
</Files>
294
295
RewriteRule .* index.php
296
HTACCESS;
297
	}
298
	/**
299
	 * @param string      $module
300
	 * @param null|string $suffix
301
	 *
302
	 * @return string
303
	 */
304 4
	public function module ($module, $suffix = null) {
305 4
		if ($module == 'System') {
306 1
			return "Can't build module, System module is a part of core, it is not necessary to build it as separate module";
307
		}
308 3
		return $this->generic_package_creation("$this->root/modules/$module", $suffix);
309
	}
310
	/**
311
	 * @param string      $theme
312
	 * @param null|string $suffix
313
	 *
314
	 * @return string
315
	 */
316 3
	public function theme ($theme, $suffix = null) {
317 3
		if ($theme == 'CleverStyle') {
318 1
			return "Can't build theme, CleverStyle theme is a part of core, it is not necessary to build it as separate theme";
319
		}
320 2
		return $this->generic_package_creation("$this->root/themes/$theme", $suffix);
321
	}
322
	/**
323
	 * @param string      $source_dir
324
	 * @param null|string $suffix
325
	 *
326
	 * @return string
327
	 */
328 5
	protected function generic_package_creation ($source_dir, $suffix = null) {
329 5
		if (!file_exists("$source_dir/meta.json")) {
330 1
			$component = basename($source_dir);
331 1
			return "Can't build $component, meta information (meta.json) not found";
332
		}
333 4
		$meta = file_get_json("$source_dir/meta.json");
334 4
		$type = '';
335 4
		$Type = '';
336 4
		switch ($meta['category']) {
337
			case 'modules':
338 2
				$type = 'module_';
339 2
				$Type = 'Module';
340 2
				break;
341
			case 'themes':
342 2
				$type = 'theme_';
343 2
				$Type = 'Theme';
344 2
				break;
345
		}
346 4
		$suffix      = $suffix ? "_$suffix" : '';
347 4
		$target_file = "$this->target/$type$meta[package]_$meta[version]$suffix.phar.php";
348 4
		if (file_exists($target_file)) {
349
			unlink($target_file);
350
		}
351 4
		$phar = new Phar($target_file);
352 4
		unset($target_file);
353 4
		$phar->startBuffering();
354 4
		@unlink("$source_dir/fs.json");
355 4
		$files  = get_files_list($source_dir, false, 'f', true, true, false, false, true);
356 4
		$length = strlen("$source_dir/");
357
		/** @noinspection ForeachSourceInspection */
358 4
		foreach ($files as $index => &$file) {
359 4
			$phar->addFile($file, "fs/$index");
360 4
			$file = substr($file, $length);
361
		}
362 4
		unset($index, $file, $length);
363
		/**
364
		 * Flip array to have direct access to files by name during extraction
365
		 */
366 4
		$phar->addFromString(
367 4
			'fs.json',
368 4
			_json_encode(
369 4
				array_flip($files)
370
			)
371
		);
372 4
		unset($files);
373 4
		$phar->addFile("$source_dir/meta.json", 'meta.json');
374 4
		$readme = false;
375 4
		if (file_exists("$source_dir/readme.html")) {
376
			$phar->addFile("$source_dir/readme.html", 'readme.html');
377
			$readme = 'readme.html';
378 4
		} elseif (file_exists("$source_dir/readme.txt")) {
379
			$phar->addFile("$source_dir/readme.txt", 'readme.txt');
380
			$readme = 'readme.txt';
381
		}
382 4
		if ($readme) {
383
			$phar->setStub("<?php Phar::webPhar(null, '$readme'); __HALT_COMPILER();");
384
		} else {
385 4
			$phar->addFromString('index.html', isset($meta['description']) ? $meta['description'] : $meta['package']);
386 4
			$phar->setStub("<?php Phar::webPhar(null, 'index.html'); __HALT_COMPILER();");
387
		}
388 4
		$phar->stopBuffering();
389 4
		return "Done! $Type $meta[package] $meta[version]";
390
	}
391
}
392