Completed
Push — master ( a4ebee...ff9168 )
by Nazar
07:28
created

Config::core_url()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4285
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * @package   CleverStyle CMS
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
class Config {
17
	use
18
		Singleton;
19
	const SYSTEM_MODULE = 'System';
20
	const SYSTEM_THEME  = 'CleverStyle';
21
	/**
22
	 * Most of general configuration properties
23
	 *
24
	 * @var mixed[]
25
	 */
26
	public $core = [];
27
	/**
28
	 * Configuration of databases, except the main database, parameters of which are stored in configuration file
29
	 *
30
	 * @var mixed[]
31
	 */
32
	public $db = [];
33
	/**
34
	 * Configuration of storages, except the main storage, parameters of which are stored in configuration file
35
	 *
36
	 * @var mixed[]
37
	 */
38
	public $storage = [];
39
	/**
40
	 * Internal structure of components parameters
41
	 *
42
	 * @var mixed[]
43
	 */
44
	public $components = [];
45
	/**
46
	 * Array of all domains, which allowed to access the site
47
	 *
48
	 * Contains keys:
49
	 * * count - Total count
50
	 * * http - Insecure (http) domains
51
	 * * https - Secure (https) domains
52
	 *
53
	 * @var array
54
	 */
55
	public $mirrors = [
56
		'count' => 0,
57
		'http'  => [],
58
		'https' => []
59
	];
60
	/**
61
	 * Loading of configuration, initialization of $Config, $Cache, $L and Page objects, Routing processing
62
	 *
63
	 * @throws ExitException
64
	 */
65
	protected function construct () {
66
		Event::instance()->fire('System/Config/init/before');
0 ignored issues
show
Bug introduced by
It seems like fire() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
67
		/**
68
		 * Reading settings from cache and defining missing data
69
		 */
70
		$config = Cache::instance()->config;
71
		/**
72
		 * Cache reloading, if necessary
73
		 */
74
		if (!is_array($config)) {
75
			$this->load_config_from_db();
76
		} else {
77
			foreach ($config as $part => $value) {
78
				$this->$part = $value;
79
			}
80
			unset($part, $value);
81
		}
82
		date_default_timezone_set($this->core['timezone']);
83
		$this->fill_mirrors();
84
		Event::instance()->fire('System/Config/init/after');
0 ignored issues
show
Bug introduced by
It seems like fire() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
85
		if (!file_exists(MODULES.'/'.$this->core['default_module'])) {
86
			$this->core['default_module'] = self::SYSTEM_MODULE;
87
			$this->save();
88
		}
89
	}
90
	/**
91
	 * Is used to fill `$this->mirrors` using current configuration
92
	 */
93
	protected function fill_mirrors () {
94
		foreach ($this->core['url'] as $i => $address) {
95
			list($protocol, $urls) = explode('://', $address, 2);
96
			$urls                       = explode(';', $urls);
97
			$this->mirrors[$protocol][] = $urls[0];
98
		}
99
		$this->mirrors['count'] = count($this->mirrors['http']) + count($this->mirrors['https']);
100
	}
101
	/**
102
	 * Reloading of settings cache
103
	 *
104
	 * @return bool
105
	 *
106
	 * @throws ExitException
107
	 */
108
	protected function load_config_from_db () {
109
		$result = DB::instance()->qf(
0 ignored issues
show
Bug introduced by
It seems like qf() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
110
			[
111
				"SELECT
112
					`core`,
113
					`db`,
114
					`storage`,
115
					`components`
116
				FROM `[prefix]config`
117
				WHERE `domain` = '%s'
118
				LIMIT 1",
119
				DOMAIN
120
			]
121
		);
122
		if (is_array($result)) {
123
			foreach ($result as $part => $value) {
124
				$this->$part = _json_decode($value);
125
			}
126
			unset($part, $value);
127
		} else {
128
			return false;
129
		}
130
		$this->apply_internal(false);
131
		return true;
132
	}
133
	/**
134
	 * Applying settings without saving changes into db
135
	 *
136
	 * @return bool
137
	 *
138
	 * @throws ExitException
139
	 */
140
	function apply () {
141
		return $this->apply_internal();
142
	}
143
	/**
144
	 * Applying settings without saving changes into db
145
	 *
146
	 * @param bool $cache_not_saved_mark
147
	 *
148
	 * @return bool
149
	 *
150
	 * @throws ExitException
151
	 */
152
	protected function apply_internal ($cache_not_saved_mark = true) {
153
		if ($cache_not_saved_mark) {
154
			$this->core['cache_not_saved'] = true;
155
		} else {
156
			unset($this->core['cache_not_saved']);
157
		}
158
		$Cache = Cache::instance();
159
		if (!$Cache->set(
0 ignored issues
show
Bug introduced by
It seems like set() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
160
			'config',
161
			[
162
				'core'       => $this->core,
163
				'db'         => $this->db,
164
				'storage'    => $this->storage,
165
				'components' => $this->components
166
			]
167
		)
168
		) {
169
			return false;
170
		}
171
		unset($Cache->{'languages'});
172
		Event::instance()->fire('System/Config/changed');
0 ignored issues
show
Bug introduced by
It seems like fire() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
173
		return true;
174
	}
175
	/**
176
	 * Saving settings
177
	 *
178
	 * @return bool
179
	 *
180
	 * @throws ExitException
181
	 */
182
	function save () {
183
		if ($this->cancel_available()) {
184
			unset($this->core['cache_not_saved']);
185
		}
186
		$core_settings_keys = file_get_json(MODULES.'/System/core_settings_keys.json');
187
		foreach ($this->core as $key => $value) {
188
			if (!in_array($key, $core_settings_keys)) {
189
				unset($this->core[$key]);
190
			}
191
		}
192
		if (DB::instance()->db_prime(0)->q(
0 ignored issues
show
Bug introduced by
It seems like db_prime() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
193
			"UPDATE `[prefix]config`
194
			SET
195
				`core`			= '%s',
196
				`db`			= '%s',
197
				`storage`		= '%s',
198
				`components`	= '%s'
199
			WHERE `domain` = '%s'
200
			LIMIT 1",
201
			_json_encode($this->core),
202
			_json_encode($this->db),
203
			_json_encode($this->storage),
204
			_json_encode($this->components),
205
			DOMAIN
206
		)
207
		) {
208
			$this->apply_internal(false);
209
			return true;
210
		}
211
		return false;
212
	}
213
	/**
214
	 * Whether configuration was applied (not saved) and can be canceled
215
	 *
216
	 * @return bool
217
	 */
218
	function cancel_available () {
219
		return isset($this->core['cache_not_saved']);
220
	}
221
	/**
222
	 * Canceling of applied settings
223
	 *
224
	 * @return bool
225
	 *
226
	 * @throws ExitException
227
	 */
228
	function cancel () {
229
		return $this->load_config_from_db() && $this->apply_internal(false);
230
	}
231
	/**
232
	 * Get base url of current mirror including language suffix
233
	 *
234
	 * @return string
235
	 */
236
	function base_url () {
237
		if (Route::instance()->mirror_index === -1) {
238
			return '';
239
		}
240
		/**
241
		 * @var _SERVER $_SERVER
242
		 */
243
		$base_url = "$_SERVER->protocol://$_SERVER->host";
244
		$L        = Language::instance();
245
		if ($this->core['multilingual']) {
246
			$base_url .= "/$L->clang";
247
		}
248
		return $base_url;
249
	}
250
	/**
251
	 * Get base url of main domain
252
	 *
253
	 * @return string
254
	 */
255
	function core_url () {
256
		/**
257
		 * @var _SERVER $_SERVER
258
		 */
259
		return "$_SERVER->protocol://$_SERVER->host";
260
	}
261
	/**
262
	 * Get object for getting db and storage configuration of module
263
	 *
264
	 * @param string $module_name
265
	 *
266
	 * @return Config\Module_Properties
267
	 */
268
	function module ($module_name) {
269
		if (!isset($this->components['modules'][$module_name])) {
270
			return False_class::instance();
271
		}
272
		return new Config\Module_Properties($this->components['modules'][$module_name], $module_name);
273
	}
274
}
275