hooks.php ➔ questions_permissions_handler()   F
last analyzed

Complexity

Conditions 21
Paths 147

Size

Total Lines 66

Duplication

Lines 21
Ratio 31.82 %

Code Coverage

Tests 0
CRAP Score 462

Importance

Changes 0
Metric Value
cc 21
nc 147
nop 4
dl 21
loc 66
ccs 0
cts 45
cp 0
crap 462
rs 3.775
c 0
b 0
f 0

How to fix   Long Method    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
 * All plugin hooks are bundled here
4
 */
5
6
/**
7
 * Add menu items to the owner_block menu
8
 *
9
 * @param string         $hook   the name of the hook
10
 * @param string         $type   the type of the hook
11
 * @param ElggMenuItem[] $items  current return value
12
 * @param array          $params supplied params
13
 *
14
 * @return void|ElggMenuItem[]
15
 */
16
function questions_owner_block_menu_handler($hook, $type, $items, $params) {
17
	
18
	if (empty($params) || !is_array($params)) {
19
		return;
20
	}
21
	
22
	$entity = elgg_extract('entity', $params);
23
	if (($entity instanceof ElggGroup) && ($entity->questions_enable === 'yes')) {
24
		$items[] = ElggMenuItem::factory([
25
			'name' => 'questions',
26
			'href' => "questions/group/{$entity->getGUID()}/all",
27
			'text' => elgg_echo('questions:group'),
28
		]);
29 View Code Duplication
	} elseif ($entity instanceof ElggUser) {
30
		$items[] = ElggMenuItem::factory([
31
			'name' => 'questions',
32
			'href' => "questions/owner/{$entity->username}",
33
			'text' => elgg_echo('questions'),
34
		]);
35
	}
36
	
37
	return $items;
38
}
39
40
/**
41
 * Add menu items to the entity menu
42
 *
43
 * @param string         $hook   the name of the hook
44
 * @param string         $type   the type of the hook
45
 * @param ElggMenuItem[] $items  current return value
46
 * @param array          $params supplied params
47
 *
48
 * @return void|ElggMenuItem[]
49
 */
50
function questions_entity_menu_handler($hook, $type, $items, $params) {
51
52
	if (empty($params) || !is_array($params)) {
53
		return;
54
	}
55
	
56
	$entity = elgg_extract('entity', $params);
57
	if (empty($entity) || (!($entity instanceof ElggQuestion) && !($entity instanceof ElggAnswer))) {
58
		return;
59
	}
60
	
61
	if ($entity->canComment()) {
62
		if (elgg_extract('full_view', $params, false) || ($entity instanceof ElggAnswer)) {
63
			$items[] = ElggMenuItem::factory([
64
				'name' => 'comments',
65
				'rel' => 'toggle',
66
				'link_class' => 'elgg-toggler',
67
				'href' => "#comments-add-{$entity->getGUID()}",
68
				'text' => elgg_view_icon('speech-bubble'),
69
				'priority' => 600,
70
			]);
71
		}
72
	}
73
	
74
	if (elgg_in_context('questions') && ($entity instanceof ElggAnswer) && questions_can_mark_answer($entity)) {
75
		$question = $entity->getContainerEntity();
76
		$answer = $question->getMarkedAnswer();
77
78
		if (empty($answer)) {
79
			$items[] = ElggMenuItem::factory([
80
				'name' => 'questions_mark',
81
				'text' => elgg_echo('questions:menu:entity:answer:mark'),
82
				'href' => "action/answers/toggle_mark?guid={$entity->getGUID()}",
83
				'is_action' => true,
84
			]);
85
		} elseif ($entity->getGUID() === $answer->getGUID()) {
86
			// there is an anwser and it's this entity
87
			$items[] = ElggMenuItem::factory([
88
				'name' => 'questions_mark',
89
				'text' => elgg_echo('questions:menu:entity:answer:unmark'),
90
				'href' => "action/answers/toggle_mark?guid={$entity->getGUID()}",
91
				'is_action' => true,
92
			]);
93
		}
94
	}
95
96
	return $items;
97
}
98
99
/**
100
 * Add menu items to the filter menu
101
 *
102
 * @param string         $hook   the name of the hook
103
 * @param string         $type   the type of the hook
104
 * @param ElggMenuItem[] $items  current return value
105
 * @param array          $params supplied params
106
 *
107
 * @return void|ElggMenuItem[]
108
 */
109
function questions_filter_menu_handler($hook, $type, $items, $params) {
110
111
	if (empty($items) || !is_array($items) || !elgg_in_context('questions')) {
112
		return;
113
	}
114
	
115
	$page_owner = elgg_get_page_owner_entity();
116
	
117
	// change some menu items
118
	foreach ($items as $key => $item) {
119
		// remove friends
120
		if ($item->getName() == 'friend') {
121
			unset($items[$key]);
122
		}
123
		
124
		// in group context
125
		if ($page_owner instanceof ElggGroup) {
126
			// remove mine
127
			if ($item->getName() == 'mine') {
128
				unset($items[$key]);
129
			}
130
131
			// check if all is correct
132
			if ($item->getName() === 'all') {
133
				// set correct url
134
				$item->setHref("questions/group/{$page_owner->getGUID()}/all");
135
				
136
				// highlight all
137
				$current_page = current_page_url();
138
				if (stristr($current_page, "questions/group/{$page_owner->getGUID()}/all")) {
139
					$item->setSelected(true);
140
				}
141
			}
142
		}
143
	}
144
	
145 View Code Duplication
	if (questions_is_expert()) {
146
		$items[] = ElggMenuItem::factory([
147
			'name' => 'todo',
148
			'text' => elgg_echo('questions:menu:filter:todo'),
149
			'href' => 'questions/todo',
150
			'priority' => 700,
151
		]);
152
153
		if ($page_owner instanceof ElggGroup) {
154
			$items[] = ElggMenuItem::factory([
155
				'name' => 'todo_group',
156
				'text' => elgg_echo('questions:menu:filter:todo_group'),
157
				'href' => "questions/todo/{$page_owner->getGUID()}",
158
				'priority' => 710,
159
			]);
160
		}
161
	}
162
163 View Code Duplication
	if (questions_experts_enabled()) {
164
		$experts_href = 'questions/experts';
165
		if ($page_owner instanceof ElggGroup) {
166
			$experts_href .= "/{$page_owner->getGUID()}";
167
		}
168
169
		$items[] = ElggMenuItem::factory([
170
			'name' => 'experts',
171
			'text' => elgg_echo('questions:menu:filter:experts'),
172
			'href' => $experts_href,
173
			'priority' => 800,
174
		]);
175
	}
176
177
	return $items;
178
}
179
180
/**
181
 * Add menu items to the user_hover menu
182
 *
183
 * @param string         $hook   the name of the hook
184
 * @param string         $type   the type of the hook
185
 * @param ElggMenuItem[] $items  current return value
186
 * @param array          $params supplied params
187
 *
188
 * @return void|ElggMenuItem[]
189
 */
190
function questions_user_hover_menu_handler($hook, $type, $items, $params) {
191
	if (empty($params) || !is_array($params)) {
192
		return;
193
	}
194
	
195
	// are experts enabled
196
	if (!questions_experts_enabled()) {
197
		return;
198
	}
199
	
200
	// get the user for this menu
201
	$user = elgg_extract('entity', $params);
202
	if (empty($user) || !($user instanceof ElggUser)) {
203
		return;
204
	}
205
	
206
	// get page owner
207
	$page_owner = elgg_get_page_owner_entity();
208
	if (!($page_owner instanceof ElggGroup)) {
209
		$page_owner = elgg_get_site_entity();
210
	}
211
	
212
	// can the current person edit the page owner, to assign the role
213
	// and is the current user not the owner of this page owner
214
	if (!$page_owner->canEdit()) {
215
		return;
216
	}
217
	
218
	$text = elgg_echo('questions:menu:user_hover:make_expert');
219
	$confirm_text = elgg_echo('questions:menu:user_hover:make_expert:confirm', [$page_owner->name]);
220
	if (check_entity_relationship($user->getGUID(), QUESTIONS_EXPERT_ROLE, $page_owner->getGUID())) {
221
		$text = elgg_echo('questions:menu:user_hover:remove_expert');
222
		$confirm_text = elgg_echo('questions:menu:user_hover:remove_expert:confirm', [$page_owner->name]);
223
	}
224
	
225
	$items[] = ElggMenuItem::factory([
226
		'name' => 'questions_expert',
227
		'text' => $text,
228
		'href' => "action/questions/toggle_expert?user_guid={$user->getGUID()}&guid={$page_owner->getGUID()}",
229
		'confirm' => $confirm_text,
230
		"section" => "admin",
231
	]);
232
	
233
	return $items;
234
}
235
236
/**
237
 * Check if a user can write an answer
238
 *
239
 * @param string $hook        the name of the hook
240
 * @param string $type        the type of the hook
241
 * @param bool   $returnvalue current return value
242
 * @param array  $params      supplied params
243
 *
244
 * @return void|bool
245
 */
246
function questions_container_permissions_handler($hook, $type, $returnvalue, $params) {
247
	static $experts_only;
248
249
	if ($returnvalue || empty($params) || !is_array($params)) {
250
		return;
251
	}
252
	
253
	$question = elgg_extract('container', $params);
254
	$user = elgg_extract('user', $params);
255
	$subtype = elgg_extract('subtype', $params);
256
	
257
	if (($subtype !== 'answer') || !($user instanceof ElggUser) || !($question instanceof ElggQuestion)) {
258
		return;
259
	}
260
	
261
	return questions_can_answer_question($question, $user);
262
}
263
264
/**
265
 * Check if a user has permissions
266
 *
267
 * @param string $hook        the name of the hook
268
 * @param string $type        the type of the hook
269
 * @param bool   $returnvalue current return value
270
 * @param array  $params      supplied params
271
 *
272
 * @return void|bool
273
 */
274
function questions_permissions_handler($hook, $type, $returnvalue, $params) {
275
	
276
	if (empty($params) || !is_array($params)) {
277
		return;
278
	}
279
	
280
	// get the provided data
281
	$entity = elgg_extract('entity', $params);
282
	$user = elgg_extract('user', $params);
283
	
284
	if (!($user instanceof ElggUser)) {
285
		return;
286
	}
287
	
288
	if (!($entity instanceof ElggQuestion) && !($entity instanceof ElggAnswer)) {
289
		return;
290
	}
291
	
292
	// expert only changes
293
	if (questions_experts_enabled()) {
294
		// check if an expert can edit a question
295 View Code Duplication
		if (!$returnvalue && ($entity instanceof ElggQuestion)) {
296
			$container = $entity->getContainerEntity();
297
			if (!($container instanceof ElggGroup)) {
298
				$container = elgg_get_site_entity();
299
			}
300
			
301
			if (questions_is_expert($container, $user)) {
302
				$returnvalue = true;
303
			}
304
		}
305
		
306
		// an expert should be able to edit an answer, so fix this
307
		if (!$returnvalue && ($entity instanceof ElggAnswer)) {
308
			// user is not the owner
309
			if ($entity->getOwnerGUID() !== $user->getGUID()) {
310
				$question = $entity->getContainerEntity();
311
				
312 View Code Duplication
				if ($question instanceof ElggQuestion) {
313
					$container = $question->getContainerEntity();
314
					if (!($container instanceof ElggGroup)) {
315
						$container = elgg_get_site_entity();
316
					}
317
					
318
					// if the user is an expert
319
					if (questions_is_expert($container, $user)) {
320
						$returnvalue = true;
321
					}
322
				}
323
			}
324
		}
325
	}
326
	
327
	// questions can't be editted by owner if it is closed
328
	if ($returnvalue && ($entity instanceof ElggQuestion)) {
329
		// is the question closed
330
		if ($entity->getStatus() === 'closed') {
331
			// are you the owner
332
			if ($user->getGUID() === $entity->getOwnerGUID()) {
333
				$returnvalue = false;
334
			}
335
		}
336
	}
337
338
	return $returnvalue;
339
}
340
341
/**
342
 * A plugin hook for the CRON, so we can send out notifications to the experts about there workload
343
 *
344
 * @param string $hook        the name of the hook
345
 * @param string $type        the type of the hook
346
 * @param string $returnvalue current return value
347
 * @param array  $params      supplied params
348
 *
349
 * @return void
350
 */
351
function questions_daily_cron_handler($hook, $type, $returnvalue, $params) {
352
353
	if (empty($params) || !is_array($params)) {
354
		return;
355
	}
356
	
357
	// are experts enabled
358
	if (!questions_experts_enabled()) {
359
		return;
360
	}
361
		
362
	$time = (int) elgg_extract('time', $params, time());
363
	$dbprefix = elgg_get_config('dbprefix');
364
	$site = elgg_get_site_entity();
365
366
	// get all experts
367
	$expert_options = [
368
		'type' => 'user',
369
		'site_guids' => false,
370
		'limit' => false,
371
		'joins' => ["JOIN {$dbprefix}entity_relationships re2 ON e.guid = re2.guid_one"],
372
		'wheres' =>["(re2.guid_two = {$site->getGUID()} AND re2.relationship = 'member_of_site')"],
373
		'relationship' => QUESTIONS_EXPERT_ROLE,
374
		'inverse_relationship' => true,
375
	];
376
	$experts = new ElggBatch('elgg_get_entities_from_relationship', $expert_options);
377
	
378
	// sending could take a while
379
	set_time_limit(0);
380
	
381
	$status_id = elgg_get_metastring_id('status');
382
	$closed_id = elgg_get_metastring_id('closed');
383
	
384
	$status_where = "NOT EXISTS (
385
		SELECT 1
386
		FROM {$dbprefix}metadata md
387
		WHERE md.entity_guid = e.guid
388
		AND md.name_id = {$status_id}
389
		AND md.value_id = {$closed_id})";
390
391
	$question_options = [
392
		'type' => 'object',
393
		'subtype' => 'question',
394
		'limit' => 3,
395
	];
396
	
397
	// loop through all experts
398
	foreach ($experts as $expert) {
399
		// fake a logged in user
400
		$backup_user = elgg_extract('user', $_SESSION);
401
		$_SESSION['user'] = $expert;
402
		
403
		$subject = elgg_echo('questions:daily:notification:subject', [], get_current_language());
404
		$message = '';
405
		
406
		$container_where = [];
407 View Code Duplication
		if (check_entity_relationship($expert->getGUID(), QUESTIONS_EXPERT_ROLE, $site->getGUID())) {
408
			$container_where[] = "(e.container_guid NOT IN (
409
				SELECT ge.guid
410
				FROM {$dbprefix}entities ge
411
				WHERE ge.type = 'group'
412
				AND ge.site_guid = {$site->getGUID()}
413
				AND ge.enabled = 'yes'
414
			))";
415
		}
416
		
417
		$group_options = [
418
			'type' => 'group',
419
			'limit' => false,
420
			'relationship' => QUESTIONS_EXPERT_ROLE,
421
			'relationship_guid' => $expert->getGUID(),
422
			'callback' => 'questions_row_to_guid',
423
		];
424
		$groups = elgg_get_entities_from_relationship($group_options);
425
		if (!empty($groups)) {
426
			$container_where[] = '(e.container_guid IN (' . implode(',', $groups) . '))';
427
		}
428
		
429
		if (empty($container_where)) {
430
			// no groups or site? then skip to next expert
431
			continue;
432
		}
433
		$container_where = '(' . implode(' OR ', $container_where) . ')';
434
		
435
		// get overdue questions
436
		// eg: solution_time < $time && status != closed
437
		$question_options['metadata_name_value_pairs'] = [
438
			'name' => 'solution_time',
439
			'value' => $time,
440
			'operand' => '<',
441
		];
442
		$question_options['wheres'] = [
443
			$status_where,
444
			$container_where
445
		];
446
		$question_options['order_by_metadata'] = [
447
			'name' => 'solution_time',
448
			'direction' => 'ASC',
449
			'as' => 'integer'
450
		];
451
		$questions = elgg_get_entities_from_metadata($question_options);
452 View Code Duplication
		if (!empty($questions)) {
453
			$message .= elgg_echo('questions:daily:notification:message:overdue', [], get_current_language()) . PHP_EOL;
454
			
455
			foreach ($questions as $question) {
456
				$message .= " - {$question->title} ({$question->getURL()})" . PHP_EOL;
457
			}
458
			
459
			$message .= elgg_echo('questions:daily:notification:message:more', [], get_current_language());
460
			$message .= " {$site->url}questions/todo" . PHP_EOL . PHP_EOL;
461
		}
462
		
463
		// get due questions
464
		// eg: solution_time >= $time && solution_time < ($time + 1 day) && status != closed
465
		$question_options['metadata_name_value_pairs'] = [
466
			[
467
				'name' => 'solution_time',
468
				'value' => $time,
469
				'operand' => '>=',
470
			],
471
			[
472
				'name' => 'solution_time',
473
				'value' => $time + (24 * 60 * 60),
474
				'operand' => '<',
475
			],
476
		];
477
		
478
		$questions = elgg_get_entities_from_metadata($question_options);
479 View Code Duplication
		if (!empty($questions)) {
480
			$message .= elgg_echo('questions:daily:notification:message:due', [], get_current_language()) . PHP_EOL;
481
			
482
			foreach ($questions as $question) {
483
				$message .= " - {$question->title} ({$question->getURL()})" . PHP_EOL;
484
			}
485
			
486
			$message .= elgg_echo('questions:daily:notification:message:more', [], get_current_language());
487
			$message .= " {$site->url}questions/todo" . PHP_EOL . PHP_EOL;
488
		}
489
		
490
		// get new questions
491
		// eg: time_created >= ($time - 1 day)
492
		unset($question_options['metadata_name_value_pairs']);
493
		unset($question_options['order_by_metadata']);
494
		$question_options['wheres'] = [
495
			$container_where,
496
			'(e.time_created > ' . ($time - (24 * 60 *60)) . ')'
497
		];
498
		$questions = elgg_get_entities_from_metadata($question_options);
499 View Code Duplication
		if (!empty($questions)) {
500
			$message .= elgg_echo('questions:daily:notification:message:new', [], get_current_language()) . PHP_EOL;
501
			
502
			foreach ($questions as $question) {
503
				$message .= " - {$question->title} ({$question->getURL()})" . PHP_EOL;
504
			}
505
			
506
			$message .= elgg_echo('questions:daily:notification:message:more', array(), get_current_language());
507
			$message .= " {$site->url}questions/all" . PHP_EOL . PHP_EOL;
508
		}
509
		
510
		// is there content in the message
511
		if (!empty($message)) {
512
			// force to email
513
			notify_user($expert->getGUID(), $site->getGUID(), $subject, $message, null, 'email');
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
514
		}
515
		
516
		// restore user
517
		$_SESSION['user'] = $backup_user;
518
	}
519
}
520