Completed
Push — master ( 6a99e5...a4d78b )
by Nazar
04:23
created

Installer::extract()   C

Complexity

Conditions 7
Paths 2

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 17
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 31
rs 6.7272
1
<?php
2
/**
3
 * @package    CleverStyle CMS
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
	Exception;
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
	"db_charset"		: "@db_charset",
29
//Settings of main Storage
30
	"storage_type"		: "Local",
31
	"storage_url"		: "",
32
	"storage_host"		: "localhost",
33
	"storage_user"		: "",
34
	"storage_password"	: "",
35
//Base language
36
	"language"			: "@language",
37
//Cache engine
38
	"cache_engine"		: "FileSystem",
39
//Settings of Memcached cache engine
40
	"memcache_host"		: "127.0.0.1",
41
	"memcache_port"		: "11211",
42
//Any length
43
	"public_key"		: "@public_key"
44
}
45
46
CONFIG;
47
	/**
48
	 * @param string $source
49
	 * @param string $target
50
	 * @param string $db_engine
51
	 *
52
	 * @throws Exception
53
	 */
54
	static function install ($source, $target, $db_engine) {
55
		static::pre_installation_checks($source, $target, $db_engine);
56
		// Needed to be defined before connecting to the database
57
		defined('DEBUG') || define('DEBUG', false);
58
		$file_index_map = static::initialize_filesystem($source);
59
		static::extract($file_index_map, $source, $target);
60
	}
61
	/**
62
	 * @param string $source
63
	 * @param string $target
64
	 * @param string $db_engine
65
	 *
66
	 * @throws Exception
67
	 */
68
	protected static function pre_installation_checks ($source, $target, $db_engine) {
69
		if (file_exists("$target/config/main.json")) {
70
			throw new Exception('"config/main.json" file already present! Installation aborted.');
71
		}
72
		if (!file_exists("$source/install/DB/$db_engine.sql")) {
73
			throw new Exception("Can't find system tables structure for selected database engine! Installation aborted.");
74
		}
75
	}
76
	/**
77
	 * @param string $source
78
	 *
79
	 * @return array[]
80
	 */
81
	protected static function initialize_filesystem ($source) {
82
		$file_index_map = json_decode(file_get_contents("$source/fs.json"), true);
83
		/**
84
		 * Special autoloader for installer
85
		 */
86
		spl_autoload_register(
87
			function ($class) use ($file_index_map, $source) {
88
				$prepared_class_name = ltrim($class, '\\');
89
				if (strpos($prepared_class_name, 'cs\\') === 0) {
90
					$prepared_class_name = substr($prepared_class_name, 3);
91
				}
92
				$prepared_class_name = explode('\\', $prepared_class_name);
93
				$namespace           = count($prepared_class_name) > 1 ? implode('/', array_slice($prepared_class_name, 0, -1)) : '';
94
				$class_name          = array_pop($prepared_class_name);
95
				/**
96
				 * Try to load classes from different places. If not found in one place - try in another.
97
				 */
98
				if (
99
					strlen($file = @$file_index_map[str_replace('//', '/', "core/classes/$namespace/$class_name.php")]) ||    //Core classes
100
					strlen($file = @$file_index_map[str_replace('//', '/', "core/thirdparty/$namespace/$class_name.php")]) || //Third party classes
101
					strlen($file = @$file_index_map[str_replace('//', '/', "core/traits/$namespace/$class_name.php")]) ||     //Core traits
102
					strlen($file = @$file_index_map[str_replace('//', '/', "core/engines/$namespace/$class_name.php")]) ||    //Core engines
103
					strlen($file = @$file_index_map[str_replace('//', '/', "components/$namespace/$class_name.php")])         //Classes in modules and plugins
104
				) {
105
					/** @noinspection UntrustedInclusionInspection */
106
					require_once "$source/fs/$file";
107
					return true;
108
				}
109
				return false;
110
			},
111
			true,
112
			true
113
		);
114
		require_once "$source/fs/".$file_index_map['core/thirdparty/upf.php'];
115
		require_once "$source/fs/".$file_index_map['core/functions.php'];
116
		// Remove default autoloader, since we have special autoloader suitable for operating inside installer where default will fail hard
117
		spl_autoload_unregister(spl_autoload_functions()[0]);
118
		return $file_index_map;
119
	}
120
	/**
121
	 * @param array[] $file_index_map
122
	 * @param string  $source
123
	 * @param string  $target
124
	 *
125
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
126
	 *
127
	 * @throws Exception
128
	 */
129
	protected static function extract ($file_index_map, $source, $target) {
130
		/**
131
		 * Extracting of engine's files
132
		 */
133
		$extracted = array_filter(
134
			array_map(
135
				function ($index, $file) use ($source, $target) {
136
					$dir = dirname("$target/$file");
137
					if (!@mkdir($dir, 0770, true) && !is_dir($dir)) {
138
						return false;
139
					}
140
					/**
141
					 * TODO: copy() + file_exists() is a hack for HHVM, when bug fixed upstream (copying of empty files) this should be simplified
142
					 */
143
					copy("$source/fs/$index", "$target/$file");
144
					return file_exists("$target/$file");
145
				},
146
				$file_index_map,
147
				array_keys($file_index_map)
148
			)
149
		);
150
		if (
151
			count($extracted) !== count($file_index_map) ||
152
			(
153
				!@mkdir("$target/storage", 0770) && !is_dir("$target/storage")
154
			) ||
155
			!file_put_contents("$target/storage/.htaccess", "Deny from all\nRewriteEngine Off\n<Files *>\n\tSetHandler default-handler\n</Files>")
156
		) {
157
			throw new Exception("Can't extract system files from the archive! Installation aborted.");
158
		}
159
	}
160
}
161