This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * A diaspora* flavoured WP Post class. |
||
4 | * |
||
5 | * @package WP_To_Diaspora\Post |
||
6 | * @since 1.5.0 |
||
7 | */ |
||
8 | |||
9 | // Exit if accessed directly. |
||
10 | defined( 'ABSPATH' ) || exit; |
||
11 | |||
12 | use League\HTMLToMarkdown\HtmlConverter; |
||
13 | |||
14 | /** |
||
15 | * Custom diaspora* post class to manage all post related things. |
||
16 | * |
||
17 | * @since 1.5.0 |
||
18 | */ |
||
19 | class WP2D_Post { |
||
20 | |||
21 | /** |
||
22 | * The original post object. |
||
23 | * |
||
24 | * @since 1.5.0 |
||
25 | * |
||
26 | * @var WP_Post |
||
27 | */ |
||
28 | public $post; |
||
29 | |||
30 | /** |
||
31 | * The original post ID. |
||
32 | * |
||
33 | * @since 1.5.0 |
||
34 | * |
||
35 | * @var int |
||
36 | */ |
||
37 | public $ID; |
||
38 | |||
39 | /** |
||
40 | * If this post should be shared on diaspora*. |
||
41 | * |
||
42 | * @since 1.5.0 |
||
43 | * |
||
44 | * @var bool |
||
45 | */ |
||
46 | public $post_to_diaspora; |
||
47 | |||
48 | /** |
||
49 | * If a link back to the original post should be added. |
||
50 | * |
||
51 | * @since 1.5.0 |
||
52 | * |
||
53 | * @var bool |
||
54 | */ |
||
55 | public $fullentrylink; |
||
56 | |||
57 | /** |
||
58 | * What content gets posted. |
||
59 | * |
||
60 | * @since 1.5.0 |
||
61 | * |
||
62 | * @var string |
||
63 | */ |
||
64 | public $display; |
||
65 | |||
66 | /** |
||
67 | * The types of tags to post. (global,custom,post) |
||
68 | * |
||
69 | * @since 1.5.0 |
||
70 | * |
||
71 | * @var array |
||
72 | */ |
||
73 | public $tags_to_post; |
||
74 | |||
75 | /** |
||
76 | * The post's custom tags. |
||
77 | * |
||
78 | * @since 1.5.0 |
||
79 | * |
||
80 | * @var array |
||
81 | */ |
||
82 | public $custom_tags; |
||
83 | |||
84 | /** |
||
85 | * Aspects this post gets posted to. |
||
86 | * |
||
87 | * @since 1.5.0 |
||
88 | * |
||
89 | * @var array |
||
90 | */ |
||
91 | public $aspects; |
||
92 | |||
93 | /** |
||
94 | * Services this post gets posted to. |
||
95 | * |
||
96 | * @since 1.5.0 |
||
97 | * |
||
98 | * @var array |
||
99 | */ |
||
100 | public $services; |
||
101 | |||
102 | /** |
||
103 | * The post's history of diaspora* posts. |
||
104 | * |
||
105 | * @since 1.5.0 |
||
106 | * |
||
107 | * @var array |
||
108 | */ |
||
109 | public $post_history; |
||
110 | |||
111 | /** |
||
112 | * If the post actions have all been set up already. |
||
113 | * |
||
114 | * @since 1.5.0 |
||
115 | * |
||
116 | * @var boolean |
||
117 | */ |
||
118 | private static $is_set_up = false; |
||
119 | |||
120 | /** |
||
121 | * Setup all the necessary WP callbacks. |
||
122 | * |
||
123 | * @since 1.5.0 |
||
124 | */ |
||
125 | public static function setup() { |
||
126 | if ( self::$is_set_up ) { |
||
127 | return; |
||
128 | } |
||
129 | |||
130 | $instance = new WP2D_Post( null ); |
||
131 | |||
132 | // Notices when a post has been shared or if it has failed. |
||
133 | add_action( 'admin_notices', [ $instance, 'admin_notices' ] ); |
||
134 | add_action( 'admin_init', [ $instance, 'ignore_post_error' ] ); |
||
135 | |||
136 | // Handle diaspora* posting when saving the post. |
||
137 | add_action( 'save_post', [ $instance, 'post' ], 20, 2 ); |
||
138 | add_action( 'save_post', [ $instance, 'save_meta_box_data' ], 10 ); |
||
139 | |||
140 | // Add meta boxes. |
||
141 | add_action( 'add_meta_boxes', [ $instance, 'add_meta_boxes' ] ); |
||
142 | |||
143 | // AJAX callback for diaspora* post history. |
||
144 | add_action( 'wp_ajax_wp_to_diaspora_get_post_history', [ $instance, 'get_post_history_callback' ] ); |
||
145 | |||
146 | self::$is_set_up = true; |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Constructor. |
||
151 | * |
||
152 | * @since 1.5.0 |
||
153 | * |
||
154 | * @param int|WP_Post $post Post ID or the post itself. |
||
155 | */ |
||
156 | public function __construct( $post ) { |
||
157 | $this->assign_wp_post( $post ); |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * Assign the original WP_Post object and all the custom meta data. |
||
162 | * |
||
163 | * @since 1.5.0 |
||
164 | * |
||
165 | * @param int|WP_Post $post Post ID or the post itself. |
||
166 | */ |
||
167 | private function assign_wp_post( $post ) { |
||
168 | if ( $this->post = get_post( $post ) ) { |
||
169 | $this->ID = $this->post->ID; |
||
170 | |||
171 | $options = WP2D_Options::instance(); |
||
172 | |||
173 | // Assign all meta values, expanding non-existent ones with the defaults. |
||
174 | $meta_current = get_post_meta( $this->ID, '_wp_to_diaspora', true ); |
||
175 | $meta = wp_parse_args( |
||
176 | $meta_current, |
||
177 | $options->get_options() |
||
178 | ); |
||
179 | if ( $meta ) { |
||
180 | foreach ( $meta as $key => $value ) { |
||
181 | $this->$key = $value; |
||
182 | } |
||
183 | } |
||
184 | |||
185 | // If no WP2D meta data has been saved yet, this post shouldn't be published. |
||
186 | // This can happen if existing posts (before WP2D) get updated externally, not through the post edit screen. |
||
187 | // Check DiasPHPora/wp-to-diaspora#91 for reference. |
||
188 | // Also, when we have a post scheduled for publishing, don't touch it. |
||
189 | // This is important when modifying scheduled posts using Quick Edit. |
||
190 | if ( ! $meta_current && ! in_array( $this->post->post_status, [ 'auto-draft', 'future' ], true ) ) { |
||
191 | $this->post_to_diaspora = false; |
||
192 | } |
||
193 | |||
194 | $this->post_history = get_post_meta( $this->ID, '_wp_to_diaspora_post_history', true ); |
||
195 | } |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * Post to diaspora* when saving a post. |
||
200 | * |
||
201 | * @since 1.5.0 |
||
202 | * |
||
203 | * @todo Maybe somebody wants to share a password protected post to a closed aspect. |
||
204 | * |
||
205 | * @param integer $post_id ID of the post being saved. |
||
206 | * @param WP_Post $post Post object being saved. |
||
207 | * |
||
208 | * @return bool If the post was posted successfully. |
||
209 | */ |
||
210 | public function post( $post_id, $post ) { |
||
211 | // Ignore any revisions and auto-saves. |
||
212 | if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { |
||
213 | return false; |
||
214 | } |
||
215 | |||
216 | $this->assign_wp_post( $post ); |
||
217 | |||
218 | $options = WP2D_Options::instance(); |
||
219 | |||
220 | // Is this post type enabled for posting? |
||
221 | if ( ! in_array( $post->post_type, $options->get_option( 'enabled_post_types' ), true ) ) { |
||
222 | return false; |
||
223 | } |
||
224 | |||
225 | // Make sure we're posting to diaspora* and the post isn't password protected. |
||
226 | if ( ! ( $this->post_to_diaspora && 'publish' === $post->post_status && '' === $post->post_password ) ) { |
||
227 | return false; |
||
228 | } |
||
229 | |||
230 | // Unset post_to_diaspora meta field to prevent mistakenly republishing to diaspora*. |
||
231 | $meta = get_post_meta( $post_id, '_wp_to_diaspora', true ); |
||
232 | $meta['post_to_diaspora'] = false; |
||
233 | update_post_meta( $post_id, '_wp_to_diaspora', $meta ); |
||
234 | |||
235 | $status_message = $this->get_title_link(); |
||
236 | |||
237 | // Post the full post text, just the excerpt, or nothing at all? |
||
238 | if ( 'full' === $this->display ) { |
||
239 | $status_message .= $this->get_full_content(); |
||
240 | } elseif ( 'excerpt' === $this->display ) { |
||
241 | $status_message .= $this->get_excerpt_content(); |
||
242 | } |
||
243 | |||
244 | // Add the tags assigned to the post. |
||
245 | $status_message .= $this->get_tags_to_add(); |
||
246 | |||
247 | // Add the original entry link to the post? |
||
248 | $status_message .= $this->get_posted_at_link(); |
||
249 | |||
250 | $status_converter = new HtmlConverter( [ 'strip_tags' => true ] ); |
||
251 | $status_message = $status_converter->convert( $status_message ); |
||
252 | |||
253 | // Set up the connection to diaspora*. |
||
254 | $api = WP2D_Helpers::api_quick_connect(); |
||
255 | if ( empty( $status_message ) ) { |
||
256 | return false; |
||
257 | } |
||
258 | |||
259 | if ( $api->has_last_error() ) { |
||
260 | // Save the post error as post meta data, so we can display it to the user. |
||
261 | update_post_meta( $post_id, '_wp_to_diaspora_post_error', $api->get_last_error() ); |
||
262 | |||
263 | return false; |
||
264 | } |
||
265 | |||
266 | // Add services to share to via diaspora*. |
||
267 | $extra_data = [ |
||
268 | 'services' => $this->services, |
||
269 | ]; |
||
270 | |||
271 | // Try to post to diaspora*. |
||
272 | $response = $api->post( $status_message, $this->aspects, $extra_data ); |
||
273 | if ( ! $response ) { |
||
274 | return false; |
||
275 | } |
||
276 | |||
277 | // Save certain diaspora* post data as meta data for future reference. |
||
278 | $this->save_to_history( (object) $response ); |
||
279 | |||
280 | // If there is still a previous post error around, remove it. |
||
281 | delete_post_meta( $post_id, '_wp_to_diaspora_post_error' ); |
||
282 | |||
283 | // Prevent any duplicate hook firing. |
||
284 | remove_action( 'save_post', [ $this, 'post' ], 20, 2 ); |
||
285 | |||
286 | return true; |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Get the title of the post linking to the post itself. |
||
291 | * |
||
292 | * @since 1.5.0 |
||
293 | * |
||
294 | * @return string Post title as a link. |
||
295 | */ |
||
296 | private function get_title_link() { |
||
297 | $title = esc_html( $this->post->post_title ); |
||
298 | $permalink = get_permalink( $this->ID ); |
||
299 | $title_link = sprintf( '<strong><a href="%2$s" title="%2$s">%1$s</a></strong>', $title, $permalink ); |
||
300 | |||
301 | /** |
||
302 | * Filter the title link at the top of the post. |
||
303 | * |
||
304 | * @since 1.5.4.1 |
||
305 | * |
||
306 | * @param string $default The whole HTML of the title link to be outputted. |
||
307 | * @param WP2D_Post $wp2d_post This object, to allow total customisation of the title. |
||
308 | */ |
||
309 | return apply_filters( 'wp2d_title_filter', "<p>{$title_link}</p>", $this ); |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * Get the full post content with only default filters applied. |
||
314 | * |
||
315 | * @since 1.5.0 |
||
316 | * |
||
317 | * @return string The full post content. |
||
318 | */ |
||
319 | private function get_full_content() { |
||
320 | // Only allow certain shortcodes. |
||
321 | global $shortcode_tags; |
||
322 | $shortcode_tags_bkp = []; |
||
323 | |||
324 | foreach ( $shortcode_tags as $shortcode_tag => $shortcode_function ) { |
||
325 | if ( ! in_array( $shortcode_tag, apply_filters( 'wp2d_shortcodes_filter', [ 'wp_caption', 'caption', 'gallery' ] ), true ) ) { |
||
326 | $shortcode_tags_bkp[ $shortcode_tag ] = $shortcode_function; |
||
327 | unset( $shortcode_tags[ $shortcode_tag ] ); |
||
328 | } |
||
329 | } |
||
330 | |||
331 | // Disable all filters and then enable only defaults. This prevents additional filters from being posted to diaspora*. |
||
332 | remove_all_filters( 'the_content' ); |
||
333 | |||
334 | /** @var array $content_filters List of filters to apply to the content. */ |
||
335 | $content_filters = apply_filters( 'wp2d_content_filters_filter', [ 'do_shortcode', 'wptexturize', 'convert_smilies', 'convert_chars', 'wpautop', 'shortcode_unautop', 'prepend_attachment', [ $this, 'embed_remove' ] ] ); |
||
336 | foreach ( $content_filters as $filter ) { |
||
337 | add_filter( 'the_content', $filter ); |
||
338 | } |
||
339 | |||
340 | // Extract URLs from [embed] shortcodes. |
||
341 | add_filter( 'embed_oembed_html', [ $this, 'embed_url' ], 10, 2 ); |
||
342 | |||
343 | // Add the pretty caption after the images. |
||
344 | add_filter( 'img_caption_shortcode', [ $this, 'custom_img_caption' ], 10, 3 ); |
||
345 | |||
346 | // Overwrite the native shortcode handler to add pretty captions. |
||
347 | // http://wordpress.stackexchange.com/a/74675/54456 for explanation. |
||
348 | add_shortcode( 'gallery', [ $this, 'custom_gallery_shortcode' ] ); |
||
349 | |||
350 | $post_content = apply_filters( 'the_content', $this->post->post_content ); |
||
351 | |||
352 | // Put the removed shortcode tags back again. |
||
353 | $shortcode_tags += $shortcode_tags_bkp; // phpcs:ignore |
||
354 | |||
355 | /** |
||
356 | * Filter the full content of the post. |
||
357 | * |
||
358 | * @since 2.1.0 |
||
359 | * |
||
360 | * @param string $default The whole HTML of the post to be outputted. |
||
361 | * @param WP2D_Post $wp2d_post This object, to allow total customisation of the post. |
||
362 | */ |
||
363 | return apply_filters( 'wp2d_post_filter', $post_content, $this ); |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | * Get the post's excerpt in a nice format. |
||
368 | * |
||
369 | * @since 1.5.0 |
||
370 | * |
||
371 | * @return string Post's excerpt. |
||
372 | */ |
||
373 | private function get_excerpt_content() { |
||
374 | // Look for the excerpt in the following order: |
||
375 | // 1. Custom post excerpt. |
||
376 | // 2. Text up to the <!--more--> tag. |
||
377 | // 3. Manually trimmed content. |
||
378 | $content = $this->post->post_content; |
||
379 | $excerpt = $this->post->post_excerpt; |
||
380 | if ( '' === $excerpt ) { |
||
381 | if ( $more_pos = strpos( $content, '<!--more' ) ) { |
||
382 | $excerpt = substr( $content, 0, $more_pos ); |
||
383 | } else { |
||
384 | $excerpt = wp_trim_words( $content, 42, '[...]' ); |
||
385 | } |
||
386 | } |
||
387 | |||
388 | /** |
||
389 | * Filter the excerpt of the post. |
||
390 | * |
||
391 | * @since 2.1.0 |
||
392 | * |
||
393 | * @param string $default The whole HTML of the excerpt to be outputted. |
||
394 | * @param WP2D_Post $wp2d_post This object, to allow total customisation of the excerpt. |
||
395 | */ |
||
396 | return apply_filters( 'wp2d_excerpt_filter', "<p>{$excerpt}</p>", $this ); |
||
397 | } |
||
398 | |||
399 | /** |
||
400 | * Get a string of tags that have been added to the post. |
||
401 | * |
||
402 | * @since 1.5.0 |
||
403 | * |
||
404 | * @return string Tags added to the post. |
||
405 | */ |
||
406 | private function get_tags_to_add() { |
||
407 | $options = WP2D_Options::instance(); |
||
408 | $tags_to_post = $this->tags_to_post; |
||
409 | $tags_to_add = ''; |
||
410 | $diaspora_tags = []; |
||
411 | |||
412 | // Add any diaspora* tags? |
||
413 | if ( ! empty( $tags_to_post ) ) { |
||
414 | // The diaspora* tags to add to the post. |
||
415 | $diaspora_tags_tmp = []; |
||
416 | |||
417 | // Add global tags? |
||
418 | $global_tags = $options->get_option( 'global_tags' ); |
||
419 | if ( is_array( $global_tags ) && in_array( 'global', $tags_to_post, true ) ) { |
||
420 | $diaspora_tags_tmp += array_flip( $global_tags ); |
||
421 | } |
||
422 | |||
423 | // Add custom tags? |
||
424 | if ( is_array( $this->custom_tags ) && in_array( 'custom', $tags_to_post, true ) ) { |
||
425 | $diaspora_tags_tmp += array_flip( $this->custom_tags ); |
||
426 | } |
||
427 | |||
428 | // Add post tags? |
||
429 | $post_tags = wp_get_post_tags( $this->ID, [ 'fields' => 'slugs' ] ); |
||
430 | if ( is_array( $post_tags ) && in_array( 'post', $tags_to_post, true ) ) { |
||
431 | $diaspora_tags_tmp += array_flip( $post_tags ); |
||
432 | } |
||
433 | |||
434 | // Get an array of cleaned up tags. |
||
435 | // NOTE: Validate method needs a variable, as it's passed by reference! |
||
436 | $diaspora_tags_tmp = array_keys( $diaspora_tags_tmp ); |
||
437 | $options->validate_tags( $diaspora_tags_tmp ); |
||
438 | |||
439 | // Get all the tags and list them all nicely in a row. |
||
440 | foreach ( $diaspora_tags_tmp as $tag ) { |
||
0 ignored issues
–
show
|
|||
441 | $diaspora_tags[] = '#' . $tag; |
||
442 | } |
||
443 | |||
444 | // Add all the found tags. |
||
445 | if ( ! empty( $diaspora_tags ) ) { |
||
446 | $tags_to_add = implode( ' ', $diaspora_tags ) . '<br/>'; |
||
447 | } |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * Filter the tags of the post. |
||
452 | * |
||
453 | * @since 2.1.0 |
||
454 | * |
||
455 | * @param string $default The whole string of tags to be outputted. |
||
456 | * @param array $tags All tags that are assigned to this post. |
||
457 | * @param WP2D_Post $wp2d_post This object, to allow total customisation of the tags output. |
||
458 | */ |
||
459 | return apply_filters( 'wp2d_tags_filter', $tags_to_add, $diaspora_tags, $this ); |
||
460 | } |
||
461 | |||
462 | /** |
||
463 | * Get the link to the original post. |
||
464 | * |
||
465 | * @since 1.5.0 |
||
466 | * |
||
467 | * @return string Original post link. |
||
468 | */ |
||
469 | private function get_posted_at_link() { |
||
470 | if ( $this->fullentrylink ) { |
||
471 | $prefix = esc_html__( 'Originally posted at:', 'wp-to-diaspora' ); |
||
472 | $permalink = get_permalink( $this->ID ); |
||
473 | $title = esc_html__( 'Permalink', 'wp-to-diaspora' ); |
||
474 | $posted_at_link = sprintf( '%1$s <a href="%2$s" title="%3$s">%2$s</a>', $prefix, $permalink, $title ); |
||
475 | |||
476 | /** |
||
477 | * Filter the "Originally posted at" link at the bottom of the post. |
||
478 | * |
||
479 | * @since 1.5.4.1 |
||
480 | * |
||
481 | * @param string $default The whole HTML of the text and link to be outputted. |
||
482 | * @param WP2D_Post $wp2d_post This object, to allow total customisation of the title. |
||
483 | * @param string $prefix The "Originally posted at:" prefix before the link. |
||
484 | */ |
||
485 | return apply_filters( 'wp2d_posted_at_link_filter', "<p>{$posted_at_link}</p>", $this, $prefix ); |
||
486 | } |
||
487 | |||
488 | return ''; |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Save the details of the new diaspora* post to this post's history. |
||
493 | * |
||
494 | * @since 1.5.0 |
||
495 | * |
||
496 | * @param object $response Response from the API containing the diaspora* post details. |
||
497 | */ |
||
498 | private function save_to_history( $response ) { |
||
499 | // Make sure the post history is an array. |
||
500 | if ( empty( $this->post_history ) ) { |
||
501 | $this->post_history = []; |
||
502 | } |
||
503 | |||
504 | // Add a new entry to the history. |
||
505 | $this->post_history[] = [ |
||
506 | 'id' => $response->id, |
||
507 | 'guid' => $response->guid, |
||
508 | 'created_at' => $this->post->post_modified, |
||
509 | 'aspects' => $this->aspects, |
||
510 | 'nsfw' => $response->nsfw, |
||
511 | 'post_url' => $response->permalink, |
||
512 | ]; |
||
513 | |||
514 | update_post_meta( $this->ID, '_wp_to_diaspora_post_history', $this->post_history ); |
||
515 | } |
||
516 | |||
517 | /** |
||
518 | * Return URL from [embed] shortcode instead of generated iframe. |
||
519 | * |
||
520 | * @since 1.5.0 |
||
521 | * @see WP_Embed::shortcode() |
||
522 | * |
||
523 | * @param mixed $html The cached HTML result, stored in post meta. |
||
524 | * @param string $url The attempted embed URL. |
||
525 | * |
||
526 | * @return string URL of the embed. |
||
527 | */ |
||
528 | public function embed_url( $html, $url ) { |
||
529 | return $url; |
||
530 | } |
||
531 | |||
532 | /** |
||
533 | * Removes '[embed]' and '[/embed]' left by embed_url. |
||
534 | * |
||
535 | * @since 1.5.0 |
||
536 | * |
||
537 | * @todo It would be great to fix it using only one filter. |
||
538 | * It's happening because embed filter is being removed by remove_all_filters('the_content') on WP2D_Post::post(). |
||
539 | * |
||
540 | * @param string $content Content of the post. |
||
541 | * |
||
542 | * @return string The content with the embed tags removed. |
||
543 | */ |
||
544 | public function embed_remove( $content ) { |
||
545 | return str_replace( [ '[embed]', '[/embed]' ], [ '<p>', '</p>' ], $content ); |
||
546 | } |
||
547 | |||
548 | /** |
||
549 | * Prettify the image caption. |
||
550 | * |
||
551 | * @since 1.5.3 |
||
552 | * |
||
553 | * @param string $caption Caption to be prettified. |
||
554 | * |
||
555 | * @return string Prettified image caption. |
||
556 | */ |
||
557 | public function get_img_caption( $caption ) { |
||
558 | $caption = trim( $caption ); |
||
559 | if ( '' === $caption ) { |
||
560 | return ''; |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * Filter the image caption to be displayed after images with captions. |
||
565 | * |
||
566 | * @since 1.5.3 |
||
567 | * |
||
568 | * @param string $default The whole HTML of the caption. |
||
569 | * @param string $caption The caption text. |
||
570 | */ |
||
571 | return apply_filters( 'wp2d_image_caption', "<blockquote>{$caption}</blockquote>", $caption ); |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * Filter the default caption shortcode output. |
||
576 | * |
||
577 | * @since 1.5.3 |
||
578 | * |
||
579 | * @see img_caption_shortcode() |
||
580 | * |
||
581 | * @param string $empty The caption output. Default empty. |
||
582 | * @param array $attr Attributes of the caption shortcode. |
||
583 | * @param string $content The image element, possibly wrapped in a hyperlink. |
||
584 | * |
||
585 | * @return string The caption shortcode output. |
||
586 | */ |
||
587 | public function custom_img_caption( $empty, $attr, $content ) { |
||
588 | $content = do_shortcode( $content ); |
||
589 | |||
590 | // If a caption attribute is defined, we'll add it after the image. |
||
591 | if ( isset( $attr['caption'] ) && '' !== $attr['caption'] ) { |
||
592 | $content .= "\n" . $this->get_img_caption( $attr['caption'] ); |
||
593 | } |
||
594 | |||
595 | return $content; |
||
596 | } |
||
597 | |||
598 | /** |
||
599 | * Create a custom gallery caption output. |
||
600 | * |
||
601 | * @since 1.5.3 |
||
602 | * |
||
603 | * @param array $attr Gallery attributes. |
||
604 | * |
||
605 | * @return string |
||
606 | */ |
||
607 | public function custom_gallery_shortcode( $attr ) { |
||
608 | // Try user value and fall back to default value in WordPress. |
||
609 | $captiontag = $attr['captiontag'] ?? ( current_theme_supports( 'html5', 'gallery' ) ? 'figcaption' : 'dd' ); |
||
610 | |||
611 | // Let WordPress create the regular gallery. |
||
612 | $gallery = gallery_shortcode( $attr ); |
||
613 | |||
614 | // Change the content of the captions. |
||
615 | $gallery = preg_replace_callback( |
||
616 | '~(<' . $captiontag . '.*>)(.*)(</' . $captiontag . '>)~mUus', |
||
617 | [ $this, 'custom_gallery_regex_callback' ], |
||
618 | $gallery |
||
619 | ); |
||
620 | |||
621 | return $gallery; |
||
622 | } |
||
623 | |||
624 | /** |
||
625 | * Change the result of the regex match from custom_gallery_shortcode. |
||
626 | * |
||
627 | * @param array $m Regex matches. |
||
628 | * |
||
629 | * @return string Prettified gallery image caption. |
||
630 | */ |
||
631 | public function custom_gallery_regex_callback( $m ) { |
||
632 | return $this->get_img_caption( $m[2] ); |
||
633 | } |
||
634 | |||
635 | /* |
||
636 | * META BOX |
||
637 | */ |
||
638 | |||
639 | /** |
||
640 | * Adds a meta box to the main column on the enabled Post Types' edit screens. |
||
641 | * |
||
642 | * @since 1.5.0 |
||
643 | */ |
||
644 | public function add_meta_boxes() { |
||
645 | $options = WP2D_Options::instance(); |
||
646 | foreach ( $options->get_option( 'enabled_post_types' ) as $post_type ) { |
||
647 | add_meta_box( |
||
648 | 'wp_to_diaspora_meta_box', |
||
649 | 'WP to diaspora*', |
||
650 | [ $this, 'meta_box_render' ], |
||
651 | $post_type, |
||
652 | 'side', |
||
653 | 'high' |
||
654 | ); |
||
655 | } |
||
656 | } |
||
657 | |||
658 | /** |
||
659 | * Prints the meta box content. |
||
660 | * |
||
661 | * @since 1.5.0 |
||
662 | * |
||
663 | * @param WP_Post $post The object for the current post. |
||
664 | */ |
||
665 | public function meta_box_render( $post ) { |
||
666 | $this->assign_wp_post( $post ); |
||
667 | |||
668 | // Add an nonce field so we can check for it later. |
||
669 | wp_nonce_field( 'wp_to_diaspora_meta_box', 'wp_to_diaspora_meta_box_nonce' ); |
||
670 | |||
671 | // Get the default values to use, but give priority to the meta data already set. |
||
672 | $options = WP2D_Options::instance(); |
||
673 | |||
674 | // Make sure we have some value for post meta fields. |
||
675 | $this->custom_tags = $this->custom_tags ?: []; |
||
676 | |||
677 | // If this post is already published, don't post again to diaspora* by default. |
||
678 | $this->post_to_diaspora = ( $this->post_to_diaspora && 'publish' !== get_post_status( $this->ID ) ); |
||
679 | $this->aspects = $this->aspects ?: []; |
||
680 | $this->services = $this->services ?: []; |
||
681 | |||
682 | // Have we already posted on diaspora*? |
||
683 | $diaspora_post_url = '#'; |
||
684 | if ( is_array( $this->post_history ) ) { |
||
685 | $latest_post = end( $this->post_history ); |
||
686 | $diaspora_post_url = $latest_post['post_url']; |
||
687 | } |
||
688 | ?> |
||
689 | <p<?php echo '#' === $diaspora_post_url ? ' style="display: none;"' : ''; ?>><a id="diaspora-post-url" href="<?php echo esc_attr( $diaspora_post_url ); ?>" target="_blank"><?php esc_html_e( 'Already posted to diaspora*.', 'wp-to-diaspora' ); ?></a></p> |
||
690 | |||
691 | <p><?php $options->post_to_diaspora_render( $this->post_to_diaspora ); ?></p> |
||
692 | <p><?php $options->fullentrylink_render( $this->fullentrylink ); ?></p> |
||
693 | <p><?php $options->display_render( $this->display ); ?></p> |
||
694 | <p><?php $options->tags_to_post_render( $this->tags_to_post ); ?></p> |
||
695 | <p><?php $options->custom_tags_render( $this->custom_tags ); ?></p> |
||
696 | <p><?php $options->aspects_services_render( [ 'aspects', $this->aspects ] ); ?></p> |
||
697 | <p><?php $options->aspects_services_render( [ 'services', $this->services ] ); ?></p> |
||
698 | |||
699 | <?php |
||
700 | } |
||
701 | |||
702 | /** |
||
703 | * When the post is saved, save our meta data. |
||
704 | * |
||
705 | * @since 1.5.0 |
||
706 | * |
||
707 | * @param integer $post_id The ID of the post being saved. |
||
708 | */ |
||
709 | public function save_meta_box_data( $post_id ) { |
||
710 | /* |
||
711 | * We need to verify this came from our screen and with proper authorization, |
||
712 | * because the save_post action can be triggered at other times. |
||
713 | */ |
||
714 | if ( ! $this->is_safe_to_save() ) { |
||
715 | return; |
||
716 | } |
||
717 | |||
718 | /* OK, it's safe for us to save the data now. */ |
||
719 | |||
720 | // Meta data to save. |
||
721 | $meta_to_save = $_POST['wp_to_diaspora_settings']; // phpcs:ignore |
||
722 | $options = WP2D_Options::instance(); |
||
723 | |||
724 | // Checkboxes. |
||
725 | $options->validate_checkboxes( [ 'post_to_diaspora', 'fullentrylink' ], $meta_to_save ); |
||
726 | |||
727 | // Single Selects. |
||
728 | $options->validate_single_selects( 'display', $meta_to_save ); |
||
729 | |||
730 | // Multiple Selects. |
||
731 | $options->validate_multi_selects( 'tags_to_post', $meta_to_save ); |
||
732 | |||
733 | // Save custom tags as array. |
||
734 | $options->validate_tags( $meta_to_save['custom_tags'] ); |
||
735 | |||
736 | // Clean up the list of aspects. If the list is empty, only use the 'Public' aspect. |
||
737 | $options->validate_aspects_services( $meta_to_save['aspects'], [ 'public' ] ); |
||
738 | |||
739 | // Clean up the list of services. |
||
740 | $options->validate_aspects_services( $meta_to_save['services'] ); |
||
741 | |||
742 | // Update the meta data for this post. |
||
743 | update_post_meta( $post_id, '_wp_to_diaspora', $meta_to_save ); |
||
744 | } |
||
745 | |||
746 | /** |
||
747 | * Perform all checks to see if we are allowed to save the meta data. |
||
748 | * |
||
749 | * @since 1.5.0 |
||
750 | * |
||
751 | * @return bool If the verification checks have passed. |
||
752 | */ |
||
753 | private function is_safe_to_save() { |
||
754 | // Verify that our nonce is set and valid. |
||
755 | if ( ! ( isset( $_POST['wp_to_diaspora_meta_box_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_to_diaspora_meta_box_nonce'] ), 'wp_to_diaspora_meta_box' ) ) ) { |
||
756 | return false; |
||
757 | } |
||
758 | |||
759 | // If this is an autosave, our form has not been submitted, so we don't want to do anything. |
||
760 | if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { |
||
761 | return false; |
||
762 | } |
||
763 | |||
764 | // Check the user's permissions. |
||
765 | $permission = ( isset( $_POST['post_type'] ) && 'page' === $_POST['post_type'] ) ? 'edit_pages' : 'edit_posts'; |
||
766 | if ( ! current_user_can( $permission, $this->ID ) ) { |
||
767 | return false; |
||
768 | } |
||
769 | |||
770 | // Make real sure that we have some meta data to save. |
||
771 | if ( ! isset( $_POST['wp_to_diaspora_settings'] ) ) { |
||
772 | return false; |
||
773 | } |
||
774 | |||
775 | return true; |
||
776 | } |
||
777 | |||
778 | /** |
||
779 | * Add admin notices when a post gets displayed. |
||
780 | * |
||
781 | * @since 1.5.0 |
||
782 | * |
||
783 | * @todo Ignore post error with AJAX. |
||
784 | */ |
||
785 | public function admin_notices() { |
||
786 | global $post, $pagenow; |
||
787 | if ( ! $post || 'post.php' !== $pagenow ) { |
||
788 | return; |
||
789 | } |
||
790 | |||
791 | if ( ( $error = get_post_meta( $post->ID, '_wp_to_diaspora_post_error', true ) ) && is_wp_error( $error ) ) { |
||
792 | // Are we adding a help tab link to this notice? |
||
793 | $help_link = WP2D_Contextual_Help::get_help_tab_quick_link( $error ); |
||
794 | |||
795 | // This notice will only be shown if posting to diaspora* has failed. |
||
796 | printf( |
||
797 | '<div class="error notice is-dismissible"><p>%1$s %2$s %3$s <a href="%4$s">%5$s</a></p></div>', |
||
798 | esc_html__( 'Failed to post to diaspora*.', 'wp-to-diaspora' ), |
||
799 | esc_html( $error->get_error_message() ), |
||
800 | $help_link, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
||
801 | esc_url( add_query_arg( 'wp2d_ignore_post_error', '' ) ), |
||
802 | esc_html__( 'Ignore', 'wp-to-diaspora' ) |
||
803 | ); |
||
804 | } elseif ( ( $diaspora_post_history = get_post_meta( $post->ID, '_wp_to_diaspora_post_history', true ) ) && is_array( $diaspora_post_history ) ) { |
||
805 | // Get the latest post from the history. |
||
806 | $latest_post = end( $diaspora_post_history ); |
||
807 | |||
808 | // Only show if this post is showing a message and the post is a fresh share. |
||
809 | if ( isset( $_GET['message'] ) && $post->post_modified === $latest_post['created_at'] ) { // phpcs:ignore |
||
810 | printf( |
||
811 | '<div class="updated notice is-dismissible"><p>%1$s <a href="%2$s" target="_blank">%3$s</a></p></div>', |
||
812 | esc_html__( 'Successfully posted to diaspora*.', 'wp-to-diaspora' ), |
||
813 | esc_url( $latest_post['post_url'] ), |
||
814 | esc_html__( 'View Post', 'wp-to-diaspora' ) |
||
815 | ); |
||
816 | } |
||
817 | } |
||
818 | } |
||
819 | |||
820 | /** |
||
821 | * Delete the error post meta data if it gets ignored. |
||
822 | * |
||
823 | * @since 1.5.0 |
||
824 | */ |
||
825 | public function ignore_post_error() { |
||
826 | // If "Ignore" link has been clicked, delete the post error meta data. |
||
827 | if ( isset( $_GET['wp2d_ignore_post_error'], $_GET['post'] ) ) { // phpcs:ignore |
||
828 | delete_post_meta( absint( $_GET['post'] ), '_wp_to_diaspora_post_error' ); // phpcs:ignore |
||
829 | } |
||
830 | } |
||
831 | |||
832 | /** |
||
833 | * Get latest diaspora* share of this post. |
||
834 | * |
||
835 | * @since 3.0.0 |
||
836 | */ |
||
837 | public function get_post_history_callback() { |
||
838 | View Code Duplication | if ( ! check_ajax_referer( 'wp2d', 'nonce', false ) ) { |
|
0 ignored issues
–
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. ![]() |
|||
839 | wp_send_json_error( [ |
||
840 | 'message' => 'WP2D: ' . __( 'AJAX Nonce failure.', 'wp-to-diaspora' ), |
||
841 | ] ); |
||
842 | } |
||
843 | |||
844 | $post_id = sanitize_key( $_REQUEST['post_id'] ?? '' ); |
||
845 | if ( ! is_numeric( $post_id ) ) { |
||
846 | return; |
||
847 | } |
||
848 | |||
849 | if ( $error = get_post_meta( $post_id, '_wp_to_diaspora_post_error', true ) ) { |
||
850 | // This notice will only be shown if posting to diaspora* has failed. |
||
851 | wp_send_json_error( [ |
||
852 | 'message' => esc_html__( 'Failed to post to diaspora*.', 'wp-to-diaspora' ) . ' - ' . esc_html( $error ), |
||
853 | ] ); |
||
854 | } |
||
855 | |||
856 | if ( ( $diaspora_post_history = get_post_meta( $post_id, '_wp_to_diaspora_post_history', true ) ) && is_array( $diaspora_post_history ) ) { |
||
857 | // Get the latest post from the history. |
||
858 | $latest_post = end( $diaspora_post_history ); |
||
859 | |||
860 | // Only show if this post is a fresh share. |
||
861 | if ( get_post( $post_id )->post_modified === $latest_post['created_at'] ) { // phpcs:ignore |
||
862 | wp_send_json_success( [ |
||
863 | 'message' => esc_html__( 'Successfully posted to diaspora*.', 'wp-to-diaspora' ), |
||
864 | 'action' => [ |
||
865 | 'label' => esc_html__( 'View Post', 'wp-to-diaspora' ), |
||
866 | 'url' => esc_url( $latest_post['post_url'] ), |
||
867 | ], |
||
868 | ] ); |
||
869 | } |
||
870 | } |
||
871 | } |
||
872 | } |
||
873 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.