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
|
|||
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 |
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.