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

mod/messages/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 internal messages plugin
4
* This plugin lets users send messages to each other.
5
*/
6
7
elgg_register_event_handler('init', 'system', 'messages_init');
8
9
function messages_init() {
10
11
	// add page menu items
12
	if (elgg_is_logged_in()) {
13
		elgg_register_menu_item('page', [
14
			'name' => 'messages:inbox',
15
			'text' => elgg_echo('messages:inbox'),
16
			'href' => "messages/inbox/" . elgg_get_logged_in_user_entity()->username,
17
			'context' => 'messages',
18
		]);
19
		
20
		elgg_register_menu_item('page', [
21
			'name' => 'messages:sentmessages',
22
			'text' => elgg_echo('messages:sentmessages'),
23
			'href' => "messages/sent/" . elgg_get_logged_in_user_entity()->username,
24
			'context' => 'messages',
25
		]);
26
	}
27
28
	// Extend system CSS with our own styles, which are defined in the messages/css view
29
	elgg_extend_view('elgg.css', 'messages/css');
30
	elgg_extend_view('elgg.js', 'messages/js');
31
	
32
	// Register a page handler, so we can have nice URLs
33
	elgg_register_page_handler('messages', 'messages_page_handler');
34
35
	// Register a URL handler
36
	elgg_register_plugin_hook_handler('entity:url', 'object', 'messages_set_url');
37
38
	// Extend avatar hover menu
39
	elgg_register_plugin_hook_handler('register', 'menu:user_hover', 'messages_user_hover_menu');
40
41
	// delete messages sent by a user when user is deleted
42
	elgg_register_event_handler('delete', 'user', 'messages_purge');
43
44
	// ecml
45
	elgg_register_plugin_hook_handler('get_views', 'ecml', 'messages_ecml_views_hook');
46
47
	// permission overrides
48
	elgg_register_plugin_hook_handler('permissions_check:metadata', 'object', 'messages_can_edit_metadata');
49
	elgg_register_plugin_hook_handler('permissions_check', 'object', 'messages_can_edit');
50
	elgg_register_plugin_hook_handler('container_permissions_check', 'object', 'messages_can_edit_container');
51
52
	// Topbar menu. We assume this menu will render *after* a message is rendered. If a refactor/plugin
53
	// causes it to render first, the unread count notification will not update until the next page.
54
	elgg_register_plugin_hook_handler('register', 'menu:topbar', 'messages_register_topbar');
55
}
56
57
/**
58
 * Messages page handler
59
 *
60
 * @param array $page Array of URL components for routing
61
 * @return bool
62
 */
63
function messages_page_handler($page) {
64
65
	elgg_gatekeeper();
66
67
	elgg_push_breadcrumb(elgg_echo('messages'), 'messages/inbox/' . $current_user->username);
68
69
	if (!isset($page[0])) {
70
		$page[0] = 'inbox';
71
	}
72
73
	// Support the old inbox url /messages/<username>, but only if it matches the logged in user.
74
	// Otherwise having a username like "read" on the system could confuse this function.
75
	if ($current_user->username === $page[0]) {
76
		$page[1] = $page[0];
77
		$page[0] = 'inbox';
78
	}
79
80
	if (!isset($page[1])) {
81
		$page[1] = $current_user->username;
82
	}
83
84
	switch ($page[0]) {
85
		case 'inbox':
86
			echo elgg_view_resource('messages/inbox', [
87
				'username' => $page[1],
88
			]);
89
			break;
90
		case 'sent':
91
			echo elgg_view_resource('messages/sent', [
92
				'username' => $page[1],
93
			]);
94
			break;
95
		case 'read':
96
			echo elgg_view_resource('messages/read', [
97
				'guid' => $page[1],
98
			]);
99
			break;
100
		case 'compose':
101
		case 'add':
102
			echo elgg_view_resource('messages/send');
103
			break;
104
		default:
105
			return false;
106
	}
107
	return true;
108
}
109
110
/**
111
 * Add inbox link to topbar
112
 *
113
 * @param string $hook   "register"
114
 * @param string $type   "menu:topbar"
115
 * @param array  $items  Menu items
116
 * @param array  $params Hook params
117
 * @return array
118
 */
119
function messages_register_topbar($hook, $type, $items, $params) {
120
	if (!elgg_is_logged_in()) {
121
		return;
122
	}
123
124
	$user = elgg_get_logged_in_user_entity();
125
126
	$text = elgg_echo('messages');
127
	$title = $text;
128
129
	$num_messages = (int) messages_count_unread();
130
	if ($num_messages) {
131
		$title .= " (" . elgg_echo("messages:unreadcount", [$num_messages]) . ")";
132
	}
133
134
	$items[] = ElggMenuItem::factory([
135
		'name' => 'messages',
136
		'href' => "messages/inbox/$user->username",
137
		'text' => $text,
138
		'priority' => 600,
139
		'title' => $title,
140
		'icon' => 'mail',
141
		'badge' => $num_messages ? $num_messages : null,
142
	]);
143
144
	return $items;
145
}
146
147
/**
148
 * Override the canEditMetadata function to return true for messages
149
 *
150
 */
151 View Code Duplication
function messages_can_edit_metadata($hook_name, $entity_type, $return_value, $parameters) {
152
153
	global $messagesendflag;
154
155
	if ($messagesendflag !== 1) {
156
		return;
157
	}
158
	
159
	$entity = elgg_extract('entity', $parameters);
160
	if ($entity->getSubtype() == 'messages') {
161
		return true;
162
	}
163
}
164
165
/**
166
 * Override the canEdit function to return true for messages within a particular context.
167
 *
168
 */
169 View Code Duplication
function messages_can_edit($hook_name, $entity_type, $return_value, $parameters) {
170
171
	global $messagesendflag;
172
	
173
	if ($messagesendflag !== 1) {
174
		return;
175
	}
176
	
177
	$entity = elgg_extract('entity', $parameters);
178
	if ($entity->getSubtype() == 'messages') {
179
		return true;
180
	}
181
}
182
183
/**
184
 * Prevent messages from generating a notification
185
 */
186
function messages_notification_msg($hook_name, $entity_type, $return_value, $params) {
187
	$entity = elgg_extract('entity', $params);
188
	if (!$entity instanceof ElggEntity) {
189
		return;
190
	}
191
		
192
	if ($entity->getSubtype() == 'messages') {
193
		return false;
194
	}
195
}
196
197
/**
198
 * Override the canEdit function to return true for messages within a particular context.
199
 *
200
 */
201
function messages_can_edit_container($hook_name, $entity_type, $return_value, $parameters) {
202
203
	global $messagesendflag;
204
205
	if ($messagesendflag == 1) {
206
		return true;
207
	}
208
}
209
210
/**
211
 * Send an internal message
212
 *
213
 * @param string $subject           The subject line of the message
214
 * @param string $body              The body of the mesage
215
 * @param int    $recipient_guid    The GUID of the user to send to
216
 * @param int    $sender_guid       Optionally, the GUID of the user to send from
217
 * @param int    $original_msg_guid The GUID of the message to reply from (default: none)
218
 * @param bool   $notify            Send a notification (default: true)
219
 * @param bool   $add_to_sent       If true (default), will add a message to the sender's 'sent' tray
220
 * @return bool
221
 */
222
function messages_send($subject, $body, $recipient_guid, $sender_guid = 0, $original_msg_guid = 0, $notify = true, $add_to_sent = true) {
223
224
	// @todo remove globals
225
	global $messagesendflag;
226
	$messagesendflag = 1;
227
228
	// @todo remove globals
229
	global $messages_pm;
230
	if ($notify) {
231
		$messages_pm = 1;
232
	} else {
233
		$messages_pm = 0;
234
	}
235
236
	// If $sender_guid == 0, set to current user
237
	if ($sender_guid == 0) {
238
		$sender_guid = (int) elgg_get_logged_in_user_guid();
239
	}
240
241
	// Initialise 2 new ElggObject
242
	$message_to = new ElggObject();
243
	$message_sent = new ElggObject();
244
245
	$message_to->subtype = "messages";
246
	$message_sent->subtype = "messages";
247
248
	$message_to->owner_guid = $recipient_guid;
249
	$message_to->container_guid = $recipient_guid;
250
	$message_sent->owner_guid = $sender_guid;
251
	$message_sent->container_guid = $sender_guid;
252
253
	$message_to->access_id = ACCESS_PUBLIC;
254
	$message_sent->access_id = ACCESS_PUBLIC;
255
256
	$message_to->title = $subject;
257
	$message_to->description = $body;
258
259
	$message_sent->title = $subject;
260
	$message_sent->description = $body;
261
262
	$message_to->toId = $recipient_guid; // the user receiving the message
263
	$message_to->fromId = $sender_guid; // the user receiving the message
264
	$message_to->readYet = 0; // this is a toggle between 0 / 1 (1 = read)
265
	$message_to->hiddenFrom = 0; // this is used when a user deletes a message in their sentbox, it is a flag
266
	$message_to->hiddenTo = 0; // this is used when a user deletes a message in their inbox
267
268
	$message_sent->toId = $recipient_guid; // the user receiving the message
269
	$message_sent->fromId = $sender_guid; // the user receiving the message
270
	$message_sent->readYet = 0; // this is a toggle between 0 / 1 (1 = read)
271
	$message_sent->hiddenFrom = 0; // this is used when a user deletes a message in their sentbox, it is a flag
272
	$message_sent->hiddenTo = 0; // this is used when a user deletes a message in their inbox
273
274
	// Save the copy of the message that goes to the recipient
275
	$success = $message_to->save();
276
277
	// Save the copy of the message that goes to the sender
278
	if ($add_to_sent) {
279
		$message_sent->save();
280
	}
281
282
	$message_to->access_id = ACCESS_PRIVATE;
283
	$message_to->save();
284
285
	if ($add_to_sent) {
286
		$message_sent->access_id = ACCESS_PRIVATE;
287
		$message_sent->save();
288
	}
289
290
	// if the new message is a reply then create a relationship link between the new message
291
	// and the message it is in reply to
292
	if ($original_msg_guid && $success) {
293
		add_entity_relationship($message_sent->guid, "reply", $original_msg_guid);
294
	}
295
296
	$message_contents = strip_tags($body);
297
	if (($recipient_guid != elgg_get_logged_in_user_guid()) && $notify) {
298
		$recipient = get_user($recipient_guid);
299
		$sender = get_user($sender_guid);
300
		
301
		$subject = elgg_echo('messages:email:subject', [], $recipient->language);
302
		$body = elgg_echo('messages:email:body', [
303
				$sender->name,
304
				$message_contents,
305
				elgg_get_site_url() . "messages/inbox/" . $recipient->username,
306
				$sender->name,
307
				elgg_get_site_url() . "messages/compose?send_to=" . $sender_guid
308
			],
309
			$recipient->language
310
		);
311
312
		$params = [
313
			'object' => $message_to,
314
			'action' => 'send',
315
			'url' => $message_to->getURL(),
316
		];
317
		notify_user($recipient_guid, $sender_guid, $subject, $body, $params);
318
	}
319
320
	$messagesendflag = 0;
321
	return $success;
322
}
323
324
/**
325
 * Message URL override
326
 *
327
 * @param string $hook
328
 * @param string $type
329
 * @param string $url
330
 * @param array  $params
331
 * @return string
332
 */
333
function messages_set_url($hook, $type, $url, $params) {
334
	$entity = $params['entity'];
335
	if (elgg_instanceof($entity, 'object', 'messages')) {
336
		return 'messages/read/' . $entity->getGUID();
337
	}
338
}
339
340
/**
341
 * Returns the unread messages in a user's inbox
342
 *
343
 * @param int  $user_guid GUID of user whose inbox we're counting (0 for logged in user)
344
 * @param int  $limit     Number of unread messages to return (default from settings)
345
 * @param int  $offset    Start at a defined offset (for listings)
346
 * @param bool $count     Switch between entities array or count mode
347
 *
348
 * @return array, int (if $count = true)
349
 * @since 1.9
350
 */
351
function messages_get_unread($user_guid = 0, $limit = null, $offset = 0, $count = false) {
352
	return elgg_get_entities_from_metadata([
353
		'metadata_name_value_pairs' => [
354
			'toId' => $user_guid,
355
			'readYet' => 0,
356
			'msg' => 1,
357
		],
358
		'owner_guid' => $user_guid ?: elgg_get_logged_in_user_guid(),
359
		'limit' => $limit ?: elgg_get_config('default_limit'),
360
		'offset' => $offset,
361
		'count' => $count,
362
		'distinct' => false,
363
	]);
364
}
365
366
/**
367
 * Count the unread messages in a user's inbox
368
 *
369
 * @param int $user_guid GUID of user whose inbox we're counting (0 for logged in user)
370
 *
371
 * @return int
372
 */
373
function messages_count_unread($user_guid = 0) {
374
	return messages_get_unread($user_guid, 10, 0, true);
375
}
376
377
/**
378
 * Prepare the compose form variables
379
 *
380
 * @return array
381
 */
382
function messages_prepare_form_vars($recipient_guid = 0) {
383
384
	$recipients = [];
385
	$recipient = get_user($recipient_guid);
386
	if (!empty($recipient)) {
387
		$recipients[] = $recipient->getGUID();
388
	}
389
390
	// input names => defaults
391
	$values = [
392
		'subject' => elgg_get_sticky_value('messages', 'subject', ''),
393
		'body' => elgg_get_sticky_value('messages', 'body', ''),
394
		'recipients' => elgg_get_sticky_value('messages', 'recipients', $recipients),
395
	];
396
397
	elgg_clear_sticky_form('messages');
398
399
	return $values;
400
}
401
402
/**
403
 * Add to the user hover menu
404
 */
405 View Code Duplication
function messages_user_hover_menu($hook, $type, $return, $params) {
0 ignored issues
show
This function seems to be duplicated in 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...
406
	$user = $params['entity'];
407
408
	if (!elgg_is_logged_in()) {
409
		return;
410
	}
411
	
412
	if (elgg_get_logged_in_user_guid() == $user->guid) {
413
		return;
414
	}
415
	
416
	$return[] = ElggMenuItem::factory([
417
		'name' => 'send',
418
		'text' => elgg_echo('messages:sendmessage'),
419
		'icon' => 'mail',
420
		'href' => "messages/compose?send_to={$user->guid}",
421
		'section' => 'action',
422
	]);
423
424
	return $return;
425
}
426
427
/**
428
 * Delete messages from a user who is being deleted
429
 *
430
 * @param string   $event Event name
431
 * @param string   $type  Event type
432
 * @param ElggUser $user  User being deleted
433
 */
434
function messages_purge($event, $type, $user) {
435
436
	if (!$user->getGUID()) {
437
		return;
438
	}
439
440
	// make sure we delete them all
441
	$entity_disable_override = access_show_hidden_entities(true);
442
	$ia = elgg_set_ignore_access(true);
443
444
	$options = [
445
		'type' => 'object',
446
		'subtype' => 'messages',
447
		'metadata_name' => 'fromId',
448
		'metadata_value' => $user->getGUID(),
449
		'limit' => 0,
450
	];
451
	$batch = new ElggBatch('elgg_get_entities_from_metadata', $options);
452
	foreach ($batch as $e) {
453
		$e->delete();
454
	}
455
456
	elgg_set_ignore_access($ia);
457
	access_show_hidden_entities($entity_disable_override);
458
}
459
460
/**
461
 * Register messages with ECML.
462
 *
463
 * @param string $hook
464
 * @param string $entity_type
465
 * @param string $return_value
466
 * @param array  $params
467
 *
468
 * @return array
469
 */
470
function messages_ecml_views_hook($hook, $entity_type, $return_value, $params) {
471
	$return_value['messages/messages'] = elgg_echo('messages');
472
473
	return $return_value;
474
}
475