Completed
Push — master ( 34fd9d...865579 )
by Nazar
04:15
created

functions.php ➔ install_process()   F

Complexity

Conditions 25
Paths 745

Size

Total Lines 300
Code Lines 180

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 25
eloc 180
nc 745
nop 2
dl 0
loc 300
rs 2.2307

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 CMS
4
 * @subpackage Installer
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
	h;
12
13
function install_form () {
14
	$timezones = get_timezones_list();
15
	return h::{'form[method=post]'}(
16
		h::nav(
17
			h::{'radio[name=mode]'}(
18
				[
19
					'value'   => ['1', '0'],
20
					'in'      => [h::span('Regular user'), h::span('Expert')],
21
					'onclick' =>
22
						"var items = document.getElementsByClassName('expert');"
23
						."for (var i = 0; i < items.length; i++) {"
24
						."items.item(i).style.display = this.value == '0' ? 'table-row' : '';"
25
						."}"
26
				]
27
			)
28
		).
29
		h::table(
30
			h::{'tr td'}(
31
				'Site name:',
32
				h::{'input[name=site_name]'}()
33
			).
34
			h::{'tr.expert td'}(
35
				'Database engine:',
36
				h::{'select[name=db_engine][size=3][selected=MySQLi]'}(
37
					file_get_json(DIR.'/db_engines.json')
38
				)
39
			).
40
			h::{'tr.expert td'}(
41
				'Database host:',
42
				h::{'input[name=db_host][value=localhost]'}(
43
					[
44
						'placeholder' => 'Relative or absolute path to DB for SQLite'
45
					]
46
				)
47
			).
48
			h::{'tr td'}(
49
				'Database name:',
50
				h::{'input[name=db_name]'}()
51
			).
52
			h::{'tr td'}(
53
				'Database user:',
54
				h::{'input[name=db_user]'}()
55
			).
56
			h::{'tr td'}(
57
				'Database user password:',
58
				h::{'input[type=password][name=db_password]'}()
59
			).
60
			h::{'tr.expert td'}(
61
				'Database tables prefix:',
62
				h::{'input[name=db_prefix]'}(
63
					[
64
						'value' => substr(md5(random_bytes(1000)), 0, 5).'_'
65
					]
66
				)
67
			).
68
			h::{'tr.expert td'}(
69
				'Database charset:',
70
				h::{'input[name=db_charset][value=utf8mb4]'}()
71
			).
72
			h::{'tr td'}(
73
				'Timezone:',
74
				h::{'select[name=timezone][size=7][selected=UTC]'}(
75
					[
76
						'in'    => array_keys($timezones),
77
						'value' => array_values($timezones)
78
					]
79
				)
80
			).
81
			h::{'tr td'}(
82
				'Language:',
83
				h::{'select[name=language][size=3][selected=English]'}(
84
					file_get_json(DIR.'/languages.json')
85
				)
86
			).
87
			h::{'tr td'}(
88
				'Email of administrator:',
89
				h::{'input[type=email][name=admin_email]'}()
90
			).
91
			h::{'tr td'}(
92
				'Administrator password:',
93
				h::{'input[type=password][name=admin_password]'}()
94
			)
95
		).
96
		h::{'button.readme'}(
97
			'Readme',
98
			[
99
				'onclick' => "window.open('readme.html', 'readme', 'location=no')"
100
			]
101
		).
102
		h::{'button.license'}(
103
			'License',
104
			[
105
				'onclick' => "window.open('license.txt', 'license', 'location=no')"
106
			]
107
		).
108
		h::{'button[type=submit]'}(
109
			'Install'
110
		)
111
	);
112
}
113
114
/**
115
 * @param array[]    $fs
116
 * @param array|null $argv
117
 *
118
 * @return string
119
 */
120
function install_process ($fs, $argv = null) {
121
	/**
122
	 * Connecting to the DataBase
123
	 */
124
	define('DEBUG', false);
125
	/**
126
	 * DataBase structure import
127
	 */
128
	if (!file_exists(DIR."/install/DB/$_POST[db_engine].sql")) {
129
		return "Can't find system tables structure for selected database engine! Installation aborted.";
130
	}
131
	$Request = Request::instance();
132
	/**
133
	 * General system configuration
134
	 */
135
	if (isset($_POST['site_url'])) {
136
		$url = $_POST['site_url'];
137
	} else {
138
		$Request->init_server($_SERVER);
139
		$url = "$Request->scheme://$Request->host$Request->path";
140
		$url = implode('/', array_slice(explode('/', $url), 0, -2)); //Remove 2 last items
141
	}
142
	preg_match('#//([^/]+)#', $url, $domain);
143
	$domain = explode(':', $domain[1])[0];
144
	$config = [
145
		'name'                              => $_POST['site_name'],
146
		'url'                               => [$url],
147
		'admin_email'                       => $_POST['admin_email'],
148
		'closed_title'                      => 'Site closed',
149
		'closed_text'                       => '<p>Site closed for maintenance</p>',
150
		'site_mode'                         => 1,
151
		'title_delimiter'                   => ' | ',
152
		'title_reverse'                     => 0,
153
		'cache_compress_js_css'             => 1,
154
		'vulcanization'                     => 1,
155
		'put_js_after_body'                 => 1,
156
		'theme'                             => 'CleverStyle',
157
		'language'                          => $_POST['language'],
158
		'active_languages'                  => [$_POST['language']],
159
		'multilingual'                      => 0,
160
		'db_balance'                        => 0,
161
		'db_mirror_mode'                    => \cs\DB::MIRROR_MODE_MASTER_MASTER,
162
		'cookie_prefix'                     => '',
163
		'cookie_domain'                     => [$domain],
164
		'inserts_limit'                     => 1000,
165
		'key_expire'                        => 120,
166
		'gravatar_support'                  => 0,
167
		'session_expire'                    => 2592000,
168
		'update_ratio'                      => 75,
169
		'sign_in_attempts_block_count'      => 0,
170
		'sign_in_attempts_block_time'       => 5,
171
		'timezone'                          => $_POST['timezone'],
172
		'password_min_length'               => 4,
173
		'password_min_strength'             => 3,
174
		'smtp'                              => 0,
175
		'smtp_host'                         => '',
176
		'smtp_port'                         => '',
177
		'smtp_secure'                       => '',
178
		'smtp_auth'                         => 0,
179
		'smtp_user'                         => '',
180
		'smtp_password'                     => '',
181
		'mail_from'                         => $_POST['admin_email'],
182
		'mail_from_name'                    => "Administrator of $_POST[site_name]",
183
		'allow_user_registration'           => 1,
184
		'require_registration_confirmation' => 1,
185
		'auto_sign_in_after_registration'   => 1,
186
		'registration_confirmation_time'    => 1,
187
		'mail_signature'                    => '',
188
		'remember_user_ip'                  => 0,
189
		'simple_admin_mode'                 => !isset($_POST['mode']) || $_POST['mode'] ? 1 : 0,
190
		'default_module'                    => 'System'
191
	];
192
	/**
193
	 * Extracting of engine's files
194
	 */
195
	$extracted = array_filter(
196
		array_map(
197
			function ($index, $file) {
198
				$dir = dirname(ROOT."/$file");
199
				if (
200
					!@mkdir($dir, 0770, true) &&
201
					!is_dir($dir)
202
				) {
203
					return false;
204
				}
205
				/**
206
				 * TODO: copy() + file_exists() is a hack for HHVM, when bug fixed upstream (copying of empty files) this should be simplified
207
				 */
208
				copy(DIR."/fs/$index", ROOT."/$file");
209
				return file_exists(ROOT."/$file");
210
			},
211
			$fs,
212
			array_keys($fs)
213
		)
214
	);
215
	if (
216
		count($extracted) !== count($fs) ||
217
		(
218
			!@mkdir(ROOT.'/storage', 0770) && !is_dir(ROOT.'/storage')
219
		) ||
220
		!file_put_contents(ROOT.'/storage/.htaccess', "Deny from all\nRewriteEngine Off\n<Files *>\n\tSetHandler default-handler\n</Files>")
221
	) {
222
		return "Can't extract system files from the archive! Installation aborted.";
223
	}
224
	/**
225
	 * Basic system configuration
226
	 */
227
	$public_key  = hash('sha512', random_bytes(1000));
228
	$main_config = is_dir(ROOT.'/config') && file_put_contents(
229
			ROOT.'/config/main.json',
230
			str_replace(
231
				[
232
					'@domain',
233
					'@timezone',
234
					'@db_host',
235
					'@db_type',
236
					'@db_name',
237
					'@db_user',
238
					'@db_password',
239
					'@db_prefix',
240
					'@db_charset',
241
					'@language',
242
					'@public_key'
243
				],
244
				[
245
					$config['cookie_domain'][0],
246
					$_POST['timezone'],
247
					$_POST['db_host'],
248
					$_POST['db_engine'],
249
					$_POST['db_name'],
250
					$_POST['db_user'],
251
					str_replace('"', '\\"', $_POST['db_password']),
252
					$_POST['db_prefix'],
253
					$_POST['db_charset'],
254
					$_POST['language'],
255
					$public_key
256
				],
257
				'{
258
//Domain of main mirror
259
	"domain"			: "@domain",
260
//Base timezone
261
	"timezone"			: "@timezone",
262
//Settings of main DB
263
	"db_host"			: "@db_host",
264
	"db_type"			: "@db_type",
265
	"db_name"			: "@db_name",
266
	"db_user"			: "@db_user",
267
	"db_password"		: "@db_password",
268
	"db_prefix"			: "@db_prefix",
269
	"db_charset"		: "@db_charset",
270
//Settings of main Storage
271
	"storage_type"		: "Local",
272
	"storage_url"		: "",
273
	"storage_host"		: "localhost",
274
	"storage_user"		: "",
275
	"storage_password"	: "",
276
//Base language
277
	"language"			: "@language",
278
//Cache engine
279
	"cache_engine"		: "FileSystem",
280
//Settings of Memcached cache engine
281
	"memcache_host"		: "127.0.0.1",
282
	"memcache_port"		: "11211",
283
//Any length
284
	"public_key"		: "@public_key"
285
}'
286
			)
287
		);
288
	extension_loaded('apc') && apc_clear_cache('user');
289
	if (!$main_config) {
290
		return "Can't write base system configuration! Installation aborted.";
291
	}
292
	chmod(ROOT.'/config/main.json', 0600);
293
	/**
294
	 * @var \cs\DB\_Abstract $cdb
295
	 */
296
	$cdb = "cs\\DB\\$_POST[db_engine]";
297
	$cdb = new $cdb(
298
		$_POST['db_name'],
299
		$_POST['db_user'],
300
		$_POST['db_password'],
301
		$_POST['db_host'],
302
		$_POST['db_charset'],
303
		$_POST['db_prefix']
304
	);
305
	if (!is_object($cdb) || !$cdb->connected()) {
306
		return 'Database connection failed! Installation aborted.';
307
	}
308
	if (!$cdb->q(
309
		array_filter(
310
			explode(';', file_get_contents(DIR."/install/DB/$_POST[db_engine].sql")),
311
			'_trim'
312
		)
313
	)
314
	) {
315
		return "Can't import system tables structure for selected database engine! Installation aborted.";
316
	}
317
	/**
318
	 * General configuration import
319
	 */
320
	$modules = [
321
		'System' => [
322
			'active' => Config\Module_Properties::ENABLED,
323
			'db'     => [
324
				'keys'  => '0',
325
				'users' => '0',
326
				'texts' => '0'
327
			]
328
		]
329
	];
330
	if (file_exists(DIR.'/modules.json')) {
331
		foreach (file_get_json(DIR.'/modules.json') as $module) {
332
			$modules[$module] = [
333
				'active'  => Config\Module_Properties::UNINSTALLED,
334
				'db'      => [],
335
				'storage' => []
336
			];
337
		}
338
		unset($module);
339
	}
340
	if (!$cdb->q(
341
		"INSERT INTO `[prefix]config` (
342
			`domain`, `core`, `db`, `storage`, `components`
343
		) VALUES (
344
			'%s', '%s', '[]', '[]', '%s'
345
		)",
346
		$config['cookie_domain'][0],
347
		_json_encode($config),
348
		'{"modules":'._json_encode($modules).',"plugins":[],"blocks":[]}'
349
	)
350
	) {
351
		return "Can't import system configuration into database! Installation aborted.";
352
	}
353
	unset($modules);
354
	/**
355
	 * Administrator registration
356
	 */
357
	$admin_login = strstr($_POST['admin_email'], '@', true);
358
	if (!$cdb->q(
359
		"INSERT INTO `[prefix]users` (
360
			`login`, `login_hash`, `password_hash`, `email`, `email_hash`, `reg_date`, `reg_ip`, `status`
361
		) VALUES (
362
			'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'
363
		)",
364
		$admin_login,
365
		hash('sha224', $admin_login),
366
		password_hash(hash('sha512', hash('sha512', $_POST['admin_password']).$public_key), PASSWORD_DEFAULT),
367
		$_POST['admin_email'],
368
		hash('sha224', $_POST['admin_email']),
369
		time(),
370
		ip2hex($Request->remote_addr),
371
		1
372
	)
373
	) {
374
		return "Can't register administrator user! Installation aborted.";
375
	}
376
	/**
377
	 * Disconnecting from the DataBase
378
	 */
379
	$cdb->__destruct();
380
	$warning   = false;
381
	// Removing of installer file
382
	$cli       = PHP_SAPI == 'cli';
383
	$installer = $cli ? ROOT."/$argv[0]" : ROOT.'/'.pathinfo(DIR, PATHINFO_BASENAME);
384
	if (!is_writable($installer) || !unlink($installer)) {
385
		$warning = "Please, remove installer file $installer for security!\n";
386
	}
387
	if ($cli) {
388
		return "Congratulations! CleverStyle CMS has been installed successfully!\n$warning\nLogin: $admin_login\nPassword: $_POST[admin_password]";
389
	} else {
390
		return
391
			h::h3(
392
				'Congratulations! CleverStyle CMS has been installed successfully!'
393
			).
394
			h::{'table tr| td'}(
395
				[
396
					'Your sign in information:',
397
					[
398
						'colspan' => 2
399
					]
400
				],
401
				[
402
					'Login:',
403
					$admin_login
404
				],
405
				[
406
					'Password:',
407
					$_POST['admin_password']
408
				]
409
			).
410
			h::p(
411
				$warning,
412
				[
413
					'style' => 'color: red;'
414
				]
415
			).
416
			h::button(
417
				'Go to website',
418
				[
419
					'onclick' => "location.href = '/';"
420
				]
421
			);
422
	}
423
}
424