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

mod/thewire/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 wire plugin
4
 *
5
 * Forked from Curverider's version
6
 *
7
 * JHU/APL Contributors:
8
 * Cash Costello
9
 * Clark Updike
10
 * John Norton
11
 * Max Thomas
12
 * Nathan Koterba
13
 */
14
15
elgg_register_event_handler('init', 'system', 'thewire_init');
16
17
/**
18
 * The Wire initialization
19
 */
20
function thewire_init() {
21
22
	// register the wire's JavaScript
23
	$thewire_js = elgg_get_simplecache_url('thewire.js');
24
	elgg_register_js('elgg.thewire', $thewire_js, 'footer');
25
26
	elgg_register_ajax_view('thewire/previous');
27
28
	// add a site navigation item
29
	elgg_register_menu_item('site', [
30
		'name' => 'thewire',
31
		'text' => elgg_echo('thewire'),
32
		'href' => 'thewire/all',
33
	]);
34
35
	// owner block menu
36
	elgg_register_plugin_hook_handler('register', 'menu:owner_block', 'thewire_owner_block_menu');
37
38
	// remove edit and access and add thread, reply, view previous
39
	elgg_register_plugin_hook_handler('register', 'menu:entity', 'thewire_setup_entity_menu_items');
40
	
41
	// Extend system CSS with our own styles, which are defined in the thewire/css view
42
	elgg_extend_view('elgg.css', 'thewire/css');
43
44
	// Register a page handler, so we can have nice URLs
45
	elgg_register_page_handler('thewire', 'thewire_page_handler');
46
47
	// Register a URL handler for thewire posts
48
	elgg_register_plugin_hook_handler('entity:url', 'object', 'thewire_set_url');
49
50
	// Register for notifications
51
	elgg_register_notification_event('object', 'thewire');
52
	elgg_register_plugin_hook_handler('prepare', 'notification:create:object:thewire', 'thewire_prepare_notification');
53
	elgg_register_plugin_hook_handler('get', 'subscriptions', 'thewire_add_original_poster');
54
55
	// allow to be liked
56
	elgg_register_plugin_hook_handler('likes:is_likable', 'object:thewire', 'Elgg\Values::getTrue');
57
58
	elgg_register_plugin_hook_handler('unit_test', 'system', 'thewire_test');
59
}
60
61
/**
62
 * The wire page handler
63
 *
64
 * Supports:
65
 * thewire/all                  View site wire posts
66
 * thewire/owner/<username>     View this user's wire posts
67
 * thewire/following/<username> View the posts of those this user follows
68
 * thewire/reply/<guid>         Reply to a post
69
 * thewire/view/<guid>          View a post
70
 * thewire/thread/<id>          View a conversation thread
71
 * thewire/tag/<tag>            View wire posts tagged with <tag>
72
 *
73
 * @param array $page From the page_handler function
74
 * @return bool
75
 */
76
function thewire_page_handler($page) {
77
78
	if (!isset($page[0])) {
79
		$page = ['all'];
80
	}
81
82
	switch ($page[0]) {
83
		case "all":
84
			echo elgg_view_resource('thewire/everyone');
85
			break;
86
87
		case "friends":
88
			echo elgg_view_resource('thewire/friends');
89
			break;
90
91
		case "owner":
92
			echo elgg_view_resource('thewire/owner');
93
			break;
94
95
		case "view":
96
			echo elgg_view_resource('thewire/view', [
97
				'guid' => elgg_extract(1, $page),
98
			]);
99
			break;
100
101
		case "thread":
102
			echo elgg_view_resource('thewire/thread', [
103
				'thread_id' => elgg_extract(1, $page),
104
			]);
105
			break;
106
107
		case "reply":
108
			echo elgg_view_resource('thewire/reply', [
109
				'guid' => elgg_extract(1, $page),
110
			]);
111
			break;
112
113
		case "tag":
114
			echo elgg_view_resource('thewire/tag', [
115
				'tag' => elgg_extract(1, $page),
116
			]);
117
			break;
118
119
		case "previous":
120
			echo elgg_view_resource('thewire/previous', [
121
				'guid' => elgg_extract(1, $page),
122
			]);
123
			break;
124
125
		default:
126
			return false;
127
	}
128
	return true;
129
}
130
131
/**
132
 * Override the url for a wire post to return the thread
133
 *
134
 * @param string $hook
135
 * @param string $type
136
 * @param string $url
137
 * @param array  $params
138
 * @return string
139
 */
140
function thewire_set_url($hook, $type, $url, $params) {
141
	$entity = elgg_extract('entity', $params);
142
	if (elgg_instanceof($entity, 'object', 'thewire')) {
143
		return "thewire/view/" . $entity->guid;
144
	}
145
}
146
147
/**
148
 * Prepare a notification message about a new wire post
149
 *
150
 * @param string                          $hook         Hook name
151
 * @param string                          $type         Hook type
152
 * @param Elgg\Notifications\Notification $notification The notification to prepare
153
 * @param array                           $params       Hook parameters
154
 * @return Elgg\Notifications\Notification
155
 */
156
function thewire_prepare_notification($hook, $type, $notification, $params) {
157
158
	$entity = $params['event']->getObject();
159
	$owner = $params['event']->getActor();
160
	$recipient = $params['recipient'];
161
	$language = $params['language'];
162
	$method = $params['method'];
163
	$descr = $entity->description;
164
165
	$subject = elgg_echo('thewire:notify:subject', [$owner->name], $language);
166
	if ($entity->reply) {
167
		$parent = thewire_get_parent($entity->guid);
168
		if ($parent) {
169
			$parent_owner = $parent->getOwnerEntity();
170
			$body = elgg_echo('thewire:notify:reply', [$owner->name, $parent_owner->name], $language);
171
		}
172
	} else {
173
		$body = elgg_echo('thewire:notify:post', [$owner->name], $language);
174
	}
175
	$body .= "\n\n" . $descr . "\n\n";
176
	$body .= elgg_echo('thewire:notify:footer', [$entity->getURL()], $language);
177
178
	$notification->subject = $subject;
179
	$notification->body = $body;
180
	$notification->summary = elgg_echo('thewire:notify:summary', [$descr], $language);
181
	$notification->url = $entity->getURL();
182
	return $notification;
183
}
184
185
/**
186
 * Get an array of hashtags from a text string
187
 *
188
 * @param string $text The text of a post
189
 * @return array
190
 */
191
function thewire_get_hashtags($text) {
192
	// beginning of text or white space followed by hashtag
193
	// hashtag must begin with # and contain at least one character not digit, space, or punctuation
194
	$matches = [];
195
	preg_match_all('/(^|[^\w])#(\w*[^\s\d!-\/:-@]+\w*)/', $text, $matches);
196
	return $matches[2];
197
}
198
199
/**
200
 * Replace urls, hash tags, and @'s by links
201
 *
202
 * @param string $text The text of a post
203
 * @return string
204
 */
205
function thewire_filter($text) {
206
	$text = ' ' . $text;
207
208
	// email addresses
209
	$text = preg_replace(
210
				'/(^|[^\w])([\w\-\.]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})/i',
211
				'$1<a href="mailto:$2@$3">$2@$3</a>',
212
				$text);
213
214
	// links
215
	$text = parse_urls($text);
216
217
	// usernames
218
	$text = preg_replace(
219
				'/(^|[^\w])@([\p{L}\p{Nd}._]+)/u',
220
				'$1<a href="' . elgg_get_site_url() . 'thewire/owner/$2">@$2</a>',
221
				$text);
222
223
	// hashtags
224
	$text = preg_replace(
225
				'/(^|[^\w])#(\w*[^\s\d!-\/:-@]+\w*)/',
226
				'$1<a href="' . elgg_get_site_url() . 'thewire/tag/$2">#$2</a>',
227
				$text);
228
229
	return trim($text);
230
}
231
232
/**
233
 * Create a new wire post.
234
 *
235
 * @param string $text        The post text
236
 * @param int    $userid      The user's guid
237
 * @param int    $access_id   Public/private etc
238
 * @param int    $parent_guid Parent post guid (if any)
239
 * @param string $method      The method (default: 'site')
240
 * @return guid or false if failure
241
 */
242
function thewire_save_post($text, $userid, $access_id, $parent_guid = 0, $method = "site") {
243
	$post = new ElggObject();
244
245
	$post->subtype = "thewire";
246
	$post->owner_guid = $userid;
247
	$post->access_id = $access_id;
248
249
	// Character limit is now from config
250
	$limit = elgg_get_plugin_setting('limit', 'thewire');
251
	if ($limit > 0) {
252
		$text = elgg_substr($text, 0, $limit);
253
	}
254
255
	// no html tags allowed so we escape
256
	$post->description = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
257
258
	$post->method = $method; //method: site, email, api, ...
259
260
	$tags = thewire_get_hashtags($text);
261
	if ($tags) {
262
		$post->tags = $tags;
263
	}
264
265
	// must do this before saving so notifications pick up that this is a reply
266
	if ($parent_guid) {
267
		$post->reply = true;
268
	}
269
270
	$guid = $post->save();
271
272
	// set thread guid
273
	if ($parent_guid) {
274
		$post->addRelationship($parent_guid, 'parent');
275
		
276
		// name conversation threads by guid of first post (works even if first post deleted)
277
		$parent_post = get_entity($parent_guid);
278
		$post->wire_thread = $parent_post->wire_thread;
279
	} else {
280
		// first post in this thread
281
		$post->wire_thread = $guid;
282
	}
283
284
	if ($guid) {
285
		elgg_create_river_item([
286
			'view' => 'river/object/thewire/create',
287
			'action_type' => 'create',
288
			'subject_guid' => $post->owner_guid,
289
			'object_guid' => $post->guid,
290
		]);
291
292
		// let other plugins know we are setting a user status
293
		$params = [
294
			'entity' => $post,
295
			'user' => $post->getOwnerEntity(),
296
			'message' => $post->description,
297
			'url' => $post->getURL(),
298
			'origin' => 'thewire',
299
		];
300
		elgg_trigger_plugin_hook('status', 'user', $params);
301
	}
302
	
303
	return $guid;
304
}
305
306
/**
307
 * Add temporary subscription for original poster if not already registered to
308
 * receive a notification of reply
309
 *
310
 * @param string $hook          Hook name
311
 * @param string $type          Hook type
312
 * @param array  $subscriptions Subscriptions for a notification event
313
 * @param array  $params        Parameters including the event
314
 *
315
 * @return void|array
316
 */
317
function thewire_add_original_poster($hook, $type, $subscriptions, $params) {
318
	$event = elgg_extract('event', $params);
319
	$entity = $event->getObject();
320
	if (!($entity instanceof ElggWire)) {
321
		return;
322
	}
323
	
324
	$parents = $entity->getEntitiesFromRelationship([
325
		'type' => 'object',
326
		'subtype' => 'thewire',
327
		'relationship' => 'parent',
328
	]);
329
	if (empty($parents)) {
330
		return ;
331
	}
332
	
333
	/* @var $parent ElggWire */
334
	$parent = $parents[0];
335
	// do not add a subscription if reply was to self
336
	if ($parent->getOwnerGUID() === $entity->getOwnerGUID()) {
337
		return;
338
	}
339
	
340
	if (array_key_exists($parent->getOwnerGUID(), $subscriptions)) {
341
		// already in the list
342
		return;
343
	}
344
	
345
	/* @var $parent_owner ElggUser */
346
	$parent_owner = $parent->getOwnerEntity();
347
	$personal_methods = $parent_owner->getNotificationSettings();
348
	$methods = [];
349
	foreach ($personal_methods as $method => $state) {
350
		if ($state) {
351
			$methods[] = $method;
352
		}
353
	}
354
	
355
	if (empty($methods)) {
356
		return;
357
	}
358
	
359
	$subscriptions[$parent->getOwnerGUID()] = $methods;
360
	return $subscriptions;
361
}
362
363
/**
364
 * Get the latest wire guid - used for ajax update
365
 *
366
 * @return guid
367
 */
368
function thewire_latest_guid() {
369
	$post = elgg_get_entities([
370
		'type' => 'object',
371
		'subtype' => 'thewire',
372
		'limit' => 1,
373
	]);
374
	if ($post) {
375
		return $post[0]->guid;
376
	} else {
377
		return 0;
378
	}
379
}
380
381
/**
382
 * Get the parent of a wire post
383
 *
384
 * @param int $post_guid The guid of the reply
385
 * @return ElggObject or null
386
 */
387
function thewire_get_parent($post_guid) {
388
	$parents = elgg_get_entities_from_relationship([
389
		'relationship' => 'parent',
390
		'relationship_guid' => $post_guid,
391
		'limit' => 1,
392
	]);
393
	if ($parents) {
394
		return $parents[0];
395
	}
396
	return null;
397
}
398
399
/**
400
 * Sets up the entity menu for thewire
401
 *
402
 * Adds reply, thread, and view previous links. Removes edit and access.
403
 *
404
 * @param string $hook   Hook name
405
 * @param string $type   Hook type
406
 * @param array  $value  Array of menu items
407
 * @param array  $params Array with the entity
408
 * @return array
409
 */
410
function thewire_setup_entity_menu_items($hook, $type, $value, $params) {
411
	$handler = elgg_extract('handler', $params, false);
412
	if ($handler != 'thewire') {
413
		return;
414
	}
415
416
	foreach ($value as $index => $item) {
417
		$name = $item->getName();
418
		if ($name == 'edit') {
419
			unset($value[$index]);
420
		}
421
	}
422
423
	$entity = $params['entity'];
424
425
	if (elgg_is_logged_in()) {
426
		$options = [
427
			'name' => 'reply',
428
			'text' => elgg_echo('reply'),
429
			'href' => "thewire/reply/$entity->guid",
430
			'priority' => 150,
431
		];
432
		$value[] = ElggMenuItem::factory($options);
433
	}
434
435 View Code Duplication
	if ($entity->reply) {
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...
436
		$options = [
437
			'name' => 'previous',
438
			'text' => elgg_echo('previous'),
439
			'href' => "thewire/previous/$entity->guid",
440
			'priority' => 160,
441
			'link_class' => 'thewire-previous',
442
			'title' => elgg_echo('thewire:previous:help'),
443
		];
444
		$value[] = ElggMenuItem::factory($options);
445
	}
446
447
	$options = [
448
		'name' => 'thread',
449
		'text' => elgg_echo('thewire:thread'),
450
		'href' => "thewire/thread/$entity->wire_thread",
451
		'priority' => 170,
452
	];
453
	$value[] = ElggMenuItem::factory($options);
454
455
	return $value;
456
}
457
458
/**
459
 * Add a menu item to an ownerblock
460
 *
461
 * @return array
462
 */
463 View Code Duplication
function thewire_owner_block_menu($hook, $type, $return, $params) {
464
	$user = elgg_extract('entity', $params);
465
	if (!$user instanceof \ElggUser) {
466
		return;
467
	}
468
469
	$return[] = \ElggMenuItem::factory([
470
		'name' => 'thewire',
471
		'text' => elgg_echo('item:object:thewire'),
472
		'href' => "thewire/owner/{$params['entity']->username}",
473
	]);
474
	
475
	return $return;
476
}
477
478
/**
479
 * Runs unit tests for the wire
480
 *
481
 * @return array
482
 */
483
function thewire_test($hook, $type, $value, $params) {
484
	$value[] = elgg_get_plugins_path() . 'thewire/tests/regex.php';
485
	return $value;
486
}
487