Completed
Push — master ( d82b6b...206636 )
by Nazar
08:39
created

Installer::initialize_system_config()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 85
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 54
CRAP Score 3.0013

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 3
eloc 71
nc 4
nop 9
dl 0
loc 85
ccs 54
cts 57
cp 0.9474
crap 3.0013
rs 8.6875
c 2
b 0
f 1

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @package    CleverStyle Framework
4
 * @subpackage Installer
5
 * @author     Nazar Mokrynskyi <[email protected]>
6
 * @copyright  Copyright (c) 2016, Nazar Mokrynskyi
7
 * @license    MIT License, see license.txt
8
 */
9
namespace cs;
10
use
11
	RuntimeException;
12
13
class Installer {
14
	const MAIN_CONFIG_STUB = /** @lang JSON */
15
		<<<CONFIG
16
{
17
//Domain of main mirror
18
	"domain"			: "@domain",
19
//Base timezone
20
	"timezone"			: "@timezone",
21
//Settings of main DB
22
	"db_host"			: "@db_host",
23
	"db_type"			: "@db_type",
24
	"db_name"			: "@db_name",
25
	"db_user"			: "@db_user",
26
	"db_password"		: "@db_password",
27
	"db_prefix"			: "@db_prefix",
28
//Settings of main Storage
29
	"storage_type"		: "Local",
30
	"storage_url"		: "",
31
	"storage_host"		: "localhost",
32
	"storage_user"		: "",
33
	"storage_password"	: "",
34
//Base language
35
	"language"			: "@language",
36
//Cache engine
37
	"cache_engine"		: "FileSystem",
38
//Settings of Memcached cache engine
39
	"memcache_host"		: "127.0.0.1",
40
	"memcache_port"		: "11211",
41
//Any length
42
	"public_key"		: "@public_key"
43
}
44
45
CONFIG;
46
	/**
47
	 * @param string $source
48
	 * @param string $target
49
	 * @param string $site_name
50
	 * @param string $url
51
	 * @param string $timezone
52
	 * @param string $db_host
53
	 * @param string $db_engine
54
	 * @param string $db_name
55
	 * @param string $db_user
56
	 * @param string $db_password
57
	 * @param string $db_prefix
58
	 * @param string $language
59
	 * @param string $admin_email
60
	 * @param string $admin_password
61
	 * @param int    $mode
62
	 *
63
	 * @throws RuntimeException
64
	 */
65 4
	public static function install (
66
		$source,
67
		$target,
68
		$site_name,
69
		$url,
70
		$timezone,
71
		$db_host,
72
		$db_engine,
73
		$db_name,
74
		$db_user,
75
		$db_password,
76
		$db_prefix,
77
		$language,
78
		$admin_email,
79
		$admin_password,
80
		$mode
81
	) {
82 4
		static::pre_installation_checks($source, $target, $db_engine);
83
		// Needed to be defined before connecting to the database
84 4
		defined('DEBUG') || define('DEBUG', false);
85 4
		$file_index_map = static::initialize_filesystem($source);
86 4
		static::extract($file_index_map, $source, $target);
87 4
		$domain     = parse_url($url, PHP_URL_HOST);
88 4
		$public_key = hash('sha512', random_bytes(1000));
89 4
		static::initialize_core_config(
90
			$target,
91
			$domain,
92
			$timezone,
93
			$db_host,
94
			$db_engine,
95
			$db_name,
96
			$db_user,
97
			$db_password,
98
			$db_prefix,
99
			$language,
100
			$public_key
101
		);
102
		/**
103
		 * @var \cs\DB\_Abstract $cdb
104
		 */
105 4
		$cdb = "cs\\DB\\$db_engine";
106 4
		$cdb = new $cdb($db_name, $db_user, $db_password, $db_host, $db_prefix);
107 4
		if (!is_object($cdb) || !$cdb->connected()) {
108
			throw new RuntimeException("Can't connect to database! Installation aborted.");
109
		}
110 4
		static::initialize_db_structure($cdb, $source, $db_engine);
111 4
		static::initialize_system_config($cdb, $source, $site_name, $url, $admin_email, $language, $domain, $timezone, $mode);
112 4
		static::create_root_administrator($cdb, $admin_email, $admin_password, $public_key);
113 4
		unset($cdb);
114 4
	}
115
	/**
116
	 * @param string $source
117
	 * @param string $target
118
	 * @param string $db_engine
119
	 *
120
	 * @throws RuntimeException
121
	 */
122 4
	protected static function pre_installation_checks ($source, $target, $db_engine) {
123 4
		if (file_exists("$target/config/main.json")) {
124
			throw new RuntimeException('"config/main.json" file already present! Installation aborted.');
125
		}
126 4
		if (!file_exists("$source/DB/$db_engine.sql")) {
127
			throw new RuntimeException("Can't find system tables structure for selected database engine! Installation aborted.");
128
		}
129 4
	}
130
	/**
131
	 * @param string $source
132
	 *
133
	 * @return array[]
134
	 */
135 4
	protected static function initialize_filesystem ($source) {
136 4
		$file_index_map = json_decode(file_get_contents("$source/fs_installer.json"), true);
137 4
		require_once "$source/fs/".$file_index_map['core/thirdparty/upf.php'];
138 4
		require_once "$source/fs/".$file_index_map['core/functions.php'];
139
		// Remove default autoloader, since we have special autoloader suitable for operating inside installer where default will fail hard
140 4
		spl_autoload_unregister(array_reverse(spl_autoload_functions())[0]);
141
		/**
142
		 * Special autoloader for installer
143
		 */
144 4
		spl_autoload_register(
145 4
			function ($class) use ($file_index_map, $source) {
146 4
				$prepared_class_name = ltrim($class, '\\');
147 4
				if (strpos($prepared_class_name, 'cs\\') === 0) {
148 4
					$prepared_class_name = substr($prepared_class_name, 3);
149
				}
150 4
				$prepared_class_name = explode('\\', $prepared_class_name);
151 4
				$namespace           = count($prepared_class_name) > 1 ? implode('/', array_slice($prepared_class_name, 0, -1)) : '';
152 4
				$class_name          = array_pop($prepared_class_name);
153
				/**
154
				 * Try to load classes from different places. If not found in one place - try in another.
155
				 */
156
				if (
157 4
					strlen($file = @$file_index_map[str_replace('//', '/', "core/classes/$namespace/$class_name.php")]) ||    //Core classes
158 4
					strlen($file = @$file_index_map[str_replace('//', '/', "core/thirdparty/$namespace/$class_name.php")]) || //Third party classes
159 4
					strlen($file = @$file_index_map[str_replace('//', '/', "core/traits/$namespace/$class_name.php")]) ||     //Core traits
160 4
					strlen($file = @$file_index_map[str_replace('//', '/', "core/engines/$namespace/$class_name.php")]) ||    //Core engines
161 4
					strlen($file = @$file_index_map[str_replace('//', '/', "$namespace/$class_name.php")])                    //Classes in modules
162
				) {
163 4
					require_once "$source/fs/$file";
164 4
					return true;
165
				}
166
				return false;
167 4
			}
168
		);
169 4
		return $file_index_map;
170
	}
171
	/**
172
	 * @param array[] $file_index_map
173
	 * @param string  $source
174
	 * @param string  $target
175
	 *
176
	 * @throws RuntimeException
177
	 */
178 4
	protected static function extract ($file_index_map, $source, $target) {
179
		/**
180
		 * Extracting of engine's files
181
		 */
182 4
		foreach ($file_index_map as $file_path => $file_index) {
183 4
			$dir = dirname("$target/$file_path");
184 4
			if (!@mkdir($dir, 0770, true) && !is_dir($dir)) {
185
				throw new RuntimeException("Can't extract system files from the archive, creating directory $dir failed! Installation aborted.");
186
			}
187 4
			if (!copy("$source/fs/$file_index", "$target/$file_path")) {
188 4
				throw new RuntimeException("Can't extract system files from the archive, creating file $target/$file_path failed! Installation aborted.");
189
			}
190
		}
191 4
		file_put_json("$target/core/fs.json", array_keys(file_get_json("$source/fs.json")));
192
		/**
193
		 * Make CLI executable
194
		 */
195 4
		chmod("$target/cli", 0770);
196 4
	}
197
	/**
198
	 * @param string $target
199
	 * @param string $domain
200
	 * @param string $timezone
201
	 * @param string $db_host
202
	 * @param string $db_engine
203
	 * @param string $db_name
204
	 * @param string $db_user
205
	 * @param string $db_password
206
	 * @param string $db_prefix
207
	 * @param string $language
208
	 * @param string $public_key
209
	 *
210
	 * @throws RuntimeException
211
	 */
212 4
	protected static function initialize_core_config (
213
		$target,
214
		$domain,
215
		$timezone,
216
		$db_host,
217
		$db_engine,
218
		$db_name,
219
		$db_user,
220
		$db_password,
221
		$db_prefix,
222
		$language,
223
		$public_key
224
	) {
225 4
		$db_password = str_replace('"', '\\"', $db_password);
226 4
		$config      = str_replace(
227 4
			['@domain', '@timezone', '@db_host', '@db_type', '@db_name', '@db_user', '@db_password', '@db_prefix', '@language', '@public_key'],
228 4
			[$domain, $timezone, $db_host, $db_engine, $db_name, $db_user, $db_password, $db_prefix, $language, $public_key],
229 4
			self::MAIN_CONFIG_STUB
230
		);
231 4
		if (!file_put_contents("$target/config/main.json", $config)) {
232
			throw new RuntimeException("Can't write core system configuration! Installation aborted.");
233
		}
234 4
		chmod("$target/config/main.json", 0600);
235 4
	}
236
	/**
237
	 * @param DB\_Abstract $cdb
238
	 * @param string       $source
239
	 * @param string       $db_engine
240
	 *
241
	 * @throws RuntimeException
242
	 */
243 4
	protected static function initialize_db_structure ($cdb, $source, $db_engine) {
244 4
		$query = array_filter(
245 4
			explode(';', file_get_contents("$source/DB/$db_engine.sql")),
246 4
			'trim'
247
		);
248 4
		if (!$cdb->q($query)) {
249
			throw new RuntimeException("Can't import system tables structure for selected database engine! Installation aborted.");
250
		}
251 4
	}
252
	/**
253
	 * @param DB\_Abstract $cdb
254
	 * @param string       $source
255
	 * @param string       $site_name
256
	 * @param string       $url
257
	 * @param string       $admin_email
258
	 * @param string       $language
259
	 * @param string       $domain
260
	 * @param string       $timezone
261
	 * @param int          $mode
262
	 *
263
	 * @throws RuntimeException
264
	 */
265 4
	protected static function initialize_system_config ($cdb, $source, $site_name, $url, $admin_email, $language, $domain, $timezone, $mode) {
266
		$config     = [
267 4
			'name'                              => $site_name,
268 4
			'url'                               => [$url],
269 4
			'admin_email'                       => $admin_email,
270 4
			'closed_title'                      => 'Site closed',
271 4
			'closed_text'                       => '<p>Site closed for maintenance</p>',
272 4
			'site_mode'                         => 1,
273 4
			'title_delimiter'                   => ' | ',
274 4
			'title_reverse'                     => 0,
275 4
			'cache_compress_js_css'             => 1,
276 4
			'frontend_load_optimization'        => 1,
277 4
			'vulcanization'                     => 1,
278 4
			'put_js_after_body'                 => 1,
279 4
			'disable_webcomponents'             => 0,
280 4
			'theme'                             => 'CleverStyle',
281 4
			'language'                          => $language,
282 4
			'active_languages'                  => [$language],
283 4
			'multilingual'                      => 0,
284 4
			'db_balance'                        => 0,
285 4
			'db_mirror_mode'                    => DB::MIRROR_MODE_MASTER_MASTER,
286 4
			'cookie_prefix'                     => '',
287 4
			'cookie_domain'                     => [$domain],
288 4
			'inserts_limit'                     => 1000,
289
			'key_expire'                        => 60 * 2,
290 4
			'gravatar_support'                  => 0,
291
			'session_expire'                    => 3600 * 24 * 30,
292 4
			'update_ratio'                      => 75,
293 4
			'sign_in_attempts_block_count'      => 0,
294 4
			'sign_in_attempts_block_time'       => 5,
295 4
			'timezone'                          => $timezone,
296 4
			'password_min_length'               => 4,
297 4
			'password_min_strength'             => 3,
298 4
			'smtp'                              => 0,
299 4
			'smtp_host'                         => '',
300 4
			'smtp_port'                         => '',
301 4
			'smtp_secure'                       => '',
302 4
			'smtp_auth'                         => 0,
303 4
			'smtp_user'                         => '',
304 4
			'smtp_password'                     => '',
305 4
			'mail_from'                         => $admin_email,
306 4
			'mail_from_name'                    => "Administrator of $site_name",
307 4
			'allow_user_registration'           => 1,
308 4
			'require_registration_confirmation' => 1,
309 4
			'auto_sign_in_after_registration'   => 1,
310 4
			'registration_confirmation_time'    => 1,
311 4
			'mail_signature'                    => '',
312 4
			'remember_user_ip'                  => 0,
313 4
			'simple_admin_mode'                 => $mode,
314 4
			'default_module'                    => Config::SYSTEM_MODULE
315
		];
316
		$components = [
317
			'modules' => [
318
				'System' => [
319 4
					'active' => Config\Module_Properties::ENABLED,
320
					'db'     => [
321
						'keys'  => '0',
322
						'users' => '0',
323
						'texts' => '0'
324
					]
325
				]
326 4
			],
327
			'blocks'  => []
328
		];
329 4
		foreach (file_get_json("$source/modules.json") as $module) {
330
			$components['modules'][$module] = [
331
				'active'  => Config\Module_Properties::UNINSTALLED,
332
				'db'      => [],
333
				'storage' => []
334
			];
335
		}
336 4
		$result = $cdb->q(
337
			"INSERT INTO `[prefix]config` (
338
				`domain`, `core`, `db`, `storage`, `components`
339
			) VALUES (
340
				'%s', '%s', '[]', '[]', '%s'
341 4
			)",
342
			$domain,
343
			_json_encode($config),
344
			_json_encode($components)
345
		);
346 4
		if (!$result) {
347
			throw new RuntimeException("Can't import system configuration into database! Installation aborted.");
348
		}
349 4
	}
350
	/**
351
	 * @param DB\_Abstract $cdb
352
	 * @param string       $admin_email
353
	 * @param string       $admin_password
354
	 * @param string       $public_key
355
	 *
356
	 * @throws RuntimeException
357
	 */
358 4
	protected static function create_root_administrator ($cdb, $admin_email, $admin_password, $public_key) {
359 4
		$admin_email = strtolower($admin_email);
360 4
		$admin_login = strstr($admin_email, '@', true);
361 4
		$result      = $cdb->q(
362
			"INSERT INTO `[prefix]users` (
363
				`login`, `login_hash`, `password_hash`, `email`, `email_hash`, `reg_date`, `reg_ip`, `status`
364
			) VALUES (
365
				'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'
366 4
			)",
367
			$admin_login,
368 4
			hash('sha224', $admin_login),
369 4
			password_hash(hash('sha512', hash('sha512', $admin_password).$public_key), PASSWORD_DEFAULT),
370
			$admin_email,
371 4
			hash('sha224', $admin_email),
372
			time(),
373 4
			'127.0.0.1',
374 4
			User::STATUS_ACTIVE
375
		);
376 4
		if (!$result) {
377
			throw new RuntimeException("Can't register root administrator user! Installation aborted.");
378
		}
379 4
	}
380
}
381