Completed
Push — master ( f3fec3...c7133e )
by Nazar
04:51
created

Installer::initialize_core_config()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 20
nc 2
nop 11
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0

How to fix   Many Parameters   

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
	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
		static::pre_installation_checks($source, $target, $db_engine);
83
		// Needed to be defined before connecting to the database
84
		defined('DEBUG') || define('DEBUG', false);
85
		$file_index_map = static::initialize_filesystem($source);
86
		static::extract($file_index_map, $source, $target);
87
		$domain     = parse_url($url, PHP_URL_HOST);
88
		$public_key = hash('sha512', random_bytes(1000));
89
		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
		$cdb = "cs\\DB\\$db_engine";
106
		$cdb = new $cdb($db_name, $db_user, $db_password, $db_host, $db_prefix);
107
		if (!is_object($cdb) || !$cdb->connected()) {
108
			throw new RuntimeException("Can't connect to database! Installation aborted.");
109
		}
110
		static::initialize_db_structure($cdb, $source, $db_engine);
111
		static::initialize_system_config($cdb, $source, $site_name, $url, $admin_email, $language, $domain, $timezone, $mode);
112
		static::create_root_administrator($cdb, $admin_email, $admin_password, $public_key);
113
		unset($cdb);
114
	}
115
	/**
116
	 * @param string $source
117
	 * @param string $target
118
	 * @param string $db_engine
119
	 *
120
	 * @throws RuntimeException
121
	 */
122
	protected static function pre_installation_checks ($source, $target, $db_engine) {
123
		if (file_exists("$target/config/main.json")) {
124
			throw new RuntimeException('"config/main.json" file already present! Installation aborted.');
125
		}
126
		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
	}
130
	/**
131
	 * @param string $source
132
	 *
133
	 * @return array[]
134
	 */
135
	protected static function initialize_filesystem ($source) {
136
		$file_index_map = json_decode(file_get_contents("$source/fs_installer.json"), true);
137
		require_once "$source/fs/".$file_index_map['core/thirdparty/upf.php'];
138
		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
		spl_autoload_unregister(spl_autoload_functions()[0]);
141
		/**
142
		 * Special autoloader for installer
143
		 */
144
		spl_autoload_register(
145
			function ($class) use ($file_index_map, $source) {
146
				$prepared_class_name = ltrim($class, '\\');
147
				if (strpos($prepared_class_name, 'cs\\') === 0) {
148
					$prepared_class_name = substr($prepared_class_name, 3);
149
				}
150
				$prepared_class_name = explode('\\', $prepared_class_name);
151
				$namespace           = count($prepared_class_name) > 1 ? implode('/', array_slice($prepared_class_name, 0, -1)) : '';
152
				$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
					strlen($file = @$file_index_map[str_replace('//', '/', "core/classes/$namespace/$class_name.php")]) ||    //Core classes
158
					strlen($file = @$file_index_map[str_replace('//', '/', "core/thirdparty/$namespace/$class_name.php")]) || //Third party classes
159
					strlen($file = @$file_index_map[str_replace('//', '/', "core/traits/$namespace/$class_name.php")]) ||     //Core traits
160
					strlen($file = @$file_index_map[str_replace('//', '/', "core/engines/$namespace/$class_name.php")]) ||    //Core engines
161
					strlen($file = @$file_index_map[str_replace('//', '/', "$namespace/$class_name.php")])                    //Classes in modules
162
				) {
163
					require_once "$source/fs/$file";
164
					return true;
165
				}
166
				return false;
167
			}
168
		);
169
		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
	protected static function extract ($file_index_map, $source, $target) {
179
		/**
180
		 * Extracting of engine's files
181
		 */
182
		foreach ($file_index_map as $file_path => $file_index) {
183
			$dir = dirname("$target/$file_path");
184
			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
			if (!copy("$source/fs/$file_index", "$target/$file_path")) {
188
				throw new RuntimeException("Can't extract system files from the archive, creating file $target/$file_path failed! Installation aborted.");
189
			}
190
		}
191
		file_put_json("$target/core/fs.json", array_keys(file_get_json("$source/fs.json")));
192
		/**
193
		 * Make CLI executable
194
		 */
195
		chmod("$target/cli", 0770);
196
	}
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
	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
		$db_password = str_replace('"', '\\"', $db_password);
226
		$config      = str_replace(
227
			['@domain', '@timezone', '@db_host', '@db_type', '@db_name', '@db_user', '@db_password', '@db_prefix', '@language', '@public_key'],
228
			[$domain, $timezone, $db_host, $db_engine, $db_name, $db_user, $db_password, $db_prefix, $language, $public_key],
229
			self::MAIN_CONFIG_STUB
230
		);
231
		if (!file_put_contents("$target/config/main.json", $config)) {
232
			throw new RuntimeException("Can't write core system configuration! Installation aborted.");
233
		}
234
		chmod("$target/config/main.json", 0600);
235
	}
236
	/**
237
	 * @param DB\_Abstract $cdb
238
	 * @param string       $source
239
	 * @param string       $db_engine
240
	 *
241
	 * @throws RuntimeException
242
	 */
243
	protected static function initialize_db_structure ($cdb, $source, $db_engine) {
244
		$query = array_filter(
245
			explode(';', file_get_contents("$source/DB/$db_engine.sql")),
246
			'trim'
247
		);
248
		if (!$cdb->q($query)) {
249
			throw new RuntimeException("Can't import system tables structure for selected database engine! Installation aborted.");
250
		}
251
	}
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
	protected static function initialize_system_config ($cdb, $source, $site_name, $url, $admin_email, $language, $domain, $timezone, $mode) {
266
		$config     = [
267
			'name'                              => $site_name,
268
			'url'                               => [$url],
269
			'admin_email'                       => $admin_email,
270
			'closed_title'                      => 'Site closed',
271
			'closed_text'                       => '<p>Site closed for maintenance</p>',
272
			'site_mode'                         => 1,
273
			'title_delimiter'                   => ' | ',
274
			'title_reverse'                     => 0,
275
			'cache_compress_js_css'             => 1,
276
			'frontend_load_optimization'        => 1,
277
			'vulcanization'                     => 1,
278
			'put_js_after_body'                 => 1,
279
			'theme'                             => 'CleverStyle',
280
			'language'                          => $language,
281
			'active_languages'                  => [$language],
282
			'multilingual'                      => 0,
283
			'db_balance'                        => 0,
284
			'db_mirror_mode'                    => DB::MIRROR_MODE_MASTER_MASTER,
285
			'cookie_prefix'                     => '',
286
			'cookie_domain'                     => [$domain],
287
			'inserts_limit'                     => 1000,
288
			'key_expire'                        => 60 * 2,
289
			'gravatar_support'                  => 0,
290
			'session_expire'                    => 3600 * 24 * 30,
291
			'update_ratio'                      => 75,
292
			'sign_in_attempts_block_count'      => 0,
293
			'sign_in_attempts_block_time'       => 5,
294
			'timezone'                          => $timezone,
295
			'password_min_length'               => 4,
296
			'password_min_strength'             => 3,
297
			'smtp'                              => 0,
298
			'smtp_host'                         => '',
299
			'smtp_port'                         => '',
300
			'smtp_secure'                       => '',
301
			'smtp_auth'                         => 0,
302
			'smtp_user'                         => '',
303
			'smtp_password'                     => '',
304
			'mail_from'                         => $admin_email,
305
			'mail_from_name'                    => "Administrator of $site_name",
306
			'allow_user_registration'           => 1,
307
			'require_registration_confirmation' => 1,
308
			'auto_sign_in_after_registration'   => 1,
309
			'registration_confirmation_time'    => 1,
310
			'mail_signature'                    => '',
311
			'remember_user_ip'                  => 0,
312
			'simple_admin_mode'                 => $mode,
313
			'default_module'                    => Config::SYSTEM_MODULE
314
		];
315
		$components = [
316
			'modules' => [
317
				'System' => [
318
					'active' => Config\Module_Properties::ENABLED,
319
					'db'     => [
320
						'keys'  => '0',
321
						'users' => '0',
322
						'texts' => '0'
323
					]
324
				]
325
			],
326
			'blocks'  => []
327
		];
328
		foreach (file_get_json("$source/modules.json") as $module) {
329
			$components['modules'][$module] = [
330
				'active'  => Config\Module_Properties::UNINSTALLED,
331
				'db'      => [],
332
				'storage' => []
333
			];
334
		}
335
		$result = $cdb->q(
336
			"INSERT INTO `[prefix]config` (
337
				`domain`, `core`, `db`, `storage`, `components`
338
			) VALUES (
339
				'%s', '%s', '[]', '[]', '%s'
340
			)",
341
			$domain,
342
			_json_encode($config),
343
			_json_encode($components)
344
		);
345
		if (!$result) {
346
			throw new RuntimeException("Can't import system configuration into database! Installation aborted.");
347
		}
348
	}
349
	/**
350
	 * @param DB\_Abstract $cdb
351
	 * @param string       $admin_email
352
	 * @param string       $admin_password
353
	 * @param string       $public_key
354
	 *
355
	 * @throws RuntimeException
356
	 */
357
	protected static function create_root_administrator ($cdb, $admin_email, $admin_password, $public_key) {
358
		$admin_email = strtolower($admin_email);
359
		$admin_login = strstr($admin_email, '@', true);
360
		$result      = $cdb->q(
361
			"INSERT INTO `[prefix]users` (
362
				`login`, `login_hash`, `password_hash`, `email`, `email_hash`, `reg_date`, `reg_ip`, `status`
363
			) VALUES (
364
				'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'
365
			)",
366
			$admin_login,
367
			hash('sha224', $admin_login),
368
			password_hash(hash('sha512', hash('sha512', $admin_password).$public_key), PASSWORD_DEFAULT),
369
			$admin_email,
370
			hash('sha224', $admin_email),
371
			time(),
372
			'127.0.0.1',
373
			User::STATUS_ACTIVE
374
		);
375
		if (!$result) {
376
			throw new RuntimeException("Can't register root administrator user! Installation aborted.");
377
		}
378
	}
379
}
380