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

Config::load_configuration()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 12
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 17
ccs 0
cts 13
cp 0
crap 12
rs 9.4285
1
<?php
2
/**
3
 * @package   CleverStyle Framework
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2011-2016, Nazar Mokrynskyi
6
 * @license   MIT License, see license.txt
7
 */
8
namespace cs;
9
10
/**
11
 * Provides next events:
12
 *  System/Config/init/before
13
 *
14
 *  System/Config/init/after
15
 *
16
 *  System/Config/changed
17
 *
18
 * @method static $this instance($check = false)
19
 */
20
class Config {
21
	use
22
		CRUD,
23
		Singleton;
24
	const SYSTEM_MODULE = 'System';
25
	const SYSTEM_THEME  = 'CleverStyle';
26
	/**
27
	 * Most of general configuration properties
28
	 *
29
	 * @var mixed[]
30
	 */
31
	public $core = [];
32
	/**
33
	 * Configuration of databases, except the main database, parameters of which are stored in configuration file
34
	 *
35
	 * @var mixed[]
36
	 */
37
	public $db = [];
38
	/**
39
	 * Configuration of storages, except the main storage, parameters of which are stored in configuration file
40
	 *
41
	 * @var mixed[]
42
	 */
43
	public $storage = [];
44
	/**
45
	 * Internal structure of components parameters
46
	 *
47
	 * @var mixed[]
48
	 */
49
	public $components = [];
50
	/**
51
	 * Array of all domains, which allowed to access the site
52
	 *
53
	 * Contains keys:
54
	 * * count - Total count
55
	 * * http - Insecure (http) domains
56
	 * * https - Secure (https) domains
57
	 *
58
	 * @var array
59
	 */
60
	public    $mirrors;
61
	protected $data_model = [
62
		'domain'     => 'text',
63
		'core'       => 'json',
64
		'db'         => 'json',
65
		'storage'    => 'json',
66
		'components' => 'json'
67
	];
68
	protected $table      = '[prefix]config';
69
	protected function cdb () {
70
		return 0;
71
	}
72
	/**
73
	 * Loading of configuration, initialization of $Config, $Cache, $L and Page objects, Routing processing
74
	 *
75
	 * @throws ExitException
76
	 */
77
	protected function construct () {
78
		Event::instance()->fire('System/Config/init/before');
79
		$this->load_configuration();
80
		date_default_timezone_set($this->core['timezone']);
81
		$this->fill_mirrors();
82
		Event::instance()->fire('System/Config/init/after');
83
		if (!file_exists(MODULES.'/'.$this->core['default_module'])) {
84
			$this->core['default_module'] = self::SYSTEM_MODULE;
85
			$this->save();
86
		}
87
	}
88
	/**
89
	 * Is used to fill `$this->mirrors` using current configuration
90
	 */
91
	protected function fill_mirrors () {
92
		$this->mirrors = [
93
			'count' => 0,
94
			'http'  => [],
95
			'https' => []
96
		];
97
		foreach ($this->core['url'] as $i => $address) {
98
			list($protocol, $urls) = explode('://', $address, 2);
99
			$urls                       = explode(';', $urls);
100
			$this->mirrors[$protocol][] = $urls[0];
101
		}
102
		$this->mirrors['count'] = count($this->mirrors['http']) + count($this->mirrors['https']);
103
	}
104
	/**
105
	 * Reloading of settings cache
106
	 *
107
	 * @throws ExitException
108
	 */
109
	protected function load_configuration () {
110
		$config = Cache::instance()->get(
111
			'config',
112
			function () {
113
				return $this->read(Core::instance()->domain);
114
			}
115
		);
116
		if (!$config) {
117
			throw new ExitException('Failed to load system configuration', 500);
118
		}
119
		foreach ($config as $part => $value) {
120
			$this->$part = $value;
121
		}
122
		$this->core += file_get_json(MODULES.'/System/core_settings_defaults.json');
123
		date_default_timezone_set($this->core['timezone']);
124
		$this->fill_mirrors();
125
	}
126
	/**
127
	 * Applying settings without saving changes into db
128
	 *
129
	 * @return bool
130
	 *
131
	 * @throws ExitException
132
	 */
133
	function apply () {
134
		return $this->apply_internal();
135
	}
136
	/**
137
	 * Applying settings without saving changes into db
138
	 *
139
	 * @param bool $cache_not_saved_mark
140
	 *
141
	 * @return bool
142
	 *
143
	 * @throws ExitException
144
	 */
145
	protected function apply_internal ($cache_not_saved_mark = true) {
146
		if ($cache_not_saved_mark) {
147
			$this->core['cache_not_saved'] = true;
148
		} else {
149
			unset($this->core['cache_not_saved']);
150
		}
151
		$Cache = Cache::instance();
152
		if (!$Cache->set(
153
			'config',
154
			[
155
				'core'       => $this->core,
156
				'db'         => $this->db,
157
				'storage'    => $this->storage,
158
				'components' => $this->components
159
			]
160
		)
161
		) {
162
			return false;
163
		}
164
		$Cache->del('languages');
165
		date_default_timezone_set($this->core['timezone']);
166
		$this->fill_mirrors();
167
		Event::instance()->fire('System/Config/changed');
168
		return true;
169
	}
170
	/**
171
	 * Saving settings
172
	 *
173
	 * @return bool
174
	 *
175
	 * @throws ExitException
176
	 */
177
	function save () {
178
		if ($this->cancel_available()) {
179
			unset($this->core['cache_not_saved']);
180
		}
181
		$core_settings_defaults = file_get_json(MODULES.'/System/core_settings_defaults.json');
182
		$this->core += $core_settings_defaults;
183
		foreach ($this->core as $key => $value) {
184
			if (!isset($core_settings_defaults[$key])) {
185
				unset($this->core[$key]);
186
			}
187
		}
188
		if (!$this->update(Core::instance()->domain, $this->core, $this->db, $this->storage, $this->components)) {
189
			return false;
190
		}
191
		return $this->apply_internal(false);
192
	}
193
	/**
194
	 * Whether configuration was applied (not saved) and can be canceled
195
	 *
196
	 * @return bool
197
	 */
198
	function cancel_available () {
199
		return isset($this->core['cache_not_saved']);
200
	}
201
	/**
202
	 * Canceling of applied settings
203
	 *
204
	 * @throws ExitException
205
	 */
206
	function cancel () {
207
		Cache::instance()->del('config');
208
		$this->load_configuration();
209
	}
210
	/**
211
	 * Get base url of current mirror including language suffix
212
	 *
213
	 * @return string
214
	 */
215
	function base_url () {
216
		if (Request::instance()->mirror_index === -1) {
217
			return '';
218
		}
219
		$base_url = $this->core_url();
220
		if ($this->core['multilingual']) {
221
			$L = Language::instance();
222
			$base_url .= "/$L->clang";
223
		}
224
		return $base_url;
225
	}
226
	/**
227
	 * Get base url of main domain
228
	 *
229
	 * @return string
230
	 */
231
	function core_url () {
232
		$Request = Request::instance();
233
		return "$Request->scheme://$Request->host";
234
	}
235
	/**
236
	 * Get object for getting db and storage configuration of module
237
	 *
238
	 * @param string $module_name
239
	 *
240
	 * @return Config\Module_Properties
241
	 */
242
	function module ($module_name) {
243
		if (!isset($this->components['modules'][$module_name])) {
244
			return False_class::instance();
245
		}
246
		return new Config\Module_Properties($this->components['modules'][$module_name], $module_name);
247
	}
248
}
249