Completed
Push — master ( ac170c...424862 )
by Nazar
04:04
created

App::render_blocks()   C

Complexity

Conditions 10
Paths 9

Size

Total Lines 90
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 90
rs 5.1578
cc 10
eloc 55
nc 9
nop 0

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