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

mod/messages/start.php (3 issues)

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