PluginProbe
ActivityPub / 2.5.0
ActivityPub v2.5.0
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / class-shortcodes.php

class-shortcodes.php in ActivityPub 2.5.0, at includes/class-shortcodes.php

599 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Activitypub;
3
4 use function Activitypub\esc_hashtag;
5
6 class Shortcodes {
7 /**
8 * Register the shortcodes
9 */
10 public static function register() {
11 foreach ( get_class_methods( self::class ) as $shortcode ) {
12 if ( 'init' !== $shortcode ) {
13 add_shortcode( 'ap_' . $shortcode, array( self::class, $shortcode ) );
14 }
15 }
16 }
17
18 /**
19 * Unregister the shortcodes
20 */
21 public static function unregister() {
22 foreach ( get_class_methods( self::class ) as $shortcode ) {
23 if ( 'init' !== $shortcode ) {
24 remove_shortcode( 'ap_' . $shortcode );
25 }
26 }
27 }
28
29 /**
30 * Generates output for the 'ap_hashtags' shortcode
31 *
32 * @param array $atts The Shortcode attributes.
33 * @param string $content The ActivityPub post-content.
34 * @param string $tag The tag/name of the Shortcode.
35 *
36 * @return string The post tags as hashtags.
37 */
38 public static function hashtags( $atts, $content, $tag ) {
39 $item = self::get_item();
40
41 if ( ! $item ) {
42 return '';
43 }
44
45 $tags = \get_the_tags( $item->ID );
46
47 if ( ! $tags ) {
48 return '';
49 }
50
51 $hash_tags = array();
52
53 foreach ( $tags as $tag ) {
54 $hash_tags[] = \sprintf(
55 '<a rel="tag" class="hashtag u-tag u-category" href="%s">%s</a>',
56 \esc_url( \get_tag_link( $tag ) ),
57 esc_hashtag( $tag->name )
58 );
59 }
60
61 return \implode( ' ', $hash_tags );
62 }
63
64 /**
65 * Generates output for the 'ap_title' Shortcode
66 *
67 * @param array $atts The Shortcode attributes.
68 * @param string $content The ActivityPub post-content.
69 * @param string $tag The tag/name of the Shortcode.
70 *
71 * @return string The post title.
72 */
73 public static function title( $atts, $content, $tag ) {
74 $item = self::get_item();
75
76 if ( ! $item ) {
77 return '';
78 }
79
80 return \wp_strip_all_tags( \get_the_title( $item->ID ), true );
81 }
82
83 /**
84 * Generates output for the 'ap_excerpt' Shortcode
85 *
86 * @param array $atts The Shortcode attributes.
87 * @param string $content The ActivityPub post-content.
88 * @param string $tag The tag/name of the Shortcode.
89 *
90 * @return string The post excerpt.
91 */
92 public static function excerpt( $atts, $content, $tag ) {
93 $item = self::get_item();
94
95 if ( ! $item ) {
96 return '';
97 }
98
99 $atts = shortcode_atts(
100 array( 'length' => ACTIVITYPUB_EXCERPT_LENGTH ),
101 $atts,
102 $tag
103 );
104
105 $excerpt_length = intval( $atts['length'] );
106
107 if ( 0 === $excerpt_length ) {
108 $excerpt_length = ACTIVITYPUB_EXCERPT_LENGTH;
109 }
110
111 $excerpt = \get_post_field( 'post_excerpt', $item );
112
113 if ( 'attachment' === $item->post_type ) {
114 // get title of attachment with fallback to alt text.
115 $content = wp_get_attachment_caption( $item->ID );
116 if ( empty( $content ) ) {
117 $content = get_post_meta( $item->ID, '_wp_attachment_image_alt', true );
118 }
119 } elseif ( '' === $excerpt ) {
120 $content = \get_post_field( 'post_content', $item );
121
122 // An empty string will make wp_trim_excerpt do stuff we do not want.
123 if ( '' !== $content ) {
124 $excerpt = \strip_shortcodes( $content );
125
126 /** This filter is documented in wp-includes/post-template.php */
127 $excerpt = \apply_filters( 'the_content', $excerpt );
128 $excerpt = \str_replace( ']]>', ']]&gt;', $excerpt );
129 }
130 }
131
132 // Strip out any remaining tags.
133 $excerpt = \wp_strip_all_tags( $excerpt );
134
135 $excerpt_more = \apply_filters( 'activitypub_excerpt_more', ' [&hellip;]' );
136 $excerpt_more_len = strlen( $excerpt_more );
137
138 // We now have a excerpt, but we need to check it's length, it may be longer than we want for two reasons:
139 //
140 // * The user has entered a manual excerpt which is longer that what we want.
141 // * No manual excerpt exists so we've used the content which might be longer than we want.
142 //
143 // Either way, let's trim it up if we need too. Also, don't forget to take into account the more indicator
144 // as part of the total length.
145 //
146
147 // Setup a variable to hold the current excerpts length.
148 $current_excerpt_length = strlen( $excerpt );
149
150 // Setup a variable to keep track of our target length.
151 $target_excerpt_length = $excerpt_length - $excerpt_more_len;
152
153 // Setup a variable to keep track of the current max length.
154 $current_excerpt_max = $target_excerpt_length;
155
156 // This is a loop since we can't calculate word break the string after 'the_excpert' filter has run (we would break
157 // all kinds of html tags), so we have to cut the excerpt down a bit at a time until we hit our target length.
158 while ( $current_excerpt_length > $target_excerpt_length && $current_excerpt_max > 0 ) {
159 // Trim the excerpt based on wordwrap() positioning.
160 // Note: we're using <br> as the linebreak just in case there are any newlines existing in the excerpt from the user.
161 // There won't be any <br> left after we've run wp_strip_all_tags() in the code above, so they're
162 // safe to use here. It won't be included in the final excerpt as the substr() will trim it off.
163 $excerpt = substr( $excerpt, 0, strpos( wordwrap( $excerpt, $current_excerpt_max, '<br>' ), '<br>' ) );
164
165 // If something went wrong, or we're in a language that wordwrap() doesn't understand,
166 // just chop it off and don't worry about breaking in the middle of a word.
167 if ( strlen( $excerpt ) > $excerpt_length - $excerpt_more_len ) {
168 $excerpt = substr( $excerpt, 0, $current_excerpt_max );
169 }
170
171 // Add in the more indicator.
172 $excerpt = $excerpt . $excerpt_more;
173
174 // Run it through the excerpt filter which will add some html tags back in.
175 $excerpt_filtered = apply_filters( 'the_excerpt', $excerpt );
176
177 // Now set the current excerpt length to this new filtered length.
178 $current_excerpt_length = strlen( $excerpt_filtered );
179
180 // Check to see if we're over the target length.
181 if ( $current_excerpt_length > $target_excerpt_length ) {
182 // If so, remove 20 characters from the current max and run the loop again.
183 $current_excerpt_max = $current_excerpt_max - 20;
184 }
185 }
186
187 return \apply_filters( 'the_excerpt', $excerpt );
188 }
189
190 /**
191 * Generates output for the 'ap_content' Shortcode
192 *
193 * @param array $atts The Shortcode attributes.
194 * @param string $content The ActivityPub post-content.
195 * @param string $tag The tag/name of the Shortcode.
196 *
197 * @return string The post content.
198 */
199 public static function content( $atts, $content, $tag ) {
200 $item = self::get_item();
201
202 if ( ! $item ) {
203 return '';
204 }
205
206 // prevent inception
207 remove_shortcode( 'ap_content' );
208
209 $atts = shortcode_atts(
210 array( 'apply_filters' => 'yes' ),
211 $atts,
212 $tag
213 );
214
215 $content = '';
216
217 if ( 'attachment' === $item->post_type ) {
218 // get title of attachment with fallback to alt text.
219 $content = wp_get_attachment_caption( $item->ID );
220 if ( empty( $content ) ) {
221 $content = get_post_meta( $item->ID, '_wp_attachment_image_alt', true );
222 }
223 } else {
224 $content = \get_post_field( 'post_content', $item );
225
226 if ( 'yes' === $atts['apply_filters'] ) {
227 $content = \apply_filters( 'the_content', $content );
228 } else {
229 $content = do_blocks( $content );
230 $content = wptexturize( $content );
231 $content = wp_filter_content_tags( $content );
232 }
233
234 // replace script and style elements
235 $content = \preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $content );
236 $content = strip_shortcodes( $content );
237 $content = \trim( \preg_replace( '/[\n\r\t]/', '', $content ) );
238 }
239
240 add_shortcode( 'ap_content', array( 'Activitypub\Shortcodes', 'content' ) );
241
242 return $content;
243 }
244
245 /**
246 * Generates output for the 'ap_permalink' Shortcode
247 *
248 * @param array $atts The Shortcode attributes.
249 * @param string $content The ActivityPub post-content.
250 * @param string $tag The tag/name of the Shortcode.
251 *
252 * @return string The post permalink.
253 */
254 public static function permalink( $atts, $content, $tag ) {
255 $item = self::get_item();
256
257 if ( ! $item ) {
258 return '';
259 }
260
261 $atts = shortcode_atts(
262 array(
263 'type' => 'url',
264 ),
265 $atts,
266 $tag
267 );
268
269 if ( 'url' === $atts['type'] ) {
270 return \esc_url( \get_permalink( $item->ID ) );
271 }
272
273 return \sprintf(
274 '<a href="%1$s" class="status-link unhandled-link">%1$s</a>',
275 \esc_url( \get_permalink( $item->ID ) )
276 );
277 }
278
279 /**
280 * Generates output for the 'ap_shortlink' Shortcode
281 *
282 * @param array $atts The Shortcode attributes.
283 * @param string $content The ActivityPub post-content.
284 * @param string $tag The tag/name of the Shortcode.
285 *
286 * @return string The post shortlink.
287 */
288 public static function shortlink( $atts, $content, $tag ) {
289 $item = self::get_item();
290
291 if ( ! $item ) {
292 return '';
293 }
294
295 $atts = shortcode_atts(
296 array(
297 'type' => 'url',
298 ),
299 $atts,
300 $tag
301 );
302
303 if ( 'url' === $atts['type'] ) {
304 return \esc_url( \wp_get_shortlink( $item->ID ) );
305 }
306
307 return \sprintf(
308 '<a href="%1$s" class="status-link unhandled-link">%1$s</a>',
309 \esc_url( \wp_get_shortlink( $item->ID ) )
310 );
311 }
312
313 /**
314 * Generates output for the 'ap_image' Shortcode
315 *
316 * @param array $atts The Shortcode attributes.
317 * @param string $content The ActivityPub post-content.
318 * @param string $tag The tag/name of the Shortcode.
319 *
320 * @return string
321 */
322 public static function image( $atts, $content, $tag ) {
323 $item = self::get_item();
324
325 if ( ! $item ) {
326 return '';
327 }
328
329 $atts = shortcode_atts(
330 array(
331 'type' => 'full',
332 ),
333 $atts,
334 $tag
335 );
336
337 $size = 'full';
338
339 if ( in_array(
340 $atts['type'],
341 array( 'thumbnail', 'medium', 'large', 'full' ),
342 true
343 ) ) {
344 $size = $atts['type'];
345 }
346
347 $image = \get_the_post_thumbnail_url( $item->ID, $size );
348
349 if ( ! $image ) {
350 return '';
351 }
352
353 return \esc_url( $image );
354 }
355
356 /**
357 * Generates output for the 'ap_hashcats' Shortcode
358 *
359 * @param array $atts The Shortcode attributes.
360 * @param string $content The ActivityPub post-content.
361 * @param string $tag The tag/name of the Shortcode.
362 *
363 * @return string The post categories as hashtags.
364 */
365 public static function hashcats( $atts, $content, $tag ) {
366 $item = self::get_item();
367
368 if ( ! $item ) {
369 return '';
370 }
371
372 $categories = \get_the_category( $item->ID );
373
374 if ( ! $categories ) {
375 return '';
376 }
377
378 $hash_tags = array();
379
380 foreach ( $categories as $category ) {
381 $hash_tags[] = \sprintf(
382 '<a rel="tag" class="hashtag u-tag u-category" href="%s">%s</a>',
383 \esc_url( \get_category_link( $category ) ),
384 esc_hashtag( $category->name )
385 );
386 }
387
388 return \implode( ' ', $hash_tags );
389 }
390
391 /**
392 * Generates output for the 'ap_author' Shortcode
393 *
394 * @param array $atts The Shortcode attributes.
395 * @param string $content The ActivityPub post-content.
396 * @param string $tag The tag/name of the Shortcode.
397 *
398 * @return string The author name.
399 */
400 public static function author( $atts, $content, $tag ) {
401 $item = self::get_item();
402
403 if ( ! $item ) {
404 return '';
405 }
406
407 $author_id = \get_post_field( 'post_author', $item->ID );
408 $name = \get_the_author_meta( 'display_name', $author_id );
409
410 if ( ! $name ) {
411 return '';
412 }
413
414 return wp_strip_all_tags( $name );
415 }
416
417 /**
418 * Generates output for the 'ap_authorurl' Shortcode
419 *
420 * @param array $atts The Shortcode attributes.
421 * @param string $content The ActivityPub post-content.
422 * @param string $tag The tag/name of the Shortcode.
423 *
424 * @return string The author URL.
425 */
426 public static function authorurl( $atts, $content, $tag ) {
427 $item = self::get_item();
428
429 if ( ! $item ) {
430 return '';
431 }
432
433 $author_id = \get_post_field( 'post_author', $item->ID );
434 $url = \get_the_author_meta( 'user_url', $author_id );
435
436 if ( ! $url ) {
437 return '';
438 }
439
440 return \esc_url( $url );
441 }
442
443 /**
444 * Generates output for the 'ap_blogurl' Shortcode
445 *
446 * @param array $atts The Shortcode attributes.
447 * @param string $content The ActivityPub post-content.
448 * @param string $tag The tag/name of the Shortcode.
449 *
450 * @return string The site URL.
451 */
452 public static function blogurl( $atts, $content, $tag ) {
453 return \esc_url( \get_bloginfo( 'url' ) );
454 }
455
456 /**
457 * Generates output for the 'ap_blogname' Shortcode
458 *
459 * @param array $atts The Shortcode attributes.
460 * @param string $content The ActivityPub post-content.
461 * @param string $tag The tag/name of the Shortcode.
462 *
463 * @return string
464 */
465 public static function blogname( $atts, $content, $tag ) {
466 return \wp_strip_all_tags( \get_bloginfo( 'name' ) );
467 }
468
469 /**
470 * Generates output for the 'ap_blogdesc' Shortcode
471 *
472 * @param array $atts The Shortcode attributes.
473 * @param string $content The ActivityPub post-content.
474 * @param string $tag The tag/name of the Shortcode.
475 *
476 * @return string The site description.
477 */
478 public static function blogdesc( $atts, $content, $tag ) {
479 return \wp_strip_all_tags( \get_bloginfo( 'description' ) );
480 }
481
482 /**
483 * Generates output for the 'ap_date' Shortcode
484 *
485 * @param array $atts The Shortcode attributes.
486 * @param string $content The ActivityPub post-content.
487 * @param string $tag The tag/name of the Shortcode.
488 *
489 * @return string The post date.
490 */
491 public static function date( $atts, $content, $tag ) {
492 $item = self::get_item();
493
494 if ( ! $item ) {
495 return '';
496 }
497
498 $datetime = \get_post_datetime( $item );
499 $dateformat = \get_option( 'date_format' );
500 $timeformat = \get_option( 'time_format' );
501
502 $date = $datetime->format( $dateformat );
503
504 if ( ! $date ) {
505 return '';
506 }
507
508 return $date;
509 }
510
511 /**
512 * Generates output for the 'ap_time' Shortcode
513 *
514 * @param array $atts The Shortcode attributes.
515 * @param string $content The ActivityPub post-content.
516 * @param string $tag The tag/name of the Shortcode.
517 *
518 * @return string The post time.
519 */
520 public static function time( $atts, $content, $tag ) {
521 $item = self::get_item();
522
523 if ( ! $item ) {
524 return '';
525 }
526
527 $datetime = \get_post_datetime( $item );
528 $dateformat = \get_option( 'date_format' );
529 $timeformat = \get_option( 'time_format' );
530
531 $date = $datetime->format( $timeformat );
532
533 if ( ! $date ) {
534 return '';
535 }
536
537 return $date;
538 }
539
540 /**
541 * Generates output for the 'ap_datetime' Shortcode
542 *
543 * @param array $atts The Shortcode attributes.
544 * @param string $content The ActivityPub post-content.
545 * @param string $tag The tag/name of the Shortcode.
546 *
547 * @return string The post date/time.
548 */
549 public static function datetime( $atts, $content, $tag ) {
550 $item = self::get_item();
551
552 if ( ! $item ) {
553 return '';
554 }
555
556 $datetime = \get_post_datetime( $item );
557 $dateformat = \get_option( 'date_format' );
558 $timeformat = \get_option( 'time_format' );
559
560 $date = $datetime->format( $dateformat . ' @ ' . $timeformat );
561
562 if ( ! $date ) {
563 return '';
564 }
565
566 return $date;
567 }
568
569 /**
570 * Get a WordPress item to federate.
571 *
572 * Checks if item (WP_Post) is "public", a supported post type
573 * and not password protected.
574 *
575 * @return null|WP_Post The WordPress item.
576 */
577 protected static function get_item() {
578 $post = \get_post();
579
580 if ( ! $post ) {
581 return null;
582 }
583
584 if ( 'publish' !== \get_post_status( $post ) ) {
585 return null;
586 }
587
588 if ( \post_password_required( $post ) ) {
589 return null;
590 }
591
592 if ( ! \in_array( \get_post_type( $post ), \get_post_types_by_support( 'activitypub' ), true ) ) {
593 return null;
594 }
595
596 return $post;
597 }
598 }
599