Passed
Push — master ( c2d8e3...289151 )
by Jeroen
06:06
created

elgg_generate_entity_url()   C

Complexity

Conditions 9
Paths 21

Size

Total Lines 60
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
eloc 36
nc 21
nop 4
dl 0
loc 60
ccs 0
cts 21
cp 0
crap 90
rs 6.8358
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
 * Elgg page handler functions
4
 *
5
 * @package    Elgg.Core
6
 * @subpackage Routing
7
 */
8
9
/**
10
 * Register a new route
11
 *
12
 * Route paths can contain wildcard segments, i.e. /blog/owner/{username}
13
 * To make a certain wildcard segment optional, add ? to its name,
14
 * i.e. /blog/owner/{username?}
15
 *
16
 * Wildcard requirements for common named variables such as 'guid' and 'username'
17
 * will be set automatically.
18
 *
19
 * @warning If you are registering a route in the path of a route registered by
20
 *          deprecated {@link elgg_register_page_handler}, your registration must
21
 *          preceed the call to elgg_register_page_handler() in the boot sequence.
22
 *
23
 * @param string $name   Unique route name
24
 *                       This name can later be used to generate route URLs
25
 * @param array  $params Route parameters
26
 *                       - path : path of the route
27
 *                       - resource : name of the resource view
28
 *                       - defaults : default values of wildcard segments
29
 *                       - requirements : regex patterns for wildcard segment requirements
30
 *                       - methods : HTTP methods
31
 *
32
 * @return \Elgg\Router\Route
33
 */
34
function elgg_register_route($name, array $params = []) {
35 112
	return _elgg_services()->router->registerRoute($name, $params);
36
}
37
38
/**
39
 * Unregister a route by its name
40
 *
41
 * @param string $name Name of the route
42
 *
43
 * @return void
44
 */
45
function elgg_unregister_route($name) {
46 19
	_elgg_services()->router->unregisterRoute($name);
47 19
}
48
49
/**
50
 * Generate a URL for named route
51
 *
52
 * @param string $name       Route name
53
 * @param array  $parameters Parameters
54
 *
55
 * @return string
56
 */
57
function elgg_generate_url($name, array $parameters = []) {
58 32
	return _elgg_services()->router->generateUrl($name, $parameters);
59
}
60
61
/**
62
 * Generate entity URL from a named route
63
 *
64
 * This function is intended to generate URLs from registered named routes that depend on entity type and subtype.
65
 * It will first try to detect routes that contain both type and subtype in the name, and will then fallback to
66
 * route names without the subtype, e.g. 'view:object:blog:attachments' and 'view:object:attachments'
67
 *
68
 * @tip Route segments will be automatically resolved from entity attributes and metadata,
69
 *      so given the path `/blog/view/{guid}/{title}/{status}` the path will be
70
 *      be resolved from entity guid, URL-friendly title and status metadata.
71
 *
72
 * @tip Parameters that do not have matching segment names in the route path, will be added to the URL as query elements.
73
 *
74
 *
75
 * @param ElggEntity $entity      Entity
76
 * @param string     $resource    Resource name
77
 * @param string     $subresource Subresource name
78
 * @param array      $parameters  URL query elements
79
 *
80
 * @return string
81
 */
82
function elgg_generate_entity_url(ElggEntity $entity, $resource = 'view', $subresource = null, $parameters = []) {
83
84
	$make_route_name = function ($type, $subtype) use ($resource, $subresource) {
85
		$route_parts = [
86
			$resource,
87
			$type,
88
			$subtype,
89
			$subresource,
90
		];
91
92
		return implode(':', array_filter($route_parts));
93
	};
94
95
	$pairs = [
96
		[$entity->type, $entity->subtype],
97
		[$entity->type, null],
98
	];
99
100
	$route = false;
101
	$route_name = '';
102
103
	foreach ($pairs as $pair) {
104
		$route_name = $make_route_name($pair[0], $pair[1]);
105
		$route = _elgg_services()->routeCollection->get($route_name);
106
		if ($route) {
107
			break;
108
		}
109
	}
110
111
	if (!$route) {
112
		return;
113
	}
114
115
	$requirements = $route->getRequirements();
116
	$defaults = $route->getDefaults();
117
118
	$props = array_merge(array_keys($requirements), array_keys($defaults));
119
120
	foreach ($props as $prop) {
121
		if (substr($prop, 0, 1) === '_') {
122
			continue;
123
		}
124
125
		if (isset($parameters[$prop])) {
126
			continue;
127
		}
128
129
		switch ($prop) {
130
			case 'title' :
131
			case 'name' :
132
				$parameters[$prop] = elgg_get_friendly_title($entity->getDisplayName());
133
				break;
134
135
			default :
136
				$parameters[$prop] = $entity->$prop;
137
				break;
138
		}
139
	}
140
141
	return elgg_generate_url($route_name, $parameters);
142
}
143
144
/**
145
 * Generate an action URL
146
 *
147
 * @param string $action          Action name
148
 * @param array  $query           Query elements
149
 * @param bool   $add_csrf_tokens Add tokens
150
 *
151
 * @return string
152
 */
153
function elgg_generate_action_url($action, array $query = [], $add_csrf_tokens = true) {
154
155
	$url = "action/$action";
156
	$url = elgg_http_add_url_query_elements($url, $query);
157
	$url = elgg_normalize_url($url);
158
159
	if ($add_csrf_tokens) {
160
		$url = elgg_add_action_tokens_to_url($url);
161
	}
162
163
	return $url;
164
}
165
166
/**
167
 * Used at the top of a page to mark it as logged in users only.
168
 *
169
 * @return void
170
 * @throws \Elgg\GatekeeperException
171
 * @since 1.9.0
172
 */
173
function elgg_gatekeeper() {
174
	if (!elgg_is_logged_in()) {
175
		_elgg_services()->redirects->setLastForwardFrom();
176
177
		$msg = elgg_echo('loggedinrequired');
178
		throw new \Elgg\GatekeeperException($msg);
179
	}
180
}
181
182
/**
183
 * Used at the top of a page to mark it as admin only.
184
 *
185
 * @return void
186
 * @throws \Elgg\GatekeeperException
187
 * @since 1.9.0
188
 */
189
function elgg_admin_gatekeeper() {
190
	elgg_gatekeeper();
191
192
	if (!elgg_is_admin_logged_in()) {
193
		_elgg_services()->redirects->setLastForwardFrom();
194
195
		$msg = elgg_echo('adminrequired');
196
		throw new \Elgg\GatekeeperException($msg);
197
	}
198
}
199
200
201
/**
202
 * May the current user access item(s) on this page? If the page owner is a group,
203
 * membership, visibility, and logged in status are taken into account.
204
 *
205
 * @param bool $forward    If set to true (default), will forward the page;
206
 *                         if set to false, will return true or false.
207
 *
208
 * @param int  $group_guid The group that owns the page. If not set, this
209
 *                         will be pulled from elgg_get_page_owner_guid().
210
 *
211
 * @return bool Will return if $forward is set to false.
212
 * @throws InvalidParameterException
213
 * @throws SecurityException
214
 * @since 1.9.0
215
 */
216
function elgg_group_gatekeeper($forward = true, $group_guid = null) {
217
	if (null === $group_guid) {
218
		$group_guid = elgg_get_page_owner_guid();
219
	}
220
221
	if (!$group_guid) {
222 17
		return true;
223
	}
224
225
	// this handles non-groups and invisible groups
226 17
	$visibility = \Elgg\GroupItemVisibility::factory($group_guid);
227
228
	if (!$visibility->shouldHideItems) {
229
		return true;
230
	}
231
	if ($forward) {
232
		// only forward to group if user can see it
233
		$group = get_entity($group_guid);
234
		$forward_url = $group ? $group->getURL() : '';
235
236
		if (!elgg_is_logged_in()) {
237
			_elgg_services()->redirects->setLastForwardFrom();
238
			$forward_reason = 'login';
239
		} else {
240
			$forward_reason = 'member';
241
		}
242
243
		$msg_keys = [
244 70
			'non_member' => 'membershiprequired',
245 8
			'logged_out' => 'loggedinrequired',
246
			'no_access' => 'noaccess',
247
		];
248 70
		register_error(elgg_echo($msg_keys[$visibility->reasonHidden]));
249
		forward($forward_url, $forward_reason);
250
	}
251
252
	return false;
253
}
254
255
/**
256
 * Can the viewer see this entity?
257
 *
258
 * Tests if the entity exists and whether the viewer has access to the entity
259
 * if it does. If the viewer cannot view this entity, it forwards to an
260
 * appropriate page.
261
 *
262
 * @param int    $guid    Entity GUID
263
 * @param string $type    Optional required entity type
264
 * @param string $subtype Optional required entity subtype
265
 * @param bool   $forward If set to true (default), will forward the page;
266
 *                        if set to false, will return true or false.
267
 *
268
 * @return bool Will return if $forward is set to false.
269 36
 * @throws \Elgg\BadRequestException
270 32
 * @throws \Elgg\EntityNotFoundException
271
 * @throws \Elgg\EntityPermissionsException
272
 * @throws \Elgg\GatekeeperException
273 36
 * @since 1.9.0
274
 */
275
function elgg_entity_gatekeeper($guid, $type = null, $subtype = null, $forward = true) {
276
	$entity = get_entity($guid);
277
	if (!$entity && $forward) {
278
		if (!elgg_entity_exists($guid)) {
279
			// entity doesn't exist
280
			throw new \Elgg\EntityNotFoundException();
281
		} else if (!elgg_is_logged_in()) {
282
			// entity requires at least a logged in user
283
			elgg_gatekeeper();
284
		} else {
285
			// user is logged in but still does not have access to it
286
			$msg = elgg_echo('limited_access');
287
			throw new \Elgg\GatekeeperException($msg);
288
		}
289
	} else if (!$entity) {
290
		return false;
291 6
	}
292
293
	if ($type && !elgg_instanceof($entity, $type, $subtype)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
294
		// entity is of wrong type/subtype
295
		if ($forward) {
296
			throw new \Elgg\BadRequestException();
297
		} else {
298
			return false;
299
		}
300 18
	}
301
302
	$hook_type = "{$entity->getType()}:{$entity->getSubtype()}";
303
	$hook_params = [
304
		'entity' => $entity,
305
		'forward' => $forward,
306
	];
307
	if (!elgg_trigger_plugin_hook('gatekeeper', $hook_type, $hook_params, true)) {
308
		if ($forward) {
309
			throw new \Elgg\EntityPermissionsException();
310
		} else {
311
			return false;
312
		}
313
	}
314
315
	return true;
316
}
317
318
/**
319
 * Require that the current request be an XHR. If not, execution of the current function
320
 * will end and a 400 response page will be sent.
321
 *
322
 * @return void
323
 * @throws \Elgg\BadRequestException
324
 * @since 1.12.0
325
 */
326
function elgg_ajax_gatekeeper() {
327
	if (!elgg_is_xhr()) {
328
		$msg = elgg_echo('ajax:not_is_xhr');
329
		throw new \Elgg\BadRequestException($msg);
330
	}
331
}
332
333
/**
334
 * Prepares a successful response to be returned by a page or an action handler
335
 *
336
 * @param mixed  $content     Response content
337
 *                            In page handlers, response content should contain an HTML string
338
 *                            In action handlers, response content can contain either a JSON string or an array of data
339
 * @param string $message     System message visible to the client
340
 *                            Can be used by handlers to display a system message
341
 * @param string $forward_url Forward URL
342
 *                            Can be used by handlers to redirect the client on non-ajax requests
343
 * @param int    $status_code HTTP status code
344
 *                            Status code of the HTTP response (defaults to 200)
345
 *
346
 * @return \Elgg\Http\OkResponse
347
 */
348
function elgg_ok_response($content = '', $message = '', $forward_url = null, $status_code = ELGG_HTTP_OK) {
349
	if ($message) {
350
		system_message($message);
351
	}
352
353
	return new \Elgg\Http\OkResponse($content, $status_code, $forward_url);
354
355
}
356
357
/**
358
 * Prepare an error response to be returned by a page or an action handler
359
 *
360
 * @param string $error       Error message
361
 *                            Can be used by handlers to display an error message
362
 *                            For certain requests this error message will also be used as the response body
363
 * @param string $forward_url URL to redirect the client to
364
 *                            Can be used by handlers to redirect the client on non-ajax requests
365
 * @param int    $status_code HTTP status code
366
 *                            Status code of the HTTP response
367
 *                            For BC reasons and due to the logic in the client-side AJAX API,
368
 *                            this defaults to 200. Note that the Router and AJAX API will
369
 *                            treat these responses as error in spite of the HTTP code assigned
370
 *
371
 * @return \Elgg\Http\ErrorResponse
372
 */
373
function elgg_error_response($error = '', $forward_url = REFERRER, $status_code = ELGG_HTTP_OK) {
374
	if ($error) {
375
		register_error($error);
376
	}
377
378
	return new \Elgg\Http\ErrorResponse($error, $status_code, $forward_url);
379
}
380
381
/**
382
 * Prepare a silent redirect response to be returned by a page or an action handler
383
 *
384
 * @param string $forward_url Redirection URL
385
 *                            Relative or absolute URL to redirect the client to
386
 * @param int    $status_code HTTP status code
387
 *                            Status code of the HTTP response
388
 *                            Note that the Router and AJAX API will treat these responses
389
 *                            as redirection in spite of the HTTP code assigned
390
 *                            Note that non-redirection HTTP codes will throw an exception
391
 *
392
 * @return \Elgg\Http\RedirectResponse
393
 * @throws \InvalidArgumentException
394
 */
395
function elgg_redirect_response($forward_url = REFERRER, $status_code = ELGG_HTTP_FOUND) {
396
	return new Elgg\Http\RedirectResponse($forward_url, $status_code);
397
}
398
399
400
/**
401
 * @see \Elgg\Application::loadCore Do not do work here. Just register for events.
402
 */
403
return function (\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
1 ignored issue
show
Unused Code introduced by
The parameter $events is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

403
return function (/** @scrutinizer ignore-unused */ \Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $hooks is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

403
return function (\Elgg\EventsService $events, /** @scrutinizer ignore-unused */ \Elgg\HooksRegistrationService $hooks) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
404
405
};
406