Completed
Push — master ( 52a157...dbf29b )
by Nazar
04:07
created

Index::should_block_be_rendered()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 8.8571
cc 5
eloc 8
nc 6
nop 1
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
use
10
	cs\Index\Router;
11
12
/**
13
 * Provides next events:
14
 *  System/Index/block_render
15
 *  [
16
 *      'index'           => $index,        //Block index
17
 *      'blocks_array'    => &$blocks_array //Reference to array in form ['top' => '', 'left' => '', 'right' => '', 'bottom' => '']
18
 *  ]
19
 *
20
 *  System/Index/construct
21
 *
22
 *  System/Index/load/before
23
 *
24
 *  System/Index/load/after
25
 *
26
 * @property string[] $controller_path Path that will be used by controller to render page
27
 */
28
class Index {
29
	use
30
		Singleton,
31
		Router;
32
33
	protected $request_method;
34
	protected $working_directory = '';
35
	protected $called_once       = false;
36
	/**
37
	 * Reference to Request::instance()->route_path
38
	 *
39
	 * @var string[]
40
	 */
41
	protected $path;
42
	/**
43
	 * Reference to Request::instance()->route_ids
44
	 *
45
	 * @var int[]
46
	 */
47
	protected $ids;
48
	/**
49
	 * Path that will be used by controller to render page
50
	 *
51
	 * @var string[]
52
	 */
53
	protected $controller_path = ['index'];
54
	/**
55
	 * Detecting module folder including of admin/api request type, including prepare file, including of plugins
56
	 *
57
	 * @throws ExitException
58
	 */
59
	function construct () {
60
		$Config     = Config::instance();
61
		$Request    = Request::instance();
62
		$this->path = &$Request->route_path;
63
		$this->ids  = &$Request->route_ids;
64
		/**
65
		 * If site is closed
66
		 */
67
		if (!$Config->core['site_mode']) {
68
			if (!$this->allow_closed_site_request($Request)) {
69
				throw new ExitException(
70
					[
1 ignored issue
show
Documentation introduced by
array(get_core_ml_text('...ml_text('closed_text')) is of type array<integer,false|stri...g","1":"false|string"}>, but the function expects a string|integer|array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
71
						get_core_ml_text('closed_title'),
72
						get_core_ml_text('closed_text')
73
					],
74
					503
75
				);
76
			}
77
			/**
78
			 * Warning about closed site for administrator
79
			 */
80
			Page::instance()->warning(get_core_ml_text('closed_title'));
81
		}
82
		$this->working_directory = MODULES."/$Request->current_module";
83
		if ($Request->admin_path) {
84
			$this->working_directory .= '/admin';
85
		} elseif ($Request->api_path) {
86
			$this->working_directory .= '/api';
87
		}
88
		if (!is_dir($this->working_directory)) {
89
			throw new ExitException(404);
90
		}
91
		if (!$this->check_permission('index')) {
92
			throw new ExitException(403);
93
		}
94
		Event::instance()->fire('System/Index/construct');
95
		/**
96
		 * Plugins processing
97
		 */
98
		foreach ($Config->components['plugins'] as $plugin) {
99
			_include(PLUGINS."/$plugin/index.php", false, false);
100
		}
101
		_include("$this->working_directory/prepare.php", false, false);
102
		$this->request_method = strtolower($Request->method);
103
		if (!preg_match('/^[a-z_]+$/', $this->request_method)) {
104
			throw new ExitException(400);
105
		}
106
	}
107
	/**
108
	 * Check if visitor is allowed to make current request to closed site
109
	 *
110
	 * @param Request $Request
111
	 *
112
	 * @return bool
113
	 */
114
	protected function allow_closed_site_request ($Request) {
115
		return
116
			User::instance()->admin() ||
117
			(
118
				$Request->api_path &&
119
				$Request->current_module == 'System' &&
120
				$Request->route === ['user', 'sign_in']
121
			);
122
	}
123
	/**
124
	 * Check whether user allowed to access to specified label
125
	 *
126
	 * @param string $label
127
	 *
128
	 * @return bool
129
	 */
130
	protected function check_permission ($label) {
131
		$Request          = Request::instance();
132
		$permission_group = $Request->current_module;
133
		if ($Request->admin_path) {
134
			$permission_group = "admin/$permission_group";
135
		} elseif ($Request->api_path) {
136
			$permission_group = "api/$permission_group";
137
		}
138
		return User::instance()->get_permission($permission_group, $label);
139
	}
140
	/**
141
	 * Page generation, blocks processing, adding of form with save/apply/cancel/reset and/or custom users buttons
142
	 *
143
	 * @throws ExitException
144
	 */
145
	protected function render_page () {
146
		$this->render_title();
147
		$this->render_content();
148
		if (!Request::instance()->api_path) {
149
			$this->render_blocks();
150
		}
151
	}
152
	/**
153
	 * Render page title
154
	 */
155
	protected function render_title () {
156
		$Page    = Page::instance();
157
		$Request = Request::instance();
158
		/**
159
		 * Add generic Home or Module name title
160
		 */
161
		if (!$Request->api_path) {
162
			$L = Language::instance();
163
			if ($Request->admin_path) {
164
				$Page->title($L->system_admin_administration);
165
			}
166
			$Page->title(
167
				$L->{$Request->home_page ? 'system_home' : $Request->current_module}
168
			);
169
		}
170
	}
171
	/**
172
	 * Render page content (without blocks, just module content)
173
	 *
174
	 * @throws ExitException
175
	 */
176
	protected function render_content () {
177
		$Page = Page::instance();
178
		/**
179
		 * If module consists of index.html only
180
		 */
181
		if (file_exists("$this->working_directory/index.html")) {
182
			ob_start();
183
			_include("$this->working_directory/index.html", false, false);
184
			$Page->content(ob_get_clean());
185
			return;
186
		}
187
		$this->execute_router();
188
	}
189
	/**
190
	 * Blocks rendering
191
	 */
192
	protected function render_blocks () {
193
		$blocks = Config::instance()->components['blocks'];
194
		/**
195
		 * It is frequent that there is no blocks - so, no need to to anything here
196
		 */
197
		if (!$blocks) {
198
			return;
199
		}
200
		$Page         = Page::instance();
201
		$blocks_array = [
202
			'top'    => '',
203
			'left'   => '',
204
			'right'  => '',
205
			'bottom' => ''
206
		];
207
		foreach ($blocks as $block) {
208
			/**
209
			 * If there is no need to show block or it was rendered by even handler - skip further processing
210
			 */
211
			if (
212
				!$this->should_block_be_rendered($block) ||
213
				!Event::instance()->fire(
214
					'System/Index/block_render',
215
					[
216
						'index'        => $block['index'],
217
						'blocks_array' => &$blocks_array
218
					]
219
				)
220
			) {
221
				/**
222
				 * Block was rendered by event handler
223
				 */
224
				continue;
225
			}
226
			$block['title'] = $this->ml_process($block['title']);
227
			switch ($block['type']) {
228
				default:
229
					$block['content'] = ob_wrapper(
230
						function () use ($block) {
231
							include BLOCKS."/block.$block[type].php";
232
						}
233
					);
234
					break;
235
				case 'html':
236
				case 'raw_html':
237
					$block['content'] = $this->ml_process($block['content']);
238
					break;
239
			}
240
			/**
241
			 * Template file will have access to `$block` variable, so it can use that
242
			 */
243
			$content = str_replace(
244
				[
245
					'<!--id-->',
246
					'<!--title-->',
247
					'<!--content-->'
248
				],
249
				[
250
					$block['index'],
251
					$block['title'],
252
					$block['content']
253
				],
254
				ob_wrapper(
255
					function () use ($block) {
256
						$template = file_exists(TEMPLATES."/blocks/block.$block[template]") ? $block['template'] : 'default.html';
257
						include TEMPLATES."/blocks/block.$template";
258
					}
259
				)
260
			);
261
			if ($block['position'] == 'floating') {
262
				$Page->replace(
263
					"<!--block#$block[index]-->",
264
					$content
265
				);
266
			} else {
267
				$blocks_array[$block['position']] .= $content;
268
			}
269
		}
270
		$Page->Top .= $blocks_array['top'];
271
		$Page->Left .= $blocks_array['left'];
272
		$Page->Right .= $blocks_array['right'];
273
		$Page->Bottom .= $blocks_array['bottom'];
274
	}
275
	/**
276
	 * Check whether to render block or not based on its properties (active state, when start to show, when it expires and permissions)
277
	 *
278
	 * @param array $block
279
	 *
280
	 * @return bool
281
	 */
282
	protected function should_block_be_rendered ($block) {
283
		return
284
			$block['active'] &&
285
			$block['start'] <= time() &&
286
			(
287
				!$block['expire'] ||
288
				$block['expire'] >= time()
289
			) &&
290
			User::instance()->get_permission('Block', $block['index']);
291
	}
292
	/**
293
	 * @param string $text
294
	 *
295
	 * @return string
296
	 */
297
	protected function ml_process ($text) {
298
		return Text::instance()->process(Config::instance()->module('System')->db('texts'), $text, true);
299
	}
300
	/**
301
	 * Getter for `controller_path` property (no other properties supported currently)
302
	 *
303
	 * @param string $property
304
	 *
305
	 * @return false|string[]
306
	 */
307
	function __get ($property) {
308
		switch ($property) {
309
			case 'controller_path';
310
				return $this->controller_path;
311
		}
312
		return false;
313
	}
314
	/**
315
	 * Executes plugins processing, blocks and module page generation
316
	 *
317
	 * @throws ExitException
318
	 */
319
	function __finish () {
320
		/**
321
		 * Protection from double calling
322
		 */
323
		if ($this->called_once) {
324
			return;
325
		}
326
		$this->called_once = true;
327
		Event::instance()->fire('System/Index/load/before');
328
		$this->render_page();
329
		Event::instance()->fire('System/Index/load/after');
330
	}
331
}
332