Test Failed
Push — master ( 8c47c2...3acf9f )
by Steve
12:37
created

mod/groups/start.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Elgg groups plugin
4
 *
5
 * @package ElggGroups
6
 */
7
8
elgg_register_event_handler('init', 'system', 'groups_init');
9
10
// Ensure this runs after other plugins
11
elgg_register_event_handler('init', 'system', 'groups_fields_setup', 10000);
12
13
/**
14
 * Initialize the groups plugin.
15
 */
16
function groups_init() {
17
18
	elgg_register_library('elgg:groups', __DIR__ . '/lib/groups.php');
19
	elgg_load_library('elgg:groups');
20
	
21
	// register group entities for search
22
	elgg_register_entity_type('group', '');
23
24
	// Set up the menu
25
	$item = new ElggMenuItem('groups', elgg_echo('groups'), 'groups/all');
26
	elgg_register_menu_item('site', $item);
27
28
	// Register a page handler, so we can have nice URLs
29
	elgg_register_page_handler('groups', 'groups_page_handler');
30
31
	// Register URL handlers for groups
32
	elgg_register_plugin_hook_handler('entity:url', 'group', 'groups_set_url');
33
	elgg_register_plugin_hook_handler('entity:icon:sizes', 'group', 'groups_set_icon_sizes');
34
35
	// add group activity tool option
36
	if (elgg_get_plugin_setting('allow_activity', 'groups') === 'yes') {
37
		add_group_tool_option('activity', elgg_echo('groups:enableactivity'), true);
38
		elgg_extend_view('groups/tool_latest', 'groups/profile/activity_module');
39
	}
40
41
	// add link to owner block
42
	elgg_register_plugin_hook_handler('register', 'menu:owner_block', 'groups_activity_owner_block_menu');
43
44
	// group entity menu
45
	elgg_register_plugin_hook_handler('register', 'menu:entity', 'groups_entity_menu_setup');
46
47
	// group user hover menu
48
	elgg_register_plugin_hook_handler('register', 'menu:user_hover', 'groups_user_entity_menu_setup');
49
50
	// invitation request actions
51
	elgg_register_plugin_hook_handler('register', 'menu:invitationrequest', 'groups_invitationrequest_menu_setup');
52
53
	// group members tabs
54
	elgg_register_plugin_hook_handler('register', 'menu:groups_members', 'groups_members_menu_setup');
55
56
	//extend some views
57
	elgg_extend_view('elgg.css', 'groups/css');
58
	if (_elgg_view_may_be_altered('groups/js', __DIR__ . '/views/default/groups/js.php')) {
59
		elgg_deprecated_notice('groups/js view has been deprecated. Use AMD modules instead', '2.2');
60
		elgg_extend_view('elgg.js', 'groups/js');
61
	}
62
63
	// Access permissions
64
	elgg_register_plugin_hook_handler('access:collections:write', 'all', 'groups_write_acl_plugin_hook', 600);
65
	elgg_register_plugin_hook_handler('default', 'access', 'groups_access_default_override');
66
	elgg_register_plugin_hook_handler('access_collection:name', 'access_collection', 'groups_set_access_collection_name');
67
68
	// Register profile menu hook
69
	elgg_register_plugin_hook_handler('profile_menu', 'profile', 'activity_profile_menu');
70
71
	// allow ecml in profiles
72
	elgg_register_plugin_hook_handler('get_views', 'ecml', 'groupprofile_ecml_views_hook');
73
74
	// Register a handler for create groups
75
	elgg_register_event_handler('create', 'group', 'groups_create_event_listener');
76
	elgg_register_event_handler('update:after', 'group', 'groups_update_event_listener');
77
78
	elgg_register_event_handler('join', 'group', 'groups_user_join_event_listener');
79
	elgg_register_event_handler('leave', 'group', 'groups_user_leave_event_listener');
80
81
	elgg_register_plugin_hook_handler('access:collections:add_user', 'collection', 'groups_access_collection_override');
82
83
	elgg_register_event_handler('upgrade', 'system', 'groups_run_upgrades');
84
85
	// Add tests
86
	elgg_register_plugin_hook_handler('unit_test', 'system', 'groups_test');
87
88
	// allow to be liked
89
	elgg_register_plugin_hook_handler('likes:is_likable', 'group:', 'Elgg\Values::getTrue');
90
91
	// prepare profile buttons to be registered in the title menu
92
	elgg_register_plugin_hook_handler('profile_buttons', 'group', 'groups_prepare_profile_buttons');
93
94
	// Help core resolve page owner guids from group routes
95
	// Registered with an earlier priority to be called before default_page_owner_handler()
96
	elgg_register_plugin_hook_handler('page_owner', 'system', 'groups_default_page_owner_handler', 400);
97
98
	// Setup filter tabs on /groups/all page
99
	elgg_register_plugin_hook_handler('register', 'menu:filter:groups/all', 'groups_setup_filter_tabs');
100
101
	elgg_register_plugin_hook_handler('register', 'menu:page', '_groups_page_menu_group_profile');
102
	elgg_register_plugin_hook_handler('register', 'menu:page', '_groups_page_menu');
103
}
104
105
/**
106
 * This function loads a set of default fields into the profile, then triggers
107
 * a hook letting other plugins to edit add and delete fields.
108
 *
109
 * Note: This is a system:init event triggered function and is run at a super
110
 * low priority to guarantee that it is called after all other plugins have
111
 * initialized.
112
 */
113
function groups_fields_setup() {
114
115
	$profile_defaults = [
116
		'description' => 'longtext',
117
		'briefdescription' => 'text',
118
		'interests' => 'tags',
119
	];
120
121
	$profile_defaults = elgg_trigger_plugin_hook('profile:fields', 'group', null, $profile_defaults);
122
123
	elgg_set_config('group', $profile_defaults);
124
125
	// register any tag metadata names
126
	foreach ($profile_defaults as $name => $type) {
127
		if ($type == 'tags') {
128
			elgg_register_tag_metadata_name($name);
129
130
			// only shows up in search but why not just set this in en.php as doing it here
131
			// means you cannot override it in a plugin
132
			add_translation(get_current_language(), ["tag_names:$name" => elgg_echo("groups:$name")]);
133
		}
134
	}
135
}
136
137
/**
138
 * Register menu items for the page menu
139
 *
140
 * @param string $hook
141
 * @param string $type
142
 * @param array  $return
143
 * @param array  $params
144
 * @return array
145
 *
146
 * @access private
147
 *
148
 * @since 3.0
149
 */
150
function _groups_page_menu_group_profile($hook, $type, $return, $params) {
151
	
152
	if (!elgg_in_context('group_profile') || !elgg_is_logged_in()) {
153
		return;
154
	}
155
	
156
	// Get the page owner entity
157
	$page_owner = elgg_get_page_owner_entity();
158
	if (!($page_owner instanceof ElggGroup)) {
159
		return;
160
	}
161
	
162
	if (!$page_owner->canEdit() || $page_owner->isPublicMembership()) {
163
		return;
164
	}
165
	
166
	$count = elgg_get_entities_from_relationship([
167
		'type' => 'user',
168
		'relationship' => 'membership_request',
169
		'relationship_guid' => $page_owner->guid,
170
		'inverse_relationship' => true,
171
		'count' => true,
172
	]);
173
174
	$text = elgg_echo('groups:membershiprequests');
175
	$title = $text;
176
	if ($count) {
177
		$title = elgg_echo('groups:membershiprequests:pending', [$count]);
178
	}
179
	
180
	$return[] = \ElggMenuItem::factory([
181
		'name' => 'membership_requests',
182
		'text' => $text,
183
		'badge' => $count ? $count : null,
184
		'title' => $title,
185
		'href' => "groups/requests/{$page_owner->guid}",
186
	]);
187
	
188
	return $return;
189
}
190
191
/**
192
 * Register menu items for the page menu
193
 *
194
 * @param string $hook
195
 * @param string $type
196
 * @param array  $return
197
 * @param array  $params
198
 * @return array
199
 *
200
 * @access private
201
 *
202
 * @since 3.0
203
 */
204
function _groups_page_menu($hook, $type, $return, $params) {
205
	
206
	if (elgg_get_context() !== 'groups') {
207
		return;
208
	}
209
	
210
	// Get the page owner entity
211
	$page_owner = elgg_get_page_owner_entity();
212
	if ($page_owner instanceof ElggGroup) {
213
		return;
214
	}
215
	
216
	$return[] = \ElggMenuItem::factory([
217
		'name' => 'groups:all',
218
		'text' => elgg_echo('groups:all'),
219
		'href' => 'groups/all',
220
	]);
221
222
	$user = elgg_get_logged_in_user_entity();
223
	if (!$user) {
224
		return $return;
225
	}
226
	
227
	$return[] = \ElggMenuItem::factory([
228
		'name' => 'groups:owned',
229
		'text' => elgg_echo('groups:owned'),
230
		'href' => "groups/owner/$user->username",
231
	]);
232
	
233
	$return[] = \ElggMenuItem::factory([
234
		'name' => 'groups:member',
235
		'text' => elgg_echo('groups:yours'),
236
		'href' => "groups/member/$user->username",
237
	]);
238
239
	$invitation_count = groups_get_invited_groups($user->guid, false, ['count' => true]);
240
241
	// Invitations
242
	$text = elgg_echo('groups:invitations');
243
	$title = $text;
244
	if ($invitation_count) {
245
		$title = elgg_echo('groups:invitations:pending', [$invitation_count]);
246
	}
247
248
	$return[] = \ElggMenuItem::factory([
249
		'name' => 'groups:user:invites',
250
		'text' => $text,
251
		'badge' => $invitation_count ? $invitation_count : null,
252
		'title' => $title,
253
		'href' => "groups/invitations/$user->username",
254
	]);
255
256
	return $return;
257
}
258
259
/**
260
 * Groups page handler
261
 *
262
 * URLs take the form of
263
 *  All groups:           groups/all
264
 *  User's owned groups:  groups/owner/<username>
265
 *  User's member groups: groups/member/<username>
266
 *  Group profile:        groups/profile/<guid>/<title>
267
 *  New group:            groups/add/<guid>
268
 *  Edit group:           groups/edit/<guid>
269
 *  Group invitations:    groups/invitations/<username>
270
 *  Invite to group:      groups/invite/<guid>
271
 *  Membership requests:  groups/requests/<guid>
272
 *  Group activity:       groups/activity/<guid>
273
 *  Group members:        groups/members/<guid>
274
 *
275
 * @param array $page Array of url segments for routing
276
 * @return bool
277
 */
278
function groups_page_handler($page) {
279
280
	if (!isset($page[0])) {
281
		$page[0] = 'all';
282
	}
283
284
	elgg_push_breadcrumb(elgg_echo('groups'), "groups/all");
285
286
	$vars = [];
287
	switch ($page[0]) {
288
		case 'add':
289
		case 'all':
290
		case 'owner':
291
		case 'search':
292
			echo elgg_view_resource("groups/{$page[0]}");
293
			break;
294
		case 'invitations':
295
		case 'member':
296
			echo elgg_view_resource("groups/{$page[0]}", [
297
				'username' => $page[1],
298
			]);
299
			break;
300
		case 'members':
301
			$vars['sort'] = elgg_extract('2', $page, 'alpha');
302
			$vars['guid'] = elgg_extract('1', $page);
303
			if (elgg_view_exists("resources/groups/members/{$vars['sort']}")) {
304
				echo elgg_view_resource("groups/members/{$vars['sort']}", $vars);
305
			} else {
306
				echo elgg_view_resource('groups/members', $vars);
307
			}
308
			break;
309
		case 'profile':
310
		case 'activity':
311
		case 'edit':
312
		case 'invite':
313
		case 'requests':
314
			echo elgg_view_resource("groups/{$page[0]}", [
315
				'guid' => $page[1],
316
			]);
317
			break;
318
		default:
319
			return false;
320
	}
321
	return true;
322
}
323
324
/**
325
 * Populates the ->getUrl() method for group objects
326
 *
327
 * @param string $hook
328
 * @param string $type
329
 * @param string $url
330
 * @param array  $params
331
 * @return string
332
 */
333
function groups_set_url($hook, $type, $url, $params) {
334
	$entity = $params['entity'];
335
	$title = elgg_get_friendly_title($entity->name);
336
	return "groups/profile/{$entity->guid}/$title";
337
}
338
339
/**
340
 * Add owner block link
341
 */
342 View Code Duplication
function groups_activity_owner_block_menu($hook, $type, $return, $params) {
343
	if (elgg_instanceof($params['entity'], 'group')) {
344
		if ($params['entity']->activity_enable != "no") {
345
			$url = "groups/activity/{$params['entity']->guid}";
346
			$item = new ElggMenuItem('activity', elgg_echo('groups:activity'), $url);
347
			$return[] = $item;
348
		}
349
	}
350
351
	return $return;
352
}
353
354
/**
355
 * Add links/info to entity menu particular to group entities
356
 */
357
function groups_entity_menu_setup($hook, $type, $return, $params) {
358
	if (elgg_in_context('widgets')) {
359
		return $return;
360
	}
361
362
	/* @var ElggGroup $entity */
363
	$entity = $params['entity'];
364
	$handler = elgg_extract('handler', $params, false);
365
	if ($handler != 'groups') {
366
		return $return;
367
	}
368
369
	/* @var ElggMenuItem $item */
370
	foreach ($return as $index => $item) {
371
		if (in_array($item->getName(), ['likes', 'unlike', 'edit', 'delete'])) {
372
			unset($return[$index]);
373
		}
374
	}
375
376
377
	// feature link
378
	if (elgg_is_admin_logged_in()) {
379
		$isFeatured = $entity->featured_group == "yes";
380
381
		$return[] = ElggMenuItem::factory([
382
			'name' => 'feature',
383
			'text' => elgg_echo("groups:makefeatured"),
384
			'href' => elgg_add_action_tokens_to_url("action/groups/featured?group_guid={$entity->guid}&action_type=feature"),
385
			'priority' => 300,
386
			'item_class' => $isFeatured ? 'hidden' : '',
387
			'deps' => 'groups/navigation',
388
		]);
389
390
		$return[] = ElggMenuItem::factory([
391
			'name' => 'unfeature',
392
			'text' => elgg_echo("groups:makeunfeatured"),
393
			'href' => elgg_add_action_tokens_to_url("action/groups/featured?group_guid={$entity->guid}&action_type=unfeature"),
394
			'priority' => 300,
395
			'item_class' => $isFeatured ? '' : 'hidden',
396
			'deps' => 'groups/navigation',
397
		]);
398
	}
399
400
	return $return;
401
}
402
403
/**
404
 * Add a remove user link to user hover menu when the page owner is a group
405
 */
406
function groups_user_entity_menu_setup($hook, $type, $return, $params) {
407
	if (elgg_is_logged_in()) {
408
		$group = elgg_get_page_owner_entity();
409
410
		// Check for valid group
411
		if (!elgg_instanceof($group, 'group')) {
412
			return $return;
413
		}
414
415
		$entity = $params['entity'];
416
417
		// Make sure we have a user and that user is a member of the group
418
		if (!elgg_instanceof($entity, 'user') || !$group->isMember($entity)) {
419
			return $return;
420
		}
421
422
		// Add remove link if we can edit the group, and if we're not trying to remove the group owner
423 View Code Duplication
		if ($group->canEdit() && $group->getOwnerGUID() != $entity->guid) {
1 ignored issue
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
424
			$return[] = ElggMenuItem::factory([
425
				'name' => 'removeuser',
426
				'href' => "action/groups/remove?user_guid={$entity->guid}&group_guid={$group->guid}",
427
				'text' => elgg_echo('groups:removeuser'),
428
				'icon' => 'user-times',
429
				'confirm' => true,
430
				'priority' => 999,
431
			]);
432
		}
433
	}
434
435
	return $return;
436
}
437
438
/**
439
 * Groups created so create an access list for it
440
 */
441
function groups_create_event_listener($event, $object_type, $object) {
442
	$ac_name = elgg_echo('groups:group') . ": " . $object->name;
443
	$ac_id = create_access_collection($ac_name, $object->guid);
444
	if ($ac_id) {
445
		$object->group_acl = $ac_id;
446
	} else {
447
		// delete group if access creation fails
448
		return false;
449
	}
450
451
	return true;
452
}
453
454
/**
455
 * Listen to group ownership changes and update group icon ownership
456
 * This will only move the source file, the actual icons are moved by
457
 * _elgg_filestore_move_icons()
458
 *
459
 * This operation is performed in an event listener to ensure that icons
460
 * are moved when ownership changes outside of the groups/edit action flow.
461
 *
462
 * @todo #4683 proposes that icons are owned by groups and not group owners
463
 * @see _elgg_filestore_move_icons()
464
 *
465
 * @param string    $event "update:after"
466
 * @param string    $type  "group"
467
 * @param ElggGroup $group Group entity
468
 * @return void
469
 */
470
function groups_update_event_listener($event, $type, $group) {
471
472
	/* @var $group \ElggGroup */
473
474
	$original_attributes = $group->getOriginalAttributes();
475
476
	if (!empty($original_attributes['owner_guid'])) {
477
		$previous_owner_guid = $original_attributes['owner_guid'];
478
479
		// Update owned metadata
480
		$metadata = elgg_get_metadata([
481
			'guid' => $group->guid,
482
			'metadata_owner_guids' => $previous_owner_guid,
483
			'limit' => 0,
484
		]);
485
486
		if ($metadata) {
487
			foreach ($metadata as $md) {
488
				$md->owner_guid = $group->owner_guid;
489
				$md->save();
490
			}
491
		}
492
	}
493
494
	if (!empty($original_attributes['name'])) {
495
		// update access collection name if group name changes
496
		$group_name = html_entity_decode($group->name, ENT_QUOTES, 'UTF-8');
497
		$ac_name = elgg_echo('groups:group') . ": " . $group_name;
498
		$acl = get_access_collection($group->group_acl);
499
		if ($acl) {
500
			$acl->name = $ac_name;
501
			$acl->save();
502
		}
503
	}
504
}
505
506
/**
507
 * Return the write access for the current group if the user has write access to it
508
 *
509
 * @elgg_plugin_hook access:collection:write all
510
 *
511
 * @param \Elgg\Hook $hook Hook
512
 * @return array
513
 */
514
function groups_write_acl_plugin_hook(\Elgg\Hook $hook) {
515
516
	$user_guid = $hook->getParam('user_id');
517
	$user = get_user($user_guid);
518
	if (!$user) {
519
		return;
520
	}
521
522
	$page_owner = elgg_get_page_owner_entity();
523
	if (!$page_owner instanceof ElggGroup) {
524
		return;
525
	}
526
527
	if (!$page_owner->canWriteToContainer($user_guid)) {
528
		return;
529
	}
530
531
	$allowed_access = [
532
		ACCESS_PRIVATE,
533
		$page_owner->group_acl,
534
	];
535
536
	if ($page_owner->getContentAccessMode() !== ElggGroup::CONTENT_ACCESS_MODE_MEMBERS_ONLY) {
537
		$allowed_access[] = ACCESS_LOGGED_IN;
538
		if (!elgg_get_config('walled_garden')) {
539
			$allowed_access[] = ACCESS_PUBLIC;
540
		}
541
	}
542
543
	$write_acls = $hook->getValue();
544
545
	// add write access to the group
546
	$collection = get_access_collection($page_owner->group_acl);
547
	if ($collection) {
548
		$write_acls[$page_owner->group_acl] = $collection->getDisplayName();
549
	}
550
551
	foreach (array_keys($write_acls) as $access_id) {
552
		if (!in_array($access_id, $allowed_access)) {
553
			unset($write_acls[$access_id]);
554
		}
555
	}
556
557
	return $write_acls;
558
}
559
560
/**
561
 * Return the write access for the current group if the user has write access to it
562
 *
563
 * @elgg_plugin_hook access_collection:display_name access_collection
564
 *
565
 * @param \Elgg\Hook $hook Hook
566
 * @return array
567
 */
568
function groups_set_access_collection_name(\Elgg\Hook $hook) {
569
570
	$access_collection = $hook->getParam('access_collection');
571
	if (!$access_collection instanceof ElggAccessCollection) {
572
		return;
573
	}
574
575
	$owner = $access_collection->getOwnerEntity();
576
	if (!$owner instanceof ElggGroup) {
577
		return;
578
	}
579
	
580
	$page_owner = elgg_get_page_owner_entity();
581
582
	if ($page_owner && $page_owner->guid == $owner->guid) {
583
		return elgg_echo('groups:acl:in_context');
584
	}
585
586
	if ($owner->canWriteToContainer()) {
587
		return elgg_echo('groups:acl', [$owner->getDisplayName()]);
588
	}
589
}
590
591
/**
592
 * Listens to a group join event and adds a user to the group's access control
593
 *
594
 */
595 View Code Duplication
function groups_user_join_event_listener($event, $object_type, $object) {
596
597
	$group = $object['group'];
598
	$user = $object['user'];
599
	$acl = $group->group_acl;
600
601
	add_user_to_access_collection($user->guid, $acl);
602
603
	return true;
604
}
605
606
/**
607
 * Make sure users are added to the access collection
608
 */
609
function groups_access_collection_override($hook, $entity_type, $returnvalue, $params) {
610
	if (isset($params['collection'])) {
611
		if (elgg_instanceof(get_entity($params['collection']->owner_guid), 'group')) {
612
			return true;
613
		}
614
	}
615
}
616
617
/**
618
 * Listens to a group leave event and removes a user from the group's access control
619
 *
620
 */
621 View Code Duplication
function groups_user_leave_event_listener($event, $object_type, $object) {
622
623
	$group = $object['group'];
624
	$user = $object['user'];
625
	$acl = $group->group_acl;
626
627
	remove_user_from_access_collection($user->guid, $acl);
628
629
	return true;
630
}
631
632
/**
633
 * The default access for members only content is this group only. This makes
634
 * for better display of access (can tell it is group only), but does not change
635
 * access to the content.
636
 *
637
 * @param string $hook   Hook name
638
 * @param string $type   Hook type
639
 * @param int    $access Current default access
640
 * @return int
641
 */
642
function groups_access_default_override($hook, $type, $access) {
643
	$page_owner = elgg_get_page_owner_entity();
644
645
	if ($page_owner instanceof ElggGroup) {
646
		if ($page_owner->getContentAccessMode() == ElggGroup::CONTENT_ACCESS_MODE_MEMBERS_ONLY) {
647
			$access = $page_owner->group_acl;
648
		}
649
	}
650
651
	return $access;
652
}
653
654
/**
655
 * Grabs groups by invitations
656
 * Have to override all access until there's a way override access to getter functions.
657
 *
658
 * @param int   $user_guid    The user's guid
659
 * @param bool  $return_guids Return guids rather than ElggGroup objects
660
 * @param array $options      Additional options
661
 *
662
 * @return mixed ElggGroups or guids depending on $return_guids, or count
663
 */
664
function groups_get_invited_groups($user_guid, $return_guids = false, $options = []) {
665
666
	$ia = elgg_set_ignore_access(true);
667
668
	$defaults = [
669
		'relationship' => 'invited',
670
		'relationship_guid' => (int) $user_guid,
671
		'inverse_relationship' => true,
672
		'limit' => 0,
673
	];
674
675
	$options = array_merge($defaults, $options);
676
	$groups = elgg_get_entities_from_relationship($options);
677
678
	elgg_set_ignore_access($ia);
679
680
	if ($return_guids) {
681
		$guids = [];
682
		foreach ($groups as $group) {
683
			$guids[] = $group->getGUID();
684
		}
685
686
		return $guids;
687
	}
688
689
	return $groups;
690
}
691
692
/**
693
 * Join a user to a group, add river event, clean-up invitations
694
 *
695
 * @param ElggGroup $group
696
 * @param ElggUser  $user
697
 * @return bool
698
 */
699
function groups_join_group($group, $user) {
700
701
	// access ignore so user can be added to access collection of invisible group
702
	$ia = elgg_set_ignore_access(true);
703
	$result = $group->join($user);
704
	elgg_set_ignore_access($ia);
705
706
	if ($result) {
707
		// flush user's access info so the collection is added
708
		get_access_list($user->guid, 0, true);
709
710
		// Remove any invite or join request flags
711
		remove_entity_relationship($group->guid, 'invited', $user->guid);
712
		remove_entity_relationship($user->guid, 'membership_request', $group->guid);
713
714
		elgg_create_river_item([
715
			'view' => 'river/relationship/member/create',
716
			'action_type' => 'join',
717
			'subject_guid' => $user->guid,
718
			'object_guid' => $group->guid,
719
		]);
720
721
		return true;
722
	}
723
724
	return false;
725
}
726
727
/**
728
 * Function to use on groups for access. It will house private, loggedin, public,
729
 * and the group itself. This is when you don't want other groups or access lists
730
 * in the access options available.
731
 *
732
 * @return array
733
 */
734
function group_access_options($group) {
735
736
	$access_array = [
737
		ACCESS_PRIVATE => elgg_echo('PRIVATE'),
738
		ACCESS_LOGGED_IN => elgg_echo('LOGGED_IN'),
739
	];
740
741
	if (!elgg_get_config('walled_garden')) {
742
		$access_array[ACCESS_PUBLIC] = elgg_echo('PUBLIC');
743
	}
744
745
	$collection = get_access_collection($group->group_acl);
746
	if ($collection) {
747
		$access_array[$collection->id] = $collection->getDisplayName();
748
	}
749
	
750
	return $access_array;
751
}
752
753
function activity_profile_menu($hook, $entity_type, $return_value, $params) {
754
755
	if (!$params['owner'] instanceof ElggGroup
756
			|| elgg_get_plugin_setting('allow_activity', 'groups') === 'no') {
757
		return;
758
	}
759
760
	$return_value[] = [
761
		'text' => elgg_echo('groups:activity'),
762
		'href' => "groups/activity/{$params['owner']->guid}"
763
	];
764
	return $return_value;
765
}
766
767
/**
768
 * Parse ECML on group profiles
769
 */
770
function groupprofile_ecml_views_hook($hook, $entity_type, $return_value, $params) {
771
	$return_value['groups/groupprofile'] = elgg_echo('groups:ecml:groupprofile');
772
773
	return $return_value;
774
}
775
776
/**
777
 * Process upgrades for the groups plugin
778
 */
779
function groups_run_upgrades() {
780
	$path = __DIR__ . '/upgrades/';
781
	$files = elgg_get_upgrade_files($path);
782
	foreach ($files as $file) {
783
		include "$path{$file}";
784
	}
785
}
786
787
/**
788
 * Runs unit tests for groups
789
 *
790
 * @return array
791
 */
792
function groups_test($hook, $type, $value, $params) {
793
	$value[] = elgg_get_plugins_path() . 'groups/tests/write_access.php';
794
	return $value;
795
}
796
797
/**
798
 * Setup invitation request actions
799
 *
800
 * @param string $hook   "register"
801
 * @param string $type   "menu:invitationrequest"
802
 * @param array  $menu   Menu items
803
 * @param array  $params Hook params
804
 * @return array
805
 */
806
function groups_invitationrequest_menu_setup($hook, $type, $menu, $params) {
807
808
	$group = elgg_extract('entity', $params);
809
	$user = elgg_extract('user', $params);
810
811
	if (!$group instanceof \ElggGroup) {
812
		return $menu;
813
	}
814
815
	if (!$user instanceof \ElggUser || !$user->canEdit()) {
816
		return $menu;
817
	}
818
819
	$accept_url = elgg_http_add_url_query_elements('action/groups/join', [
820
		'user_guid' => $user->guid,
821
		'group_guid' => $group->guid,
822
	]);
823
824
	$menu[] = \ElggMenuItem::factory([
825
		'name' => 'accept',
826
		'href' => $accept_url,
827
		'is_action' => true,
828
		'text' => elgg_echo('accept'),
829
		'link_class' => 'elgg-button elgg-button-submit',
830
		'is_trusted' => true,
831
	]);
832
833
	$delete_url = elgg_http_add_url_query_elements('action/groups/killinvitation', [
834
		'user_guid' => $user->guid,
835
		'group_guid' => $group->guid,
836
	]);
837
838
	$menu[] = \ElggMenuItem::factory([
839
		'name' => 'delete',
840
		'href' => $delete_url,
841
		'is_action' => true,
842
		'confirm' => elgg_echo('groups:invite:remove:check'),
843
		'text' => elgg_echo('delete'),
844
		'link_class' => 'elgg-button elgg-button-delete mlm',
845
	]);
846
847
	return $menu;
848
}
849
850
/**
851
 * Setup group members tabs
852
 *
853
 * @param string         $hook   "register"
854
 * @param string         $type   "menu:groups_members"
855
 * @param ElggMenuItem[] $menu   Menu items
856
 * @param array          $params Hook params
857
 *
858
 * @return void|ElggMenuItem[]
859
 */
860
function groups_members_menu_setup($hook, $type, $menu, $params) {
861
862
	$entity = elgg_extract('entity', $params);
863
	if (empty($entity) || !($entity instanceof ElggGroup)) {
864
		return;
865
	}
866
867
	$menu[] = ElggMenuItem::factory([
868
		'name' => 'alpha',
869
		'text' => elgg_echo('sort:alpha'),
870
		'href' => "groups/members/{$entity->getGUID()}",
871
		'priority' => 100
872
	]);
873
874
	$menu[] = ElggMenuItem::factory([
875
		'name' => 'newest',
876
		'text' => elgg_echo('sort:newest'),
877
		'href' => "groups/members/{$entity->getGUID()}/newest",
878
		'priority' => 200
879
	]);
880
881
	return $menu;
882
}
883
884
/**
885
 * Returns menu items to be registered in the title menu of the group profile
886
 *
887
 * @param string         $hook   "profile_buttons"
888
 * @param string         $type   "group"
889
 * @param ElggMenuItem[] $items  Buttons
890
 * @param array          $params Hook params
891
 * @return ElggMenuItem[]
892
 */
893
function groups_prepare_profile_buttons($hook, $type, $items, $params) {
894
895
	$group = elgg_extract('entity', $params);
896
	if (!$group instanceof ElggGroup) {
897
		return;
898
	}
899
900
	$actions = [];
901
902
	if ($group->canEdit()) {
903
		// group owners can edit the group and invite new members
904
		$actions['groups:edit'] = "groups/edit/{$group->guid}";
905
		$actions['groups:invite'] = "groups/invite/{$group->guid}";
906
	}
907
908
	$user = elgg_get_logged_in_user_entity();
909
	if ($user && $group->isMember($user)) {
910
		if ($group->owner_guid != $user->guid) {
911
			// a member can leave a group if he/she doesn't own it
912
			$actions['groups:leave'] = "action/groups/leave?group_guid={$group->guid}";
913
		}
914
	} else if ($user) {
915
		$url = "action/groups/join?group_guid={$group->guid}";
916
		if ($group->isPublicMembership() || $group->canEdit()) {
917
			// admins can always join
918
			// non-admins can join if membership is public
919
			$actions['groups:join'] = $url;
920
		} else {
921
			// request membership
922
			$actions['groups:joinrequest'] = $url;
923
		}
924
	}
925
926
	foreach ($actions as $action => $url) {
927
		$items[] = ElggMenuItem::factory([
928
			'name' => $action,
929
			'href' => elgg_normalize_url($url),
930
			'text' => elgg_echo($action),
931
			'is_action' => 0 === strpos($url, 'action'),
932
			'link_class' => 'elgg-button elgg-button-action',
933
		]);
934
	}
935
936
	return $items;
937
}
938
939
/**
940
 * Helper handler to correctly resolve page owners on group routes
941
 *
942
 * @see default_page_owner_handler()
943
 *
944
 * @param string $hook   "page_owner"
945
 * @param string $type   "system"
946
 * @param int    $return Page owner guid
947
 * @param array  $params Hook params
948
 * @return int|void
949
 */
950
function groups_default_page_owner_handler($hook, $type, $return, $params) {
951
952
	if ($return) {
953
		return;
954
	}
955
956
	$segments = _elgg_services()->request->getUrlSegments();
957
	$identifier = array_shift($segments);
958
959
	if ($identifier !== 'groups') {
960
		return;
961
	}
962
963
	$page = array_shift($segments);
964
965
	switch ($page) {
966
		case 'add' :
967
			$guid = array_shift($segments);
968
			if (!$guid) {
969
				$guid = elgg_get_logged_in_user_guid();
970
			}
971
			return $guid;
972
973
		case 'edit':
974
		case 'profile' :
975
		case 'activity' :
976
		case 'invite' :
977
		case 'requests' :
978
		case 'members' :
979
		case 'profile' :
980
			$guid = array_shift($segments);
981
			if (!$guid) {
982
				return;
983
			}
984
			return $guid;
985
986
		case 'member' :
987
		case 'owner' :
988
		case 'invitations':
989
			$username = array_shift($segments);
990
			if ($username) {
991
				$user = get_user_by_username($username);
992
			} else {
993
				$user = elgg_get_logged_in_user_entity();
994
			}
995
			if (!$user) {
996
				return;
997
			}
998
			return $user->guid;
999
	}
1000
}
1001
1002
/**
1003
 * Setup filter tabs on /groups/all page
1004
 *
1005
 * @param string         $hook   "register"
1006
 * @param string         $type   "menu:filter:groups/all"
1007
 * @param ElggMenuItem[] $return Menu
1008
 * @param array          $params Hook params
1009
 * @return ElggMenuItem[]
1010
 */
1011
function groups_setup_filter_tabs($hook, $type, $return, $params) {
1012
1013
	$filter_value = elgg_extract('filter_value', $params);
1014
1015
	$return[] = ElggMenuItem::factory([
1016
		'name' => 'newest',
1017
		'text' => elgg_echo('sort:newest'),
1018
		'href' => 'groups/all?filter=newest',
1019
		'priority' => 200,
1020
		'selected' => $filter_value == 'newest',
1021
	]);
1022
1023
	$return[] = ElggMenuItem::factory([
1024
		'name' => 'alpha',
1025
		'text' => elgg_echo('sort:alpha'),
1026
		'href' => 'groups/all?filter=alpha',
1027
		'priority' => 250,
1028
		'selected' => $filter_value == 'alpha',
1029
	]);
1030
1031
	$return[] = ElggMenuItem::factory([
1032
		'name' => 'popular',
1033
		'text' => elgg_echo('sort:popular'),
1034
		'href' => 'groups/all?filter=popular',
1035
		'priority' => 300,
1036
		'selected' => $filter_value == 'popular',
1037
	]);
1038
1039
	$return[] = ElggMenuItem::factory([
1040
		'name' => 'featured',
1041
		'text' => elgg_echo('groups:featured'),
1042
		'href' => 'groups/all?filter=featured',
1043
		'priority' => 400,
1044
		'selected' => $filter_value == 'featured',
1045
	]);
1046
	
1047
	return $return;
1048
}
1049
1050
/**
1051
 * Add 'original' to group icon sizes
1052
 *
1053
 * @elgg_plugin_hook entity:icon:sizes group
1054
 *
1055
 * @param \Elgg\Hook $hook Hook
1056
 * @return array
1057
 */
1058
function groups_set_icon_sizes(\Elgg\Hook $hook) {
1059
1060
	$sizes = $hook->getValue();
1061
	$sizes['original'] = [];
1062
1063
	return $sizes;
1064
}
1065