Completed
Push — master ( 444a6b...0030e4 )
by Jeroen
11:43
created

Router::isPublicPage()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 56
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 5.0105

Importance

Changes 0
Metric Value
cc 5
eloc 38
nc 8
nop 1
dl 0
loc 56
ccs 37
cts 40
cp 0.925
crap 5.0105
rs 8.7592
c 0
b 0
f 0

How to fix   Long Method   

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
namespace Elgg;
4
5
use Elgg\Http\Request;
6
use Elgg\Http\ResponseBuilder;
7
use RuntimeException;
8
9
/**
10
 * Delegates requests to controllers based on the registered configuration.
11
 *
12
 * Plugin devs should use these wrapper functions:
13
 *  * elgg_register_page_handler
14
 *  * elgg_unregister_page_handler
15
 *
16
 * @package    Elgg.Core
17
 * @subpackage Router
18
 * @since      1.9.0
19
 * @access private
20
 */
21
class Router {
22
23
	use Profilable;
24
25
	private $handlers = array();
26
	private $hooks;
27
28
	/**
29
	 * Constructor
30
	 *
31
	 * @param PluginHooksService $hooks For customized routing.
32
	 */
33 77
	public function __construct(PluginHooksService $hooks) {
34 77
		$this->hooks = $hooks;
35 77
	}
36
37
	/**
38
	 * Routes the request to a registered page handler
39
	 *
40
	 * This function triggers a plugin hook `'route', $identifier` so that plugins can
41
	 * modify the routing or handle a request.
42
	 *
43
	 * @param Request $request The request to handle.
44
	 * @return boolean Whether the request was routed successfully.
45
	 * @access private
46
	 */
47 75
	public function route(Request $request) {
48 75
		$segments = $request->getUrlSegments();
49 75
		if ($segments) {
50 75
			$identifier = array_shift($segments);
51 75
		} else {
52
			$identifier = '';
53
			$segments = [];
54
		}
55
56 75
		$is_walled_garden = _elgg_services()->config->get('walled_garden');
57 75
		$is_logged_in = _elgg_services()->session->isLoggedIn();
58 75
		$url = elgg_normalize_url($identifier . '/' . implode('/', $segments));
59
		
60 75
		if ($is_walled_garden && !$is_logged_in && !$this->isPublicPage($url)) {
61 1
			if (!elgg_is_xhr()) {
62 1
				_elgg_services()->session->set('last_forward_from', current_page_url());
63 1
			}
64 1
			register_error(_elgg_services()->translator->translate('loggedinrequired'));
65 1
			_elgg_services()->responseFactory->redirect('', 'walled_garden');
66 1
			return false;
67
		}
68
69
		// return false to stop processing the request (because you handled it)
70
		// return a new $result array if you want to route the request differently
71
		$old = array(
72 74
			'identifier' => $identifier,
73 74
			'handler' => $identifier, // backward compatibility
74 74
			'segments' => $segments,
75 74
		);
76
77 74
		if ($this->timer) {
78
			$this->timer->begin(['build page']);
79
		}
80
81 74
		ob_start();
82
83 74
		$result = $this->hooks->trigger('route', $identifier, $old, $old);
84 74
		if ($result === false) {
85 9
			$output = ob_get_clean();
86 9
			$response = elgg_ok_response($output);
87 9
		} else {
88 65
			if ($result !== $old) {
89 2
				_elgg_services()->logger->warn('Use the route:rewrite hook to modify routes.');
90 2
			}
91
92 65
			if ($identifier != $result['identifier']) {
93 1
				$identifier = $result['identifier'];
94 65
			} else if ($identifier != $result['handler']) {
95 1
				$identifier = $result['handler'];
96 1
			}
97
98 65
			$segments = $result['segments'];
99
100 65
			$response = false;
101
102 65
			if (isset($this->handlers[$identifier]) && is_callable($this->handlers[$identifier])) {
103 64
				$function = $this->handlers[$identifier];
104 64
				$response = call_user_func($function, $segments, $identifier);
105 64
			}
106
			
107 65
			$output = ob_get_clean();
108
			
109 65
			if ($response === false) {
110 1
				return headers_sent();
111
			}
112
113 64
			if (!$response instanceof ResponseBuilder) {
114 4
				$response = elgg_ok_response($output);
115 4
			}
116
		}
117
118 73
		if (_elgg_services()->responseFactory->getSentResponse()) {
119 14
			return true;
120
		}
121
		
122 59
		_elgg_services()->responseFactory->respond($response);
123 58
		return headers_sent();
124
	}
125
126
	/**
127
	 * Register a function that gets called when the first part of a URL is
128
	 * equal to the identifier.
129
	 *
130
	 * @param string $identifier The page type to handle
131
	 * @param string $function   Your function name
132
	 *
133
	 * @return bool Depending on success
134
	 */
135 199
	public function registerPageHandler($identifier, $function) {
136 199
		if (is_callable($function, true)) {
137 199
			$this->handlers[$identifier] = $function;
138 199
			return true;
139
		}
140
141 1
		return false;
142
	}
143
144
	/**
145
	 * Unregister a page handler for an identifier
146
	 *
147
	 * @param string $identifier The page type identifier
148
	 *
149
	 * @return void
150
	 */
151 1
	public function unregisterPageHandler($identifier) {
152 1
		unset($this->handlers[$identifier]);
153 1
	}
154
155
	/**
156
	 * Get page handlers as array of identifier => callback
157
	 * 
158
	 * @return array
159
	 */
160 1
	public function getPageHandlers() {
161 1
		return $this->handlers;
162
	}
163
164
	/**
165
	 * Filter a request through the route:rewrite hook
166
	 *
167
	 * @param Request $request Elgg request
168
	 *
169
	 * @return Request
170
	 * @access private
171
	 */
172 1
	public function allowRewrite(Request $request) {
173 1
		$segments = $request->getUrlSegments();
174 1
		if ($segments) {
175 1
			$identifier = array_shift($segments);
176 1
		} else {
177
			$identifier = '';
178
		}
179
180
		$old = array(
181 1
			'identifier' => $identifier,
182 1
			'segments' => $segments,
183 1
		);
184 1
		$new = _elgg_services()->hooks->trigger('route:rewrite', $identifier, $old, $old);
185 1
		if ($new === $old) {
186
			return $request;
187
		}
188
189 1
		if (!isset($new['identifier']) || !isset($new['segments']) || !is_string($new['identifier']) || !is_array($new['segments'])
190 1
		) {
191
			throw new RuntimeException('rewrite_path handler returned invalid route data.');
192
		}
193
194
		// rewrite request
195 1
		$segments = $new['segments'];
196 1
		array_unshift($segments, $new['identifier']);
197 1
		return $request->setUrlSegments($segments);
198
	}
199
200
	/**
201
	 * Checks if the page should be allowed to be served in a walled garden mode
202
	 *
203
	 * Pages are registered to be public by {@elgg_plugin_hook public_pages walled_garden}.
204
	 *
205
	 * @param string $url Defaults to the current URL
206
	 *
207
	 * @return bool
208
	 * @since 3.0
209
	 */
210 22
	public function isPublicPage($url = '') {
211 22
		if (empty($url)) {
212
			$url = current_page_url();
213
		}
214
215 22
		$parts = parse_url($url);
216 22
		unset($parts['query']);
217 22
		unset($parts['fragment']);
218 22
		$url = elgg_http_build_url($parts);
0 ignored issues
show
Security Bug introduced by
It seems like $parts defined by parse_url($url) on line 215 can also be of type false; however, elgg_http_build_url() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
219 22
		$url = rtrim($url, '/') . '/';
220
221 22
		$site_url = _elgg_services()->config->getSiteUrl();
222
223 22
		if ($url == $site_url) {
224
			// always allow index page
225
			return true;
226
		}
227
228
		// default public pages
229
		$defaults = array(
230 22
			'walled_garden/.*',
231 22
			'action/.*',
232 22
			'login',
233 22
			'register',
234 22
			'forgotpassword',
235 22
			'changepassword',
236 22
			'refresh_token',
237 22
			'ajax/view/languages.js',
238 22
			'upgrade\.php',
239 22
			'css/.*',
240 22
			'js/.*',
241 22
			'cache/[0-9]+/\w+/.*',
242 22
			'cron/.*',
243 22
			'services/.*',
244 22
			'serve-file/.*',
245 22
			'robots.txt',
246 22
			'favicon.ico',
247 22
		);
248
249
		$params = [
250 22
			'url' => $url,
251 22
		];
252
253 22
		$public_routes = _elgg_services()->hooks->trigger('public_pages', 'walled_garden', $params, $defaults);
254
		
255 22
		$site_url = preg_quote($site_url);
256 22
		foreach ($public_routes as $public_route) {
257 22
			$pattern = "`^{$site_url}{$public_route}/*$`i";
258 22
			if (preg_match($pattern, $url)) {
259 19
				return true;
260
			}
261 21
		}
262
263
		// non-public page
264 3
		return false;
265
	}
266
267
}
268