Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

mod/pages/start.php (13 issues)

1
<?php
2
/**
3
 * Elgg Pages
4
 */
5
6
require_once(dirname(__FILE__) . '/lib/pages.php');
7
8
/**
9
 * Initialize the pages plugin
10
 *
11
 * @return void
12
 */
13
function pages_init() {
14
15
	// register a library of helper functions
16 31
	elgg_register_library('elgg:pages', __DIR__ . '/lib/pages.php');
17
18 31
	$item = new ElggMenuItem('pages', elgg_echo('pages'), 'pages/all');
19 31
	elgg_register_menu_item('site', $item);
20
21
	// Register a page handler, so we can have nice URLs
22 31
	elgg_register_page_handler('pages', 'pages_page_handler');
23
24
	// Register a url handler
25 31
	elgg_register_plugin_hook_handler('entity:url', 'object', 'pages_set_url');
26 31
	elgg_register_plugin_hook_handler('extender:url', 'annotation', 'pages_set_revision_url');
27
28
	// Extend the main css view
29 31
	elgg_extend_view('elgg.css', 'pages/css');
30
31
	// Register for notifications
32 31
	elgg_register_notification_event('object', 'page');
33 31
	elgg_register_plugin_hook_handler('prepare', 'notification:create:object:page', 'pages_prepare_notification');
34
35
	// add to groups
36 31
	add_group_tool_option('pages', elgg_echo('groups:enablepages'), true);
37 31
	elgg_extend_view('groups/tool_latest', 'pages/group_module');
38
	
39
	// Language short codes must be of the form "pages:key"
40
	// where key is the array key below
41 31
	elgg_set_config('pages', [
42 31
		'title' => 'text',
43
		'description' => 'longtext',
44
		'tags' => 'tags',
45
		'parent_guid' => 'pages/parent',
46
		'access_id' => 'access',
47
		'write_access_id' => 'access',
48
	]);
49
50 31
	elgg_register_plugin_hook_handler('register', 'menu:owner_block', 'pages_owner_block_menu');
51
52
	// write permission plugin hooks
53 31
	elgg_register_plugin_hook_handler('permissions_check', 'object', 'pages_write_permission_check');
54 31
	elgg_register_plugin_hook_handler('container_permissions_check', 'object', 'pages_container_permission_check');
55
56 31
	elgg_register_plugin_hook_handler('access:collections:write', 'user', 'pages_write_access_options_hook');
57
58
	// icon url override
59 31
	elgg_register_plugin_hook_handler('entity:icon:url', 'object', 'pages_icon_url_override');
60
61
	// entity menu
62 31
	elgg_register_plugin_hook_handler('register', 'menu:entity', 'pages_entity_menu_setup');
63
64
	// register ecml views to parse
65 31
	elgg_register_plugin_hook_handler('get_views', 'ecml', 'pages_ecml_views_hook');
66
67
	// allow to be liked
68 31
	elgg_register_plugin_hook_handler('likes:is_likable', 'object:page', 'Elgg\Values::getTrue');
69
	
70
	// prevent public write access
71 31
	elgg_register_plugin_hook_handler('view_vars', 'input/access', 'pages_write_access_vars');
72 31
}
73
74
/**
75
 * Dispatcher for pages.
76
 * URLs take the form of
77
 *  All pages:        pages/all
78
 *  User's pages:     pages/owner/<username>
79
 *  Friends' pages:   pages/friends/<username>
80
 *  View page:        pages/view/<guid>/<title>
81
 *  New page:         pages/add/<guid> (container: user, group, parent)
82
 *  Edit page:        pages/edit/<guid>
83
 *  History of page:  pages/history/<guid>
84
 *  Revision of page: pages/revision/<id>
85
 *  Group pages:      pages/group/<guid>/all
86
 *
87
 * Title is ignored
88
 *
89
 * @param array $page URL segments
90
 *
91
 * @return bool
92
 */
93
function pages_page_handler($page) {
94
95
	elgg_push_breadcrumb(elgg_echo('pages'), 'pages/all');
96
97
	switch (elgg_extract(0, $page, 'all')) {
98
		case 'owner':
99
			echo elgg_view_resource('pages/owner');
100
			break;
101
		case 'friends':
102
			echo elgg_view_resource('pages/friends');
103
			break;
104
		case 'view':
105
			echo elgg_view_resource('pages/view', [
106
				'guid' => (int) elgg_extract(1, $page),
107
			]);
108
			break;
109
		case 'add':
110
			echo elgg_view_resource('pages/new', [
111
				'guid' => (int) elgg_extract(1, $page),
112
			]);
113
			break;
114
		case 'edit':
115
			echo elgg_view_resource('pages/edit', [
116
				'guid' => (int) elgg_extract(1, $page),
117
			]);
118
			break;
119
		case 'group':
120
			echo elgg_view_resource('pages/owner');
121
			break;
122
		case 'history':
123
			echo elgg_view_resource('pages/history', [
124
				'guid' => (int) elgg_extract(1, $page),
125
			]);
126
			break;
127
		case 'revision':
128
			echo elgg_view_resource('pages/revision', [
129
				'id' => (int) elgg_extract(1, $page),
130
			]);
131
			break;
132
		case 'all':
133
			echo elgg_view_resource('pages/all');
134
			break;
135
		default:
136
			return false;
137
	}
138
	
139
	return true;
140
}
141
142
/**
143
 * Override the page url
144
 *
145
 * @param string $hook   'entity:url'
146
 * @param string $type   'object'
147
 * @param string $url    current return value
148
 * @param array  $params supplied params
149
 *
150
 * @return void|string
151
 */
152
function pages_set_url($hook, $type, $url, $params) {
153 3
	$entity = elgg_extract('entity', $params);
154 3
	if (!$entity instanceof ElggPage) {
155 3
		return;
156
	}
157
	
158
	$title = elgg_get_friendly_title($entity->getDisplayName());
159
	return "pages/view/{$entity->guid}/{$title}";
160
}
161
162
/**
163
 * Override the page annotation url
164
 *
165
 * @param string $hook   'extender:url'
166
 * @param string $type   'annotation'
167
 * @param string $url    current return value
168
 * @param array  $params supplied params
169
 *
170
 * @return void|string
171
 */
172
function pages_set_revision_url($hook, $type, $url, $params) {
173
	
174
	$annotation = elgg_extract('extender', $params);
175
	if ($annotation->getSubtype() == 'page') {
176
		return "pages/revision/{$annotation->id}";
177
	}
178
}
179
180
/**
181
 * Override the default entity icon for pages
182
 *
183
 * @param string $hook        'entity:icon:url'
184
 * @param string $type        'object'
185
 * @param string $returnvalue current return value
186
 * @param array  $params      supplied params
187
 *
188
 * @return string
189
 */
190
function pages_icon_url_override($hook, $type, $returnvalue, $params) {
191
	
192 1
	$entity = elgg_extract('entity', $params);
193 1
	if ($entity instanceof ElggPage) {
194
		return elgg_get_simplecache_url('pages/images/pages.gif');
195
	}
196 1
}
197
198
/**
199
 * Add a menu item to the user ownerblock
200
 *
201
 * @param string         $hook   'register'
202
 * @param string         $type   'menu:owner_block'
203
 * @param ElggMenuItem[] $return current return value
204
 * @param array          $params supplied params
205
 *
206
 * @return ElggMenuItem[]
207
 */
208
function pages_owner_block_menu($hook, $type, $return, $params) {
209
	
210
	$entity = elgg_extract('entity', $params);
211
	if ($entity instanceof ElggUser) {
212
		$url = "pages/owner/{$entity->username}";
213
		$item = new ElggMenuItem('pages', elgg_echo('pages'), $url);
214
		$return[] = $item;
215
	} elseif ($entity instanceof ElggGroup) {
216
		if ($entity->isToolEnabled('pages')) {
217
			$url = "pages/group/{$entity->guid}/all";
218
			$item = new ElggMenuItem('pages', elgg_echo('pages:group'), $url);
219
			$return[] = $item;
220
		}
221
	}
222
	
223
	return $return;
224
}
225
226
/**
227
 * Add links/info to entity menu particular to pages plugin
228
 *
229
 * @param string         $hook   'register'
230
 * @param string         $type   'menu:entity'
231
 * @param ElggMenuItem[] $return current return value
232
 * @param array          $params supplied params
233
 *
234
 * @return void|ElggMenuItem[]
235
 */
236
function pages_entity_menu_setup($hook, $type, $return, $params) {
237
238 1
	$entity = elgg_extract('entity', $params);
239 1
	if (!$entity instanceof ElggPage) {
240 1
		return;
241
	}
242
	
243
	if (!$entity->canEdit()) {
244
		return;
245
	}
246
	
247
	$return[] = \ElggMenuItem::factory([
248
		'name' => 'history',
249
		'icon' => 'history',
250
		'text' => elgg_echo('pages:history'),
251
		'href' => "pages/history/{$entity->guid}",
252
	]);
253
254
	return $return;
255
}
256
257
/**
258
 * Prepare a notification message about a new page
259
 *
260
 * @param string                          $hook         'prepare'
261
 * @param string                          $type         'notification:create:object:page' | 'notification:create:object:page_top'
262
 * @param Elgg\Notifications\Notification $notification The notification to prepare
263
 * @param array                           $params       Hook parameters
264
 *
265
 * @return void|Elgg\Notifications\Notification
266
 */
267
function pages_prepare_notification($hook, $type, $notification, $params) {
268
	
269
	$event = elgg_extract('event', $params);
270
	
271
	$entity = $event->getObject();
272
	if (!$entity instanceof ElggPage) {
273
		return;
274
	}
275
	
276
	$owner = $event->getActor();
277
	$recipient = elgg_extract('recipient', $params);
0 ignored issues
show
The assignment to $recipient is dead and can be removed.
Loading history...
278
	$language = elgg_extract('language', $params);
279
	$method = elgg_extract('method', $params);
0 ignored issues
show
The assignment to $method is dead and can be removed.
Loading history...
280
281
	$descr = $entity->description;
282
	$title = $entity->getDisplayName();
283
284
	$notification->subject = elgg_echo('pages:notify:subject', [$title], $language);
285
	$notification->body = elgg_echo('pages:notify:body', [
286
		$owner->getDisplayName(),
287
		$title,
288
		$descr,
289
		$entity->getURL(),
290
	], $language);
291
	$notification->summary = elgg_echo('pages:notify:summary', [$entity->getDisplayName()], $language);
292
	$notification->url = $entity->getURL();
293
	
294
	return $notification;
295
}
296
297
/**
298
 * Extend permissions checking to extend can-edit for write users.
299
 *
300
 * @param string $hook        'permissions_check'
301
 * @param string $type        'object'
302
 * @param bool   $returnvalue current return value
303
 * @param array  $params      supplied params
304
 *
305
 * @return void|bool
306
 */
307
function pages_write_permission_check($hook, $type, $returnvalue, $params) {
1 ignored issue
show
The parameter $type 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

307
function pages_write_permission_check($hook, /** @scrutinizer ignore-unused */ $type, $returnvalue, $params) {

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...
308
	
309 113
	$entity = elgg_extract('entity', $params);
310 113
	if (!$entity instanceof ElggPage) {
311 107
		return;
312
	}
313
	
314 6
	$write_permission = (int) $entity->write_access_id;
315 6
	$user = elgg_extract('user', $params);
316
317 6
	if (empty($write_permission) || !$user instanceof ElggUser) {
318 6
		return;
319
	}
320
	
321
	switch ($write_permission) {
322
		case ACCESS_PRIVATE:
323
			// Elgg's default decision is what we want
324
			return;
325
			break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
326
		default:
327
			$list = get_access_array($user->guid);
328
			if (in_array($write_permission, $list)) {
329
				// user in the access collection
330
				return true;
331
			}
332
			break;
333
	}
334
}
335
336
/**
337
 * Extend container permissions checking to extend container write access for write users.
338
 *
339
 * @param string $hook        'container_permissions_check'
340
 * @param string $type        'object'
341
 * @param bool   $returnvalue current return value
342
 * @param array  $params      supplied params
343
 *
344
 * @return void|bool
345
 */
346
function pages_container_permission_check($hook, $type, $returnvalue, $params) {
347
	
348 8
	$subtype = elgg_extract('subtype', $params);
349
	// check type/subtype
350 8
	if ($type !== 'object' || $subtype !== 'page') {
351 2
		return;
352
	}
353
	
354 6
	$container = elgg_extract('container', $params);
355 6
	$user = elgg_extract('user', $params);
356
	
357 6
	if (!$user instanceof ElggUser) {
358
		return;
359
	}
360
	
361
	// OK if you can write to the container
362 6
	if ($container instanceof ElggEntity && $container->canWriteToContainer($user->guid)) {
363 6
		return true;
364
	}
365
366
	// look up a page object given via input
367
	if ($page_guid = get_input('page_guid', 0)) {
368
		$page = get_entity($page_guid);
0 ignored issues
show
It seems like $page_guid can also be of type string; however, parameter $guid of get_entity() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

368
		$page = get_entity(/** @scrutinizer ignore-type */ $page_guid);
Loading history...
369
	} elseif ($parent_guid = get_input('parent_guid', 0)) {
370
		$page = get_entity($parent_guid);
371
	}
372
	if (!$page instanceof ElggPage) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $page does not seem to be defined for all execution paths leading up to this point.
Loading history...
373
		return;
374
	}
375
376
	// try the page's container
377
	$page_container = $page->getContainerEntity();
378
	if ($page_container && $page_container->canWriteToContainer($user->guid)) {
379
		return true;
380
	}
381
382
	// I don't understand this but it's old - mrclay
383
	if (in_array($page->write_access_id, get_access_list())) {
0 ignored issues
show
get_access_list() of type string is incompatible with the type array expected by parameter $haystack of in_array(). ( Ignorable by Annotation )

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

383
	if (in_array($page->write_access_id, /** @scrutinizer ignore-type */ get_access_list())) {
Loading history...
384
		return true;
385
	}
386
}
387
388
/**
389
 * Return views to parse for pages.
390
 *
391
 * @param string $hook         'get_views'
392
 * @param string $type         'ecml'
393
 * @param array  $return_value current return value
394
 * @param array  $params       supplied params
395
 *
396
 * @return array
397
 */
398
function pages_ecml_views_hook($hook, $type, $return_value, $params) {
1 ignored issue
show
The parameter $type 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

398
function pages_ecml_views_hook($hook, /** @scrutinizer ignore-unused */ $type, $return_value, $params) {

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...
399
	$return_value['object/page'] = elgg_echo('item:object:page');
400
401
	return $return_value;
402
}
403
404
/**
405
 * Is the given value a page object?
406
 *
407
 * @param ElggObject $value the entity to check
408
 *
409
 * @return bool
410
 * @access private
411
 */
412
function pages_is_page($value) {
413
	
414
	if (!$value instanceof ElggObject) {
415
		return false;
416
	}
417
	
418
	return in_array($value->getSubtype(), ['page', 'page_top']);
419
}
420
421
/**
422
 * Return options for the write_access_id input
423
 *
424
 * @param string $hook         'access:collections:write'
425
 * @param string $type         'user'
426
 * @param array  $return_value current return value
427
 * @param array  $params       supplied params
428
 *
429
 * @return void|array
430
 */
431
function pages_write_access_options_hook($hook, $type, $return_value, $params) {
2 ignored issues
show
The parameter $type 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

431
function pages_write_access_options_hook($hook, /** @scrutinizer ignore-unused */ $type, $return_value, $params) {

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...
The parameter $hook 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

431
function pages_write_access_options_hook(/** @scrutinizer ignore-unused */ $hook, $type, $return_value, $params) {

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...
432
	
433 5
	$input_params = elgg_extract('input_params', $params);
434 5
	if (empty($input_params) || !isset($return_value[ACCESS_PUBLIC])) {
435 5
		return;
436
	}
437
	
438
	if (elgg_extract('entity_subtype', $input_params) !== 'page') {
439
		return;
440
	}
441
442
	if (elgg_extract('purpose', $input_params) !== 'write') {
443
		return;
444
	}
445
	
446
	unset($return_value[ACCESS_PUBLIC]);
447
	
448
	return $return_value;
449
}
450
451
/**
452
 * Called on view_vars, input/access hook
453
 * Prevent ACCESS_PUBLIC from ending up as a write access option
454
 *
455
 * @param string $hook   'view_vars'
456
 * @param string $type   'input/access'
457
 * @param array  $return current return value
458
 * @param array  $params supplied params
459
 *
460
 * @return void|array
461
 */
462
function pages_write_access_vars($hook, $type, $return, $params) {
3 ignored issues
show
The parameter $type 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

462
function pages_write_access_vars($hook, /** @scrutinizer ignore-unused */ $type, $return, $params) {

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...
The parameter $hook 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

462
function pages_write_access_vars(/** @scrutinizer ignore-unused */ $hook, $type, $return, $params) {

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...
The parameter $params 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

462
function pages_write_access_vars($hook, $type, $return, /** @scrutinizer ignore-unused */ $params) {

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...
463
	
464
	if (elgg_extract('name', $return) !== 'write_access_id' || elgg_extract('purpose', $return) !== 'write') {
465
		return;
466
	}
467
	
468
	$value = (int) elgg_extract('value', $return);
469
	if ($value !== ACCESS_PUBLIC && $value !== ACCESS_DEFAULT) {
470
		return;
471
	}
472
	
473
	$default_access = get_default_access();
474
	
475
	if ($value === ACCESS_PUBLIC || $default_access === ACCESS_PUBLIC) {
476
		// is the value public, or default which resolves to public?
477
		// if so we'll set it to logged in, the next most permissible write access level
478
		$return['value'] = ACCESS_LOGGED_IN;
479
	}
480
	
481
	return $return;
482
}
483
484
return function() {
485 18
	elgg_register_event_handler('init', 'system', 'pages_init');
486
};
487