Passed
Push — master ( 3457e5...a8ff25 )
by Jeroen
64:07
created

groups_default_page_owner_handler()   D

Complexity

Conditions 17
Paths 29

Size

Total Lines 48
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 306

Importance

Changes 0
Metric Value
cc 17
eloc 34
nc 29
nop 4
dl 0
loc 48
ccs 0
cts 33
cp 0
crap 306
rs 4.9412
c 0
b 0
f 0

How to fix   Complexity   

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 groups plugin
4
 *
5
 * @package ElggGroups
6
 */
7
8
/**
9
 * Initialize the groups plugin
10
 *
11
 * @return void
12
 */
13
function groups_init() {
14
	
15 31
	elgg_extend_view('object/elements/imprint/contents', 'groups/imprint/member_count');
16 31
	elgg_extend_view('object/elements/imprint/contents', 'groups/imprint/membership_type');
17
	
18
	// Set up the menu
19 31
	$item = new ElggMenuItem('groups', elgg_echo('groups'), 'groups/all');
20 31
	elgg_register_menu_item('site', $item);
21
22
	// Register URL handlers for groups
23 31
	elgg_register_plugin_hook_handler('entity:url', 'group', 'groups_set_url');
24 31
	elgg_register_plugin_hook_handler('entity:icon:sizes', 'group', 'groups_set_icon_sizes');
25
26
	// group entity menu
27 31
	elgg_register_plugin_hook_handler('register', 'menu:entity', 'groups_entity_menu_setup');
28
29
	// group user hover menu
30 31
	elgg_register_plugin_hook_handler('register', 'menu:user_hover', 'groups_user_entity_menu_setup');
31
32
	// invitation request actions
33 31
	elgg_register_plugin_hook_handler('register', 'menu:invitationrequest', 'groups_invitationrequest_menu_setup');
34
35
	// group members tabs
36 31
	elgg_register_plugin_hook_handler('register', 'menu:groups_members', 'groups_members_menu_setup');
37
	
38
	// topbar menu
39 31
	elgg_register_plugin_hook_handler('register', 'menu:topbar', '_groups_topbar_menu_setup');
40
41
	//extend some views
42 31
	elgg_extend_view('elgg.css', 'groups/groups.css');
43
44
	// Access permissions
45 31
	elgg_register_plugin_hook_handler('access:collections:write', 'all', 'groups_write_acl_plugin_hook', 600);
46 31
	elgg_register_plugin_hook_handler('default', 'access', 'groups_access_default_override');
47 31
	elgg_register_plugin_hook_handler('access_collection:name', 'access_collection', 'groups_set_access_collection_name');
48
49
	// allow ecml in profiles
50 31
	elgg_register_plugin_hook_handler('get_views', 'ecml', 'groupprofile_ecml_views_hook');
51
52
	// Register a handler for create groups
53 31
	elgg_register_event_handler('create', 'group', 'groups_create_event_listener');
54 31
	elgg_register_event_handler('update:after', 'group', 'groups_update_event_listener');
55
56 31
	elgg_register_event_handler('join', 'group', 'groups_user_join_event_listener');
57 31
	elgg_register_event_handler('leave', 'group', 'groups_user_leave_event_listener');
58
59
	// allow to be liked
60 31
	elgg_register_plugin_hook_handler('likes:is_likable', 'group:', 'Elgg\Values::getTrue');
61
62
	// Help core resolve page owner guids from group routes
63
	// Registered with an earlier priority to be called before default_page_owner_handler()
64 31
	elgg_register_plugin_hook_handler('page_owner', 'system', 'groups_default_page_owner_handler', 400);
65
66
	// Setup filter tabs on /groups/all page
67 31
	elgg_register_plugin_hook_handler('register', 'menu:filter:groups/all', 'groups_setup_filter_tabs');
68
69 31
	elgg_register_plugin_hook_handler('register', 'menu:page', '_groups_page_menu_group_profile');
70 31
	elgg_register_plugin_hook_handler('register', 'menu:page', '_groups_page_menu');
71 31
	elgg_register_plugin_hook_handler('register', 'menu:title', '_groups_title_menu');
72 31
}
73
74
/**
75
 * This function loads a set of default fields into the profile, then triggers
76
 * a hook letting other plugins to edit add and delete fields.
77
 *
78
 * Note: This is a system:init event triggered function and is run at a super
79
 * low priority to guarantee that it is called after all other plugins have
80
 * initialized.
81
 *
82
 * @return void
83
 */
84
function groups_fields_setup() {
85
86
	$profile_defaults = [
87 31
		'description' => 'longtext',
88
		'briefdescription' => 'text',
89
		'interests' => 'tags',
90
	];
91
92 31
	$profile_defaults = elgg_trigger_plugin_hook('profile:fields', 'group', null, $profile_defaults);
93
94 31
	elgg_set_config('group', $profile_defaults);
95
96
	// register any tag metadata names
97 31
	foreach ($profile_defaults as $name => $type) {
98 31
		if ($type == 'tags') {
99 31
			elgg_register_tag_metadata_name($name);
100
101
			// only shows up in search but why not just set this in en.php as doing it here
102
			// means you cannot override it in a plugin
103 31
			add_translation(get_current_language(), ["tag_names:$name" => elgg_echo("groups:$name")]);
104
		}
105
	}
106 31
}
107
108
/**
109
 * Register menu items for the page menu
110
 *
111
 * @param string         $hook   'register'
112
 * @param string         $type   'menu:page'
113
 * @param ElggMenuItem[] $return current return value
114
 * @param array          $params supplied params
115
 *
116
 * @return void|ElggMenuItem[]
117
 *
118
 * @access private
119
 * @since 3.0
120
 */
121
function _groups_page_menu_group_profile($hook, $type, $return, $params) {
122
	
123 1
	if (!elgg_in_context('group_profile') || !elgg_is_logged_in()) {
124 1
		return;
125
	}
126
	
127
	// Get the page owner entity
128
	$page_owner = elgg_get_page_owner_entity();
129
	if (!($page_owner instanceof ElggGroup)) {
130
		return;
131
	}
132
	
133
	if (!$page_owner->canEdit() || $page_owner->isPublicMembership()) {
134
		return;
135
	}
136
	
137
	$count = elgg_get_entities([
138
		'type' => 'user',
139
		'relationship' => 'membership_request',
140
		'relationship_guid' => $page_owner->guid,
141
		'inverse_relationship' => true,
142
		'count' => true,
143
	]);
144
145
	$text = elgg_echo('groups:membershiprequests');
146
	$title = $text;
147
	if ($count) {
148
		$title = elgg_echo('groups:membershiprequests:pending', [$count]);
149
	}
150
	
151
	$return[] = \ElggMenuItem::factory([
152
		'name' => 'membership_requests',
153
		'text' => $text,
154
		'badge' => $count ? $count : null,
155
		'title' => $title,
156
		'href' => "groups/requests/{$page_owner->guid}",
157
	]);
158
	
159
	return $return;
160
}
161
162
/**
163
 * Register menu items for the page menu
164
 *
165
 * @param string         $hook   'register'
166
 * @param string         $type   'menu:page'
167
 * @param ElggMenuItem[] $return current return value
168
 * @param array          $params supplied params
169
 *
170
 * @return void|ElggMenuItem[]
171
 *
172
 * @access private
173
 * @since 3.0
174
 */
175
function _groups_page_menu($hook, $type, $return, $params) {
176
	
177 1
	if (elgg_get_context() !== 'groups') {
178 1
		return;
179
	}
180
	
181
	// Get the page owner entity
182
	$page_owner = elgg_get_page_owner_entity();
183
	if ($page_owner instanceof ElggGroup) {
184
		return;
185
	}
186
	
187
	$return[] = \ElggMenuItem::factory([
188
		'name' => 'groups:all',
189
		'text' => elgg_echo('groups:all'),
190
		'href' => 'groups/all',
191
	]);
192
193
	$user = elgg_get_logged_in_user_entity();
194
	if (!$user) {
195
		return $return;
196
	}
197
	
198
	$return[] = \ElggMenuItem::factory([
199
		'name' => 'groups:owned',
200
		'text' => elgg_echo('groups:owned'),
201
		'href' => "groups/owner/$user->username",
202
	]);
203
	
204
	$return[] = \ElggMenuItem::factory([
205
		'name' => 'groups:member',
206
		'text' => elgg_echo('groups:yours'),
207
		'href' => "groups/member/$user->username",
208
	]);
209
210
	$invitation_count = groups_get_invited_groups($user->guid, false, ['count' => true]);
211
212
	// Invitations
213
	$text = elgg_echo('groups:invitations');
214
	$title = $text;
215
	if ($invitation_count) {
216
		$title = elgg_echo('groups:invitations:pending', [$invitation_count]);
217
	}
218
219
	$return[] = \ElggMenuItem::factory([
220
		'name' => 'groups:user:invites',
221
		'text' => $text,
222
		'badge' => $invitation_count ?: null,
223
		'title' => $title,
224
		'href' => "groups/invitations/$user->username",
225
	]);
226
227
	return $return;
228
}
229
230
/**
231
 * Populates the ->getUrl() method for group objects
232
 *
233
 * @param string $hook   'entity:url'
234
 * @param string $type   'group'
235
 * @param string $url    current return value
236
 * @param array  $params supplied params
237
 *
238
 * @return void|string
239
 */
240
function groups_set_url($hook, $type, $url, $params) {
241
	
242
	$entity = elgg_extract('entity', $params);
243
	if (!$entity instanceof ElggGroup) {
244
		return;
245
	}
246
	
247
	$title = elgg_get_friendly_title($entity->getDisplayName());
248
	return "groups/profile/{$entity->guid}/$title";
249
}
250
251
/**
252
 * Returns a menu item for leaving a group
253
 *
254
 * @param \ElggGroup $group Group to leave
255
 * @param \ElggUser  $user  User to check leave action for
256
 *
257
 * @return \ElggMenuItem|false
258
 */
259
function groups_get_group_leave_menu_item(\ElggGroup $group, $user = null) {
260
	if (!$group instanceof \ElggGroup) {
0 ignored issues
show
introduced by
The condition ! $group instanceof ElggGroup can never be true.
Loading history...
261
		return false;
262
	}
263
	
264
	if (!$user instanceof ElggUser) {
265
		$user = elgg_get_logged_in_user_entity();
266
	}
267
	
268
	if (!$user instanceof ElggUser) {
269
		return false;
270
	}
271
	
272
	if (!$group->isMember($user) || ($group->owner_guid === $user->guid)) {
273
		// a member can leave a group if he/she doesn't own it
274
		return false;
275
	}
276
	
277
	return \ElggMenuItem::factory([
278
		'name' => 'groups:leave',
279
		'icon' => 'sign-out',
280
		'text' => elgg_echo('groups:leave'),
281
		'href' => elgg_http_add_url_query_elements('action/groups/leave', [
282
			'group_guid' => $group->guid,
283
			'user_guid' => $user->guid,
284
		]),
285
		'is_action' => true,
286
	]);
287
}
288
289
/**
290
 * Returns a menu item for joining a group
291
 *
292
 * @param \ElggGroup $group Group to leave
293
 * @param \ElggUser  $user  User to check leave action for
294
 *
295
 * @return \ElggMenuItem|false
296
 */
297
function groups_get_group_join_menu_item(\ElggGroup $group, $user = null) {
298
	if (!$group instanceof \ElggGroup) {
0 ignored issues
show
introduced by
The condition ! $group instanceof ElggGroup can never be true.
Loading history...
299
		return false;
300
	}
301
	
302
	if (!$user instanceof ElggUser) {
303
		$user = elgg_get_logged_in_user_entity();
304
	}
305
	
306
	if (!$user instanceof ElggUser) {
307
		return false;
308
	}
309
	
310
	if ($group->isMember($user)) {
311
		return false;
312
	}
313
	
314
	$menu_name = 'groups:joinrequest';
315
	if ($group->isPublicMembership() || $group->canEdit()) {
316
		// admins can always join
317
		// non-admins can join if membership is public
318
		$menu_name = 'groups:join';
319
	}
320
	
321
	return \ElggMenuItem::factory([
322
		'name' => $menu_name,
323
		'icon' => 'sign-in',
324
		'text' => elgg_echo($menu_name),
325
		'href' => elgg_http_add_url_query_elements('action/groups/join', [
326
			'group_guid' => $group->guid,
327
			'user_guid' => $user->guid,
328
		]),
329
		'is_action' => true,
330
	]);
331
}
332
333
/**
334
 * Add links/info to entity menu particular to group entities
335
 *
336
 * @param string         $hook   'register'
337
 * @param string         $type   'menu:entity'
338
 * @param ElggMenuItem[] $return current return value
339
 * @param array          $params supplied params
340
 *
341
 * @return void|ElggMenuItem[]
342
 */
343
function groups_entity_menu_setup($hook, $type, $return, $params) {
344 1
	$entity = elgg_extract('entity', $params);
345 1
	if (!($entity instanceof \ElggGroup)) {
346 1
		return;
347
	}
348
	
349 1
	$user = elgg_get_logged_in_user_entity();
350 1
	if (empty($user)) {
351 1
		return;
352
	}
353
	
354
	$group_join = groups_get_group_join_menu_item($entity, $user);
355
	if (!empty($group_join)) {
356
		$return[] = $group_join;
357
	}
358
	
359
	$group_leave = groups_get_group_leave_menu_item($entity, $user);
360
	if (!empty($group_leave)) {
361
		$return[] = $group_leave;
362
	}
363
		
364
	if ($user->isAdmin()) {
365
		$isFeatured = $entity->featured_group === "yes";
366
	
367
		$return[] = ElggMenuItem::factory([
368
			'name' => 'feature',
369
			'icon' => 'arrow-up',
370
			'text' => elgg_echo('groups:makefeatured'),
371
			'href' => "action/groups/featured?group_guid={$entity->guid}&action_type=feature",
372
			'is_action' => true,
373
			'item_class' => $isFeatured ? 'hidden' : '',
374
			'data-toggle' => 'unfeature',
375
		]);
376
	
377
		$return[] = ElggMenuItem::factory([
378
			'name' => 'unfeature',
379
			'icon' => 'arrow-down',
380
			'text' => elgg_echo('groups:makeunfeatured'),
381
			'href' => "action/groups/featured?group_guid={$entity->guid}&action_type=unfeature",
382
			'is_action' => true,
383
			'item_class' => $isFeatured ? '' : 'hidden',
384
			'data-toggle' => 'feature',
385
		]);
386
	}
387
	
388
	return $return;
389
}
390
391
/**
392
 * Add a remove user link to user hover menu when the page owner is a group
393
 *
394
 * @param string         $hook   'register'
395
 * @param string         $type   'menu:user_hover'
396
 * @param ElggMenuItem[] $return current return value
397
 * @param array          $params supplied params
398
 *
399
 * @return void|ElggMenuItem[]
400
 */
401
function groups_user_entity_menu_setup($hook, $type, $return, $params) {
402 1
	$group = elgg_get_page_owner_entity();
403
404 1
	if (!($group instanceof \ElggGroup) || !$group->canEdit()) {
405 1
		return;
406
	}
407
408
	$entity = elgg_extract('entity', $params);
409
410
	// Make sure we have a user and that user is a member of the group
411
	if (!($entity instanceof \ElggUser) || !$group->isMember($entity)) {
412
		return;
413
	}
414
415
	// Check if we are looking at the group owner
416
	if ($group->owner_guid === $entity->guid) {
417
		return;
418
	}
419
	
420
	$return[] = ElggMenuItem::factory([
421
		'name' => 'removeuser',
422
		'href' => "action/groups/remove?user_guid={$entity->guid}&group_guid={$group->guid}",
423
		'text' => elgg_echo('groups:removeuser'),
424
		'icon' => 'user-times',
425
		'confirm' => true,
426
		'priority' => 999,
427
	]);
428
429
	return $return;
430
}
431
432
/**
433
 * Groups created so create an access list for it
434
 *
435
 * @param string    $event  'create'
436
 * @param string    $type   'group'
437
 * @param ElggGroup $object the new group
438
 *
439
 * @return bool
440
 */
441
function groups_create_event_listener($event, $type, $object) {
442
443
	// ensure that user has sufficient permissions to update group metadata
444
	// prior to joining the group
445 13
	$ia = elgg_set_ignore_access(true);
446
447 13
	$ac_name = elgg_echo('groups:group') . ": " . $object->name;
448 13
	$ac_id = create_access_collection($ac_name, $object->guid, 'group_acl');
449
	
450 13
	elgg_set_ignore_access($ia);
451
452 13
	return (bool) $ac_id; // delete the group if acl creation fails
453
}
454
455
/**
456
 * Listen to group ownership changes and update group icon ownership
457
 * This will only move the source file, the actual icons are moved by
458
 * _elgg_filestore_move_icons()
459
 *
460
 * This operation is performed in an event listener to ensure that icons
461
 * are moved when ownership changes outside of the groups/edit action flow.
462
 *
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 = _groups_get_group_acl($group);
499
		if ($acl) {
0 ignored issues
show
introduced by
The condition $acl can never be true.
Loading history...
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
 * @param \Elgg\Hook $hook 'access:collection:write' 'all'
510
 * @return void|array
511
 */
512
function groups_write_acl_plugin_hook(\Elgg\Hook $hook) {
513
514 5
	$user_guid = $hook->getParam('user_id');
515 5
	$user = get_user($user_guid);
516 5
	if (!$user) {
0 ignored issues
show
introduced by
The condition ! $user can never be false.
Loading history...
517
		return;
518
	}
519
520 5
	$page_owner = elgg_get_page_owner_entity();
521 5
	if (!$page_owner instanceof ElggGroup) {
522 4
		return;
523
	}
524
525 1
	if (!$page_owner->canWriteToContainer($user_guid)) {
526 1
		return;
527
	}
528
529 1
	$allowed_access = [ACCESS_PRIVATE];
530 1
	$acl = _groups_get_group_acl($page_owner);
531 1
	if ($acl) {
532 1
		$allowed_access[] = $acl->id;
533
	}
534
535 1
	if ($page_owner->getContentAccessMode() !== ElggGroup::CONTENT_ACCESS_MODE_MEMBERS_ONLY) {
536 1
		$allowed_access[] = ACCESS_LOGGED_IN;
537 1
		if (!elgg_get_config('walled_garden')) {
538 1
			$allowed_access[] = ACCESS_PUBLIC;
539
		}
540
	}
541
542 1
	$write_acls = $hook->getValue();
543
544
	// add write access to the group
545 1
	if ($acl) {
546 1
		$write_acls[$acl->id] = $acl->getDisplayName();
547
	}
548
549 1
	foreach (array_keys($write_acls) as $access_id) {
550 1
		if (!in_array($access_id, $allowed_access)) {
551 1
			unset($write_acls[$access_id]);
552
		}
553
	}
554
555 1
	return $write_acls;
556
}
557
558
/**
559
 * Return the write access for the current group if the user has write access to it
560
 *
561
 * @param \Elgg\Hook $hook 'access_collection:display_name' 'access_collection'
562
 * @return void|string
563
 */
564
function groups_set_access_collection_name(\Elgg\Hook $hook) {
565
566 4
	$access_collection = $hook->getParam('access_collection');
567 4
	if (!$access_collection instanceof ElggAccessCollection) {
568
		return;
569
	}
570
571 4
	$owner = $access_collection->getOwnerEntity();
572 4
	if (!$owner instanceof ElggGroup) {
0 ignored issues
show
introduced by
The condition ! $owner instanceof ElggGroup can never be false.
Loading history...
573 4
		return;
574
	}
575
	
576 1
	$page_owner = elgg_get_page_owner_entity();
577
578 1
	if ($page_owner && $page_owner->guid == $owner->guid) {
579 1
		return elgg_echo('groups:acl:in_context');
580
	}
581
582
	if ($owner->canWriteToContainer()) {
583
		return elgg_echo('groups:acl', [$owner->getDisplayName()]);
584
	}
585
}
586
587
/**
588
 * Perform actions when a user joins a group
589
 *
590
 * @param string $event       'join'
591
 * @param string $object_type 'group'
592
 * @param array  $params      supplied params
593
 *
594
 * @return void
595
 */
596
function groups_user_join_event_listener($event, $object_type, $params) {
597 8
	$group = elgg_extract('group', $params);
598 8
	$user = elgg_extract('user', $params);
599 8
	if (!$group instanceof ElggGroup || !$user instanceof ElggUser) {
600
		return;
601
	}
602
	
603
	// Remove any invite or join request flags
604 8
	remove_entity_relationship($group->guid, 'invited', $user->guid);
605 8
	remove_entity_relationship($user->guid, 'membership_request', $group->guid);
606
607 8
	if (elgg_extract('create_river_item', $params)) {
608
		elgg_create_river_item([
609
			'action_type' => 'join',
610
			'subject_guid' => $user->guid,
611
			'object_guid' => $group->guid,
612
		]);
613
	}
614
	
615
	// add a user to the group's access control
616 8
	$collection = _groups_get_group_acl($group);
617 8
	if (!empty($collection)) {
618 8
		$collection->addMember($user->guid);
619
	}
620 8
}
621
622
/**
623
 * Perform actions when a user leaves a group
624
 *
625
 * @param string $event       'leave'
626
 * @param string $object_type 'group'
627
 * @param array  $params      supplied params
628
 *
629
 * @return void
630
 */
631
function groups_user_leave_event_listener($event, $object_type, $params) {
632 2
	$group = elgg_extract('group', $params);
633 2
	$user = elgg_extract('user', $params);
634 2
	if (!$group instanceof ElggGroup || !$user instanceof ElggUser) {
635
		return;
636
	}
637
	
638
	// Remove any invite or join request flags (for some edge cases)
639 2
	remove_entity_relationship($group->guid, 'invited', $user->guid);
640 2
	remove_entity_relationship($user->guid, 'membership_request', $group->guid);
641
	
642
	// Removes a user from the group's access control
643 2
	$collection = _groups_get_group_acl($group);
644 2
	if (!empty($collection)) {
645 2
		$collection->removeMember($user->guid);
646
	}
647 2
}
648
649
/**
650
 * The default access for members only content is this group only. This makes
651
 * for better display of access (can tell it is group only), but does not change
652
 * access to the content.
653
 *
654
 * @param string $hook   Hook name
655
 * @param string $type   Hook type
656
 * @param int    $access Current default access
657
 *
658
 * @return int|void
659
 */
660
function groups_access_default_override($hook, $type, $access) {
661 6
	$page_owner = elgg_get_page_owner_entity();
662 6
	if (!($page_owner instanceof ElggGroup)) {
663 6
		return;
664
	}
665
			
666
	if ($page_owner->getContentAccessMode() !== ElggGroup::CONTENT_ACCESS_MODE_MEMBERS_ONLY) {
667
		return;
668
	}
669
	
670
	$acl = _groups_get_group_acl($page_owner);
671
	if (empty($acl)) {
672
		return;
673
	}
674
	
675
	return $acl->id;
676
}
677
678
/**
679
 * Grabs groups by invitations
680
 * Have to override all access until there's a way override access to getter functions.
681
 *
682
 * @param int   $user_guid    The user's guid
683
 * @param bool  $return_guids Return guids rather than ElggGroup objects
684
 * @param array $options      Additional options
685
 *
686
 * @return mixed ElggGroups or guids depending on $return_guids, or count
687
 */
688
function groups_get_invited_groups($user_guid, $return_guids = false, $options = []) {
689
690
	$ia = elgg_set_ignore_access(true);
691
692
	$defaults = [
693
		'relationship' => 'invited',
694
		'relationship_guid' => (int) $user_guid,
695
		'inverse_relationship' => true,
696
		'limit' => 0,
697
	];
698
699
	$options = array_merge($defaults, $options);
700
	$groups = elgg_get_entities($options);
701
702
	elgg_set_ignore_access($ia);
703
704
	if ($return_guids) {
705
		$guids = [];
706
		foreach ($groups as $group) {
707
			$guids[] = $group->getGUID();
708
		}
709
710
		return $guids;
711
	}
712
713
	return $groups;
714
}
715
716
/**
717
 * Function to use on groups for access. It will house private, loggedin, public,
718
 * and the group itself. This is when you don't want other groups or access lists
719
 * in the access options available.
720
 *
721
 * @param ElggGroup $group the group
722
 *
723
 * @return array
724
 */
725
function group_access_options($group) {
726
727
	$access_array = [
728
		ACCESS_PRIVATE => elgg_echo('access:label:private'),
729
		ACCESS_LOGGED_IN => elgg_echo('access:label:logged_in'),
730
	];
731
732
	if (!elgg_get_config('walled_garden')) {
733
		$access_array[ACCESS_PUBLIC] = elgg_echo('access:label:public');
734
	}
735
736
	if (!$group instanceof ElggGroup) {
0 ignored issues
show
introduced by
The condition ! $group instanceof ElggGroup can never be true.
Loading history...
737
		return $access_array;
738
	}
739
	
740
	$collection = _groups_get_group_acl($group);
741
	if ($collection) {
0 ignored issues
show
introduced by
The condition $collection can never be true.
Loading history...
742
		$access_array[$collection->id] = $collection->getDisplayName();
743
	}
744
	
745
	return $access_array;
746
}
747
748
/**
749
 * Parse ECML on group profiles
750
 *
751
 * @param string $hook         'get_views'
752
 * @param string $type         'ecml'
753
 * @param array  $return_value current return value
754
 * @param mixed  $params       supplied params
755
 *
756
 * @return array
757
 */
758
function groupprofile_ecml_views_hook($hook, $type, $return_value, $params) {
759
	$return_value['groups/groupprofile'] = elgg_echo('groups:ecml:groupprofile');
760
761
	return $return_value;
762
}
763
764
/**
765
 * Setup invitation request actions
766
 *
767
 * @param string $hook   "register"
768
 * @param string $type   "menu:invitationrequest"
769
 * @param array  $menu   Menu items
770
 * @param array  $params Hook params
771
 * @return array
772
 */
773
function groups_invitationrequest_menu_setup($hook, $type, $menu, $params) {
774
775
	$group = elgg_extract('entity', $params);
776
	$user = elgg_extract('user', $params);
777
778
	if (!$group instanceof \ElggGroup) {
779
		return $menu;
780
	}
781
782
	if (!$user instanceof \ElggUser || !$user->canEdit()) {
783
		return $menu;
784
	}
785
786
	$accept_url = elgg_http_add_url_query_elements('action/groups/join', [
787
		'user_guid' => $user->guid,
788
		'group_guid' => $group->guid,
789
	]);
790
791
	$menu[] = \ElggMenuItem::factory([
792
		'name' => 'accept',
793
		'href' => $accept_url,
794
		'is_action' => true,
795
		'text' => elgg_echo('accept'),
796
		'link_class' => 'elgg-button elgg-button-submit',
797
		'is_trusted' => true,
798
	]);
799
800
	$delete_url = elgg_http_add_url_query_elements('action/groups/killinvitation', [
801
		'user_guid' => $user->guid,
802
		'group_guid' => $group->guid,
803
	]);
804
805
	$menu[] = \ElggMenuItem::factory([
806
		'name' => 'delete',
807
		'href' => $delete_url,
808
		'is_action' => true,
809
		'confirm' => elgg_echo('groups:invite:remove:check'),
810
		'text' => elgg_echo('delete'),
811
		'link_class' => 'elgg-button elgg-button-delete mlm',
812
	]);
813
814
	return $menu;
815
}
816
817
/**
818
 * Setup group members tabs
819
 *
820
 * @param string         $hook   "register"
821
 * @param string         $type   "menu:groups_members"
822
 * @param ElggMenuItem[] $menu   Menu items
823
 * @param array          $params Hook params
824
 *
825
 * @return void|ElggMenuItem[]
826
 */
827
function groups_members_menu_setup($hook, $type, $menu, $params) {
828
829
	$entity = elgg_extract('entity', $params);
830
	if (empty($entity) || !($entity instanceof ElggGroup)) {
831
		return;
832
	}
833
834
	$menu[] = ElggMenuItem::factory([
835
		'name' => 'alpha',
836
		'text' => elgg_echo('sort:alpha'),
837
		'href' => "groups/members/{$entity->getGUID()}",
838
		'priority' => 100
839
	]);
840
841
	$menu[] = ElggMenuItem::factory([
842
		'name' => 'newest',
843
		'text' => elgg_echo('sort:newest'),
844
		'href' => "groups/members/{$entity->getGUID()}/newest",
845
		'priority' => 200
846
	]);
847
848
	return $menu;
849
}
850
851
/**
852
 * Registers optional group invites menu item to topbar
853
 *
854
 * @elgg_plugin_hook register menu:topbar
855
 *
856
 * @param \Elgg\Hook $hook hook
857
 *
858
 * @return void|ElggMenuItem[]
859
 *
860
 * @since 3.0
861
 *
862
 * @internal
863
 */
864
function _groups_topbar_menu_setup(\Elgg\Hook $hook) {
865
866 1
	$user = elgg_get_logged_in_user_entity();
867 1
	if (empty($user)) {
868 1
		return;
869
	}
870
	
871
	$count = groups_get_invited_groups($user->guid, false, ['count' => true]);
872
	if (empty($count)) {
873
		return;
874
	}
875
	
876
	$result = $hook->getValue();
877
	
878
	// Invitations
879
	$text = elgg_echo('groups:invitations');
880
	$title = elgg_echo('groups:invitations:pending', [$count]);
881
	
882
	$result[] = \ElggMenuItem::factory([
883
		'name' => 'groups:user:invites',
884
		'text' => $text,
885
		'badge' => $count,
886
		'title' => $title,
887
		'icon' => 'users',
888
		'parent_name' => 'account',
889
		'section' => 'alt',
890
		'href' => "groups/invitations/{$user->username}",
891
	]);
892
	
893
	return $result;
894
}
895
896
/**
897
 * Registers title menu items for group
898
 *
899
 * @elgg_plugin_hook register menu:title
900
 *
901
 * @param \Elgg\Hook $hook Hook
902
 * @return \ElggMenuItem[]
903
 *
904
 * @internal
905
 */
906
function _groups_title_menu(\Elgg\Hook $hook) {
907 1
	$group = $hook->getEntityParam();
908 1
	if (!$group instanceof ElggGroup) {
909 1
		return;
910
	}
911
	
912
	$user = elgg_get_logged_in_user_entity();
913
	if (empty($user)) {
914
		return;
915
	}
916
	
917
	$result = $hook->getValue();
918
	if ($group->canEdit()) {
919
		// group owners can edit the group and invite new members
920
		$result[] = \ElggMenuItem::factory([
921
			'name' => 'groups:edit',
922
			'href' => "groups/edit/{$group->guid}",
923
			'text' => elgg_echo('groups:edit'),
924
			'link_class' => 'elgg-button elgg-button-action',
925
		]);
926
		$result[] = \ElggMenuItem::factory([
927
			'name' => 'groups:invite',
928
			'href' => "groups/invite/{$group->guid}",
929
			'text' => elgg_echo('groups:invite'),
930
			'link_class' => 'elgg-button elgg-button-action',
931
		]);
932
	}
933
	
934
	if ($group->isMember($user)) {
935
		$is_owner = ($group->owner_guid === $user->guid);
936
		$result[] = ElggMenuItem::factory([
937
			'name' => 'group-dropdown',
938
			'href' => false,
939
			'text' => elgg_echo($is_owner ? 'groups:button:owned' : 'groups:button:joined'),
940
			'icon_alt' => 'angle-down',
941
			'link_class' => 'elgg-button elgg-button-action-done',
942
			'child_menu' => [
943
				'display' => 'dropdown',
944
			],
945
		]);
946
		
947
		$leave_group = groups_get_group_leave_menu_item($group, $user);
948
		if ($leave_group) {
0 ignored issues
show
introduced by
The condition $leave_group can never be true.
Loading history...
949
			$leave_group->setParentName('group-dropdown');
950
			$result[] = $leave_group;
951
		}
952
	} else {
953
		$join_group = groups_get_group_join_menu_item($group, $user);
954
		if ($join_group) {
0 ignored issues
show
introduced by
The condition $join_group can never be true.
Loading history...
955
			$join_group->setLinkClass('elgg-button elgg-button-action');
956
			$result[] = $join_group;
957
		}
958
	}
959
	
960
	return $result;
961
}
962
963
/**
964
 * Helper handler to correctly resolve page owners on group routes
965
 *
966
 * @see default_page_owner_handler()
967
 *
968
 * @param string $hook   "page_owner"
969
 * @param string $type   "system"
970
 * @param int    $return Page owner guid
971
 * @param array  $params Hook params
972
 * @return int|void
973
 */
974
function groups_default_page_owner_handler($hook, $type, $return, $params) {
975
976
	if ($return) {
977
		return;
978
	}
979
980
	$segments = _elgg_services()->request->getUrlSegments();
981
	$identifier = array_shift($segments);
982
983
	if ($identifier !== 'groups') {
984
		return;
985
	}
986
987
	$page = array_shift($segments);
988
989
	switch ($page) {
990
		case 'add' :
991
			$guid = array_shift($segments);
992
			if (!$guid) {
993
				$guid = elgg_get_logged_in_user_guid();
994
			}
995
			return $guid;
996
997
		case 'edit':
998
		case 'profile' :
999
		case 'invite' :
1000
		case 'requests' :
1001
		case 'members' :
1002
		case 'profile' :
1003
			$guid = array_shift($segments);
1004
			if (!$guid) {
1005
				return;
1006
			}
1007
			return $guid;
1008
1009
		case 'member' :
1010
		case 'owner' :
1011
		case 'invitations':
1012
			$username = array_shift($segments);
1013
			if ($username) {
1014
				$user = get_user_by_username($username);
1015
			} else {
1016
				$user = elgg_get_logged_in_user_entity();
1017
			}
1018
			if (!$user) {
1019
				return;
1020
			}
1021
			return $user->guid;
1022
	}
1023
}
1024
1025
/**
1026
 * Setup filter tabs on /groups/all page
1027
 *
1028
 * @param string         $hook   "register"
1029
 * @param string         $type   "menu:filter:groups/all"
1030
 * @param ElggMenuItem[] $return Menu
1031
 * @param array          $params Hook params
1032
 * @return ElggMenuItem[]
1033
 */
1034
function groups_setup_filter_tabs($hook, $type, $return, $params) {
1035
1036
	$filter_value = elgg_extract('filter_value', $params);
1037
1038
	$return[] = ElggMenuItem::factory([
1039
		'name' => 'newest',
1040
		'text' => elgg_echo('sort:newest'),
1041
		'href' => 'groups/all?filter=newest',
1042
		'priority' => 200,
1043
		'selected' => $filter_value == 'newest',
1044
	]);
1045
1046
	$return[] = ElggMenuItem::factory([
1047
		'name' => 'alpha',
1048
		'text' => elgg_echo('sort:alpha'),
1049
		'href' => 'groups/all?filter=alpha',
1050
		'priority' => 250,
1051
		'selected' => $filter_value == 'alpha',
1052
	]);
1053
1054
	$return[] = ElggMenuItem::factory([
1055
		'name' => 'popular',
1056
		'text' => elgg_echo('sort:popular'),
1057
		'href' => 'groups/all?filter=popular',
1058
		'priority' => 300,
1059
		'selected' => $filter_value == 'popular',
1060
	]);
1061
1062
	$return[] = ElggMenuItem::factory([
1063
		'name' => 'featured',
1064
		'text' => elgg_echo('groups:featured'),
1065
		'href' => 'groups/all?filter=featured',
1066
		'priority' => 400,
1067
		'selected' => $filter_value == 'featured',
1068
	]);
1069
	
1070
	return $return;
1071
}
1072
1073
/**
1074
 * Add 'original' to group icon sizes
1075
 *
1076
 * @elgg_plugin_hook entity:icon:sizes group
1077
 *
1078
 * @param \Elgg\Hook $hook Hook
1079
 * @return array
1080
 */
1081
function groups_set_icon_sizes(\Elgg\Hook $hook) {
1082
1083
	$sizes = $hook->getValue();
1084
	$sizes['original'] = [];
1085
1086
	return $sizes;
1087
}
1088
1089
/**
1090
 * Get the access collection for a given group
1091
 *
1092
 * @param \ElggGroup $group the group
1093
 *
1094
 * @return \ElggAccessCollection|false
1095
 *
1096
 * @internal
1097
 * @since 3.0
1098
 */
1099
function _groups_get_group_acl(\ElggGroup $group) {
1100 8
	if (!$group instanceof \ElggGroup) {
0 ignored issues
show
introduced by
The condition ! $group instanceof ElggGroup can never be true.
Loading history...
1101
		return false;
1102
	}
1103
	
1104 8
	return elgg_extract(0, $group->getOwnedAccessCollections(['subtype' => 'group_acl']), false);
1105
}
1106
1107
/**
1108
 * Prepares variables for the group edit form view.
1109
 *
1110
 * @param mixed $group ElggGroup or null. If a group, uses values from the group.
1111
 * @return array
1112
 */
1113
function groups_prepare_form_vars($group = null) {
1114
	$values = [
1115
		'name' => '',
1116
		'membership' => ACCESS_PUBLIC,
1117
		'vis' => ACCESS_PUBLIC,
1118
		'guid' => null,
1119
		'entity' => null,
1120
		'owner_guid' => elgg_get_logged_in_user_guid(),
1121
		'content_access_mode' => ElggGroup::CONTENT_ACCESS_MODE_UNRESTRICTED
1122
	];
1123
1124
	// handle customizable profile fields
1125
	$fields = elgg_get_config('group');
1126
1127
	if ($fields) {
1128
		foreach ($fields as $name => $type) {
1129
			$values[$name] = '';
1130
		}
1131
	}
1132
1133
	// get current group settings
1134
	if ($group) {
1135
		foreach (array_keys($values) as $field) {
1136
			if (isset($group->$field)) {
1137
				$values[$field] = $group->$field;
1138
			}
1139
		}
1140
1141
		if ($group->access_id != ACCESS_PUBLIC && $group->access_id != ACCESS_LOGGED_IN) {
1142
			// group only access - this is done to handle access not created when group is created
1143
			$values['vis'] = ACCESS_PRIVATE;
1144
		} else {
1145
			$values['vis'] = $group->access_id;
1146
		}
1147
1148
		// The content_access_mode was introduced in 1.9. This method must be
1149
		// used for backwards compatibility with groups created before 1.9.
1150
		$values['content_access_mode'] = $group->getContentAccessMode();
1151
1152
		$values['entity'] = $group;
1153
	}
1154
1155
	// handle tool options
1156
	$entity = ($group instanceof \ElggGroup) ? $group : null;
1157
	$tools = elgg_get_group_tool_options($entity);
1158
	foreach ($tools as $group_option) {
1159
		$option_name = $group_option->name . "_enable";
1160
1161
		$enabled = $group_option->default_on;
1162
		if ($entity) {
1163
			$enabled = $entity->isToolEnabled($group_option->name);
1164
		}
1165
		$values[$option_name] = $enabled ? 'yes' : 'no';
1166
	}
1167
1168
	// get any sticky form settings
1169
	if (elgg_is_sticky_form('groups')) {
1170
		$sticky_values = elgg_get_sticky_values('groups');
1171
		foreach ($sticky_values as $key => $value) {
1172
			$values[$key] = $value;
1173
		}
1174
	}
1175
1176
	elgg_clear_sticky_form('groups');
1177
1178
	return $values;
1179
}
1180
1181
return function() {
1182 18
	elgg_register_event_handler('init', 'system', 'groups_init');
1183
1184
	// Ensure this runs after other plugins
1185
	elgg_register_event_handler('init', 'system', 'groups_fields_setup', 10000);
1186
};