Completed
Push — master ( 265d0d...5b91fe )
by Nazar
07:12
created

App   B

Complexity

Total Complexity 39

Size/Duplication

Total Lines 233
Duplicated Lines 0 %

Test Coverage

Coverage 98.08%

Importance

Changes 0
Metric Value
dl 0
loc 233
ccs 102
cts 104
cp 0.9808
rs 8.2857
c 0
b 0
f 0
wmc 39

11 Methods

Rating   Name   Duplication   Size   Complexity  
A execute() 0 15 3
A __get() 0 5 2
A init() 0 2 1
A check_permission() 0 11 4
B should_block_be_rendered() 0 9 5
A handle_closed_site() 0 20 3
B allow_closed_site_request() 0 8 5
A render_title() 0 10 3
A ml_process() 0 2 1
A render() 0 10 4
C render_blocks() 0 63 8
1
<?php
2
/**
3
 * @package   CleverStyle Framework
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2011-2017, 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/render/before
21
 *
22
 *  System/App/execute_router/before
23
 *
24
 *  System/App/execute_router/after
25
 *
26
 *  System/App/render/after
27
 *
28
 * @property string[] $controller_path Path that will be used by controller to render page
29
 *
30
 * @method static $this instance($check = false)
31
 */
32
class App {
33
	use
34
		Singleton,
35
		Router;
36
	const INIT_STATE_METHOD = 'init';
37 45
	protected function init () {
38 45
		$this->init_router();
39 45
	}
40
	/**
41
	 * Executes blocks and module page generation
42
	 *
43
	 * @throws ExitException
44
	 */
45 42
	public function execute () {
46 42
		$Config  = Config::instance();
47 42
		$Request = Request::instance();
48 42
		if (!preg_match('/^[0-9a-z_]+$/i', $Request->method)) {
49 3
			throw new ExitException(400);
50
		}
51 42
		$this->handle_closed_site($Config, $Request);
52 39
		if (!$this->check_permission($Request, 'index')) {
53 6
			throw new ExitException(403);
54
		}
55 36
		Event::instance()->fire('System/App/render/before');
56 36
		$Page = Page::instance();
57 36
		$this->render($Request, $Page);
58 36
		Event::instance()->fire('System/App/render/after');
59 36
		$Page->render();
60 36
	}
61
	/**
62
	 * @param Config  $Config
63
	 * @param Request $Request
64
	 *
65
	 * @throws ExitException
66
	 */
67 42
	protected function handle_closed_site ($Config, $Request) {
68 42
		if ($Config->core['site_mode']) {
69 39
			return;
70
		}
71
		/**
72
		 * If site is closed
73
		 */
74 9
		if (!$this->allow_closed_site_request($Request)) {
75 6
			throw new ExitException(
76
				[
77 6
					$Config->core['closed_title'],
78 6
					$Config->core['closed_text']
79
				],
80 6
				503
81
			);
82
		}
83
		/**
84
		 * Warning about closed site for administrator
85
		 */
86 6
		Page::instance()->warning($Config->core['closed_title']);
87 6
	}
88
	/**
89
	 * Check if visitor is allowed to make current request to closed site
90
	 *
91
	 * @param Request $Request
92
	 *
93
	 * @return bool
94
	 */
95 9
	protected function allow_closed_site_request ($Request) {
96
		return
97 9
			User::instance()->admin() ||
98
			(
99 9
				$Request->api_path &&
100 9
				$Request->current_module == 'System' &&
101 9
				$Request->route == ['profile'] &&
102 9
				$Request->method == 'SIGN_IN'
103
			);
104
	}
105
	/**
106
	 * Check whether user allowed to access to specified label
107
	 *
108
	 * @param Request $Request
109
	 * @param string  $label
110
	 *
111
	 * @return bool
112
	 */
113 42
	protected function check_permission ($Request, $label) {
114 42
		if ($Request->cli_path) {
115 3
			return true;
116
		}
117 42
		$permission_group = $Request->current_module;
118 42
		if ($Request->admin_path) {
119 6
			$permission_group = "admin/$permission_group";
120 39
		} elseif ($Request->api_path) {
121 36
			$permission_group = "api/$permission_group";
122
		}
123 42
		return User::instance()->get_permission($permission_group, $label);
124
	}
125
	/**
126
	 * @param Request $Request
127
	 * @param Page    $Page
128
	 */
129 36
	protected function render ($Request, $Page) {
130 36
		if ($Request->api_path) {
131 33
			$Page->json(null);
132 33
			$this->execute_router($Request);
133 6
		} elseif ($Request->cli_path || !$Page->interface) {
134 3
			$this->execute_router($Request);
135
		} else {
136 6
			$this->render_title($Request, $Page);
137 6
			$this->execute_router($Request);
138 6
			$this->render_blocks($Page);
139
		}
140 36
	}
141
	/**
142
	 * Render page title
143
	 *
144
	 * @param Request $Request
145
	 * @param Page    $Page
146
	 */
147 6
	protected function render_title ($Request, $Page) {
148
		/**
149
		 * Add generic Home or Module name title
150
		 */
151 6
		$L = Language::instance();
152 6
		if ($Request->admin_path) {
153 3
			$Page->title($L->system_admin_administration);
0 ignored issues
show
Bug Best Practice introduced by
The property system_admin_administration does not exist on cs\Language. Since you implemented __get, consider adding a @property annotation.
Loading history...
154
		}
155 6
		$Page->title(
156 6
			$L->{$Request->home_page ? 'system_home' : $Request->current_module}
157
		);
158 6
	}
159
	/**
160
	 * Blocks rendering
161
	 *
162
	 * @param Page $Page
163
	 */
164 6
	protected function render_blocks ($Page) {
165
		/**
166
		 * @var array $blocks
167
		 */
168 6
		$blocks = Config::instance()->components['blocks'];
169
		/**
170
		 * It is frequent that there is no blocks - so, no need to to anything here
171
		 */
172 6
		if (!$blocks) {
0 ignored issues
show
introduced by
The condition ! $blocks can never be false.
Loading history...
173 6
			return;
174
		}
175
		$blocks_array = [
176 3
			'top'    => '',
177
			'left'   => '',
178
			'right'  => '',
179
			'bottom' => ''
180
		];
181 3
		foreach ($blocks as $block) {
182
			/**
183
			 * If there is no need to show block or it was rendered by even handler - skip further processing
184
			 */
185
			if (
186 3
				!$this->should_block_be_rendered($block) ||
187 3
				!Event::instance()->fire(
188 3
					'System/App/block_render',
189
					[
190 3
						'index'        => $block['index'],
191 3
						'blocks_array' => &$blocks_array
192
					]
193
				)
194
			) {
195
				/**
196
				 * Block was rendered by event handler
197
				 */
198 3
				continue;
199
			}
200 3
			$block['title'] = $this->ml_process($block['title']);
201 3
			switch ($block['type']) {
202
				default:
203 3
					$block['content'] = ob_wrapper(
204 3
						function () use ($block) {
205 3
							include BLOCKS."/block.$block[type].php";
206 3
						}
207
					);
208 3
					break;
209
				case 'html':
210
				case 'raw_html':
211 3
					$block['content'] = $this->ml_process($block['content']);
212 3
					break;
213
			}
214 3
			if ($block['position'] == 'floating') {
215 3
				$Page->replace(
216 3
					"<!--block#$block[index]-->",
217 3
					$block['content']
218
				);
219
			} else {
220 3
				$blocks_array[$block['position']] .= $block['content'];
221
			}
222
		}
223 3
		$Page->Top .= $blocks_array['top'];
224 3
		$Page->Left .= $blocks_array['left'];
225 3
		$Page->Right .= $blocks_array['right'];
226 3
		$Page->Bottom .= $blocks_array['bottom'];
227 3
	}
228
	/**
229
	 * Check whether to render block or not based on its properties (active state, when start to show, when it expires and permissions)
230
	 *
231
	 * @param array $block
232
	 *
233
	 * @return bool
234
	 */
235 3
	protected function should_block_be_rendered ($block) {
236
		return
237 3
			$block['active'] &&
238 3
			$block['start'] <= time() &&
239
			(
240 3
				!$block['expire'] ||
241 3
				$block['expire'] >= time()
242
			) &&
243 3
			User::instance()->get_permission('Block', $block['index']);
244
	}
245
	/**
246
	 * @param string $text
247
	 *
248
	 * @return string
249
	 */
250 3
	protected function ml_process ($text) {
251 3
		return Text::instance()->process(Config::instance()->module('System')->db('texts'), $text, true);
252
	}
253
	/**
254
	 * Getter for `controller_path` property (no other properties supported currently)
255
	 *
256
	 * @param string $property
257
	 *
258
	 * @return false|string[]
259
	 */
260 9
	public function __get ($property) {
261 9
		if ($property == 'controller_path') {
262 9
			return $this->controller_path;
263
		}
264 3
		return false;
265
	}
266
}
267