Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
18.39% covered (danger)
18.39%
48 / 261
21.74% covered (danger)
21.74%
5 / 23
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_Likes_Settings
18.39% covered (danger)
18.39%
48 / 261
21.74% covered (danger)
21.74%
5 / 23
8481.20
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 add_likes_to_sharing_meta_box_title
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 add_meta_box
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 meta_box_content
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
42
 is_enabled_sitewide
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 meta_box_save
13.64% covered (danger)
13.64%
3 / 22
0.00% covered (danger)
0.00%
0 / 1
277.66
 sharing_meta_box_content
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 sharing_menu
n/a
0 / 0
n/a
0 / 0
1
 sharing_page
n/a
0 / 0
n/a
0 / 0
1
 updated_message
n/a
0 / 0
n/a
0 / 0
3
 sharing_block
n/a
0 / 0
n/a
0 / 0
1
 is_post_likeable
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
72
 is_likes_button_visible
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
3.33
 is_likes_visible
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 is_likes_module_enabled
70.37% covered (warning)
70.37%
19 / 27
0.00% covered (danger)
0.00%
0 / 1
24.52
 is_single_post_enabled
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 get_options
50.00% covered (danger)
50.00%
11 / 22
0.00% covered (danger)
0.00%
0 / 1
22.50
 is_index_enabled
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 is_single_page_enabled
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 is_attachment_enabled
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 admin_settings_init
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 1
12
 reblogs_enabled_sitewide
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 is_comments_enabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 admin_settings_callback
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
272
 process_update_requests_if_sharedaddy_not_loaded
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
42
 admin_settings_showbuttonon_init
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
 admin_settings_showbuttonon_callback
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
72
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3use Automattic\Jetpack\Status\Host;
4use Automattic\Jetpack\Sync\Settings;
5
6/**
7 * Jetpack likes settings class.
8 */
9class Jetpack_Likes_Settings {
10
11    /**
12     * Determines whether the module runs in the Jetpack plugin, as opposed to WP.com Simple site environment
13     *
14     * @var bool
15     */
16    public $in_jetpack = true;
17
18    /**
19     * Constructor function.
20     */
21    public function __construct() {
22        $this->in_jetpack = ! ( new Host() )->is_wpcom_simple();
23    }
24
25    /**
26     * Replaces the "Sharing" title for the post screen metabox with "Likes and Shares"
27     */
28    public function add_likes_to_sharing_meta_box_title() {
29        return __( 'Likes and Shares', 'jetpack' );
30    }
31
32    /**
33     * Adds a metabox to the post screen if the sharing one doesn't currently exist.
34     */
35    public function add_meta_box() {
36        if (
37            /**
38             * Allow disabling of the Likes metabox on the post editor screen.
39             *
40             * @module likes
41             *
42             * @since 2.2.0
43             *
44             * @param bool false Should the Likes metabox be disabled? Default to false.
45             */
46        apply_filters( 'post_flair_disable', false )
47        ) {
48            return;
49        }
50
51        $post_types = get_post_types( array( 'public' => true ) );
52        /**
53         * Filters the Likes metabox title.
54         *
55         * @module likes
56         *
57         * @since 2.2.0
58         *
59         * @param string Likes metabox title. Default to "Likes".
60         */
61        $title = apply_filters( 'likes_meta_box_title', __( 'Likes', 'jetpack' ) );
62        foreach ( $post_types as $post_type ) {
63            add_meta_box( 'likes_meta', $title, array( $this, 'meta_box_content' ), $post_type, 'side', 'default', array( '__back_compat_meta_box' => true ) );
64        }
65    }
66
67    /**
68     * Shows the likes option in the post screen metabox.
69     *
70     * @param object $post - the post object.
71     */
72    public function meta_box_content( $post ) {
73        $post_id         = ! empty( $post->ID ) ? (int) $post->ID : get_the_ID();
74        $checked         = true;
75        $disabled        = ! $this->is_enabled_sitewide();
76        $switched_status = get_post_meta( $post_id, 'switch_like_status', true );
77
78        if ( $disabled && empty( $switched_status ) || ! $disabled && $switched_status === '0' ) {
79            $checked = false;
80        }
81
82        /**
83         * Fires before the Likes meta box content in the post editor.
84         *
85         * @module likes
86         *
87         * @since 2.2.0
88         *
89         * @param WP_Post|array|null $post Post data.
90         */
91        do_action( 'start_likes_meta_box_content', $post );
92        ?>
93
94        <p>
95            <label for="wpl_enable_post_likes">
96                <input type="checkbox" name="wpl_enable_post_likes" id="wpl_enable_post_likes" value="1" <?php checked( $checked ); ?>>
97                <?php esc_html_e( 'Show likes.', 'jetpack' ); ?>
98            </label>
99            <input type="hidden" name="wpl_like_status_hidden" value="1" />
100            <?php wp_nonce_field( 'likes-and-shares', '_likesharenonce' ); ?>
101        </p>
102        <?php
103        /**
104         * Fires after the Likes meta box content in the post editor.
105         *
106         * @module likes
107         *
108         * @since 2.2.0
109         *
110         * @param WP_Post|array|null $post Post data.
111         */
112        do_action( 'end_likes_meta_box_content', $post );
113    }
114
115    /**
116     * Returns the current state of the "WordPress.com Likes are" option.
117     *
118     * @return boolean true if enabled sitewide, false if not
119     */
120    public function is_enabled_sitewide() {
121        /**
122         * Filters whether Likes are enabled by default on all posts.
123         * true if enabled sitewide, false if not.
124         *
125         * @module likes
126         *
127         * @since 2.2.0
128         *
129         * @param bool $option Are Likes enabled sitewide.
130         */
131        return (bool) apply_filters( 'wpl_is_enabled_sitewide', ! Jetpack_Options::get_option_and_ensure_autoload( 'disabled_likes', 0 ) );
132    }
133
134    /**
135     * Handle meta box saving.
136     *
137     * @param int $post_id - the post ID.
138     */
139    public function meta_box_save( $post_id ) {
140        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
141            return $post_id;
142        }
143
144        if ( empty( $_POST['wpl_like_status_hidden'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- we're not changing anything on the site.
145            return $post_id;
146        }
147
148        if ( ! isset( $_POST['_likesharenonce'] ) || ! wp_verify_nonce( $_POST['_likesharenonce'], 'likes-and-shares' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- WordPress core doesn't unslash or verify nonces either.
149            return $post_id;
150        }
151
152        // Record sharing disable. Only needs to be done for WPCOM.
153        if ( ! $this->in_jetpack ) {
154            if ( isset( $_POST['post_type'] ) && in_array( $_POST['post_type'], get_post_types( array( 'public' => true ) ), true ) ) {
155                if ( ! isset( $_POST['wpl_enable_post_sharing'] ) ) {
156                    update_post_meta( $post_id, 'sharing_disabled', 1 );
157                } else {
158                    delete_post_meta( $post_id, 'sharing_disabled' );
159                }
160            }
161        }
162
163        if ( 'post' === $_POST['post_type'] ) {
164            if ( ! current_user_can( 'edit_post', $post_id ) ) {
165                return $post_id;
166            }
167        }
168
169        // Record a change in like status for this post - only if it contradicts the
170        // site like setting. If it doesn't contradict, then we delete the new individual status.
171        if ( ! $this->is_enabled_sitewide() && ! empty( $_POST['wpl_enable_post_likes'] ) ) {
172            // Likes turned on for individual posts. User wants to add the button to a single post.
173            update_post_meta( $post_id, 'switch_like_status', 1 );
174        } elseif ( $this->is_enabled_sitewide() && empty( $_POST['wpl_enable_post_likes'] ) ) {
175            // Likes turned on for all posts. User wants to remove the button from a single post.
176            update_post_meta( $post_id, 'switch_like_status', 0 );
177        } elseif (
178        ( ! $this->is_enabled_sitewide() && empty( $_POST['wpl_enable_post_likes'] ) ) ||
179        ( $this->is_enabled_sitewide() && ! empty( $_POST['wpl_enable_post_likes'] ) )
180        ) {
181            // User wants to update the likes button status for an individual post, but the new status
182            // is the same as if they're asking for the default behavior according to the current Likes setting.
183            // So we delete the meta.
184            delete_post_meta( $post_id, 'switch_like_status' );
185        }
186
187        return $post_id;
188    }
189
190    /**
191     * WordPress.com: Metabox option for sharing (sharedaddy will handle this on the JP blog).
192     *
193     * @param object $post - the post object.
194     */
195    public function sharing_meta_box_content( $post ) {
196        $post_id  = ! empty( $post->ID ) ? (int) $post->ID : get_the_ID();
197        $disabled = get_post_meta( $post_id, 'sharing_disabled', true );
198        ?>
199        <p>
200            <label for="wpl_enable_post_sharing">
201                <input type="checkbox" name="wpl_enable_post_sharing" id="wpl_enable_post_sharing" value="1" <?php checked( ! $disabled ); ?>>
202                <?php esc_html_e( 'Show sharing buttons.', 'jetpack' ); ?>
203            </label>
204            <input type="hidden" name="wpl_sharing_status_hidden" value="1" />
205        </p>
206        <?php
207    }
208
209    /**
210     * Adds the 'sharing' menu to the settings menu.
211     * Only ran if sharedaddy and publicize are not already active.
212     *
213     * @deprecated 13.2
214     */
215    public function sharing_menu() {
216        add_submenu_page( 'options-general.php', esc_html__( 'Sharing Settings', 'jetpack' ), esc_html__( 'Sharing', 'jetpack' ), 'manage_options', 'sharing', array( $this, 'sharing_page' ) );
217    }
218
219    /**
220     * Provides a sharing page with the sharing_global_options hook
221     * so we can display the setting.
222     * Only ran if sharedaddy and publicize are not already active.
223     *
224     * @deprecated 13.2
225     */
226    public function sharing_page() {
227        $this->updated_message();
228        ?>
229        <div class="wrap">
230            <div class="icon32" id="icon-options-general"><br /></div>
231            <h1><?php esc_html_e( 'Sharing Settings', 'jetpack' ); ?></h1>
232            <?php
233            /** This action is documented in modules/sharedaddy/sharing.php */
234            do_action( 'pre_admin_screen_sharing' );
235            ?>
236            <?php $this->sharing_block(); ?>
237        </div>
238        <?php
239    }
240
241    /**
242     * Returns the settings have been saved message.
243     *
244     * @deprecated 13.2
245     */
246    public function updated_message() {
247        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- ignoring since we are just displaying that the settings have been saved and not making  any other changes to the site.
248        if ( isset( $_GET['update'] ) && 'saved' === $_GET['update'] ) {
249            echo '<div class="updated"><p>' . esc_html__( 'Settings have been saved', 'jetpack' ) . '</p></div>';
250        }
251    }
252
253    /**
254     * Returns just the "sharing buttons" w/ like option block, so it can be inserted into different sharing page contexts
255     *
256     * @deprecated 13.2
257     */
258    public function sharing_block() {
259        ?>
260        <h2><?php esc_html_e( 'Sharing Buttons', 'jetpack' ); ?></h2>
261        <form method="post" action="">
262            <table class="form-table">
263                <tbody>
264                <?php
265                /** This action is documented in modules/sharedaddy/sharing.php */
266                do_action( 'sharing_global_options' );
267                ?>
268                </tbody>
269            </table>
270
271            <p class="submit">
272            <input type="submit" name="submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes', 'jetpack' ); ?>" />
273            <?php wp_nonce_field( 'sharing-options' ); ?>
274        </form>
275        <?php
276    }
277
278    /**
279     * Are likes enabled for this post?
280     *
281     * @param int $post_id - the post ID.
282     * @return bool
283     */
284    public function is_post_likeable( $post_id = 0 ) {
285        $post = get_post( $post_id );
286        if ( ! $post || is_wp_error( $post ) ) {
287            return false;
288        }
289
290        $sitewide_likes_enabled = (bool) $this->is_enabled_sitewide();
291        $post_likes_switched    = get_post_meta( $post->ID, 'switch_like_status', true );
292
293        /*
294         * On WPCOM, headstart was inserting bad data for post_likes_switched.
295         * it was wrapping the boolean value in an array. The array is always truthy regardless of its contents.
296         * There was another bug where truthy values were ignored if the global like setting was false.
297         * So in effect, the values for headstart never had an inpact.
298         * Delete the $post_likes_switched flag in this case in order to keep the behaviour as it was.
299         */
300        if ( is_array( $post_likes_switched ) ) {
301            $post_likes_switched = null;
302        }
303
304        /*
305         * on WPCOM, we need to look at post edit date so we don't break old posts
306         * if post edit date predates this code, stick with the former (buggy) behavior
307         * see: p7DVsv-64H-p2
308         */
309        $last_modified_time = strtotime( $post->post_modified_gmt );
310
311        $behavior_was_changed_at = strtotime( '2019-02-22 00:40:42' );
312
313        if ( $this->in_jetpack || $last_modified_time > $behavior_was_changed_at ) {
314            /*
315             * the new and improved behavior on Jetpack and recent WPCOM posts:
316             * $post_likes_switched is empty to follow site setting,
317             * 0 if we want likes disabled, 1 if we want likes enabled.
318             */
319            return $post_likes_switched || ( $sitewide_likes_enabled && $post_likes_switched !== '0' );
320        }
321
322        // implicit else (old behavior): $post_likes_switched simply inverts the global setting.
323        return ( (bool) $post_likes_switched ) xor $sitewide_likes_enabled;
324    }
325
326    /**
327     * Is the like button itself visible (as opposed to the reblog button)
328     *
329     * If called from within The Loop or if called with a $post_id set, then the post will be checked.
330     * Otherwise the sitewide setting will be used.
331     *
332     * @param int $post_id The ID of the post being rendered. Defaults to the current post if called from within The Loop.
333     * @return bool
334     */
335    public function is_likes_button_visible( $post_id = 0 ) {
336        if ( in_the_loop() || $post_id ) {
337            // If in The Loop, is_post_likeable will check the current post.
338            return $this->is_post_likeable( $post_id );
339        } else {
340            // Otherwise, check and see if likes are enabled sitewide.
341            return $this->is_enabled_sitewide();
342        }
343    }
344
345    /**
346     * Are likes visible in this context?
347     *
348     * Some of this code was taken and modified from sharing_display() to ensure
349     * similar logic and filters apply here, too.
350     */
351    public function is_likes_visible() {
352        if ( Settings::is_syncing() ) {
353            return false;
354        }
355
356        return $this->is_likes_button_visible() && $this->is_likes_module_enabled();
357    }
358
359    /**
360     * Apply filters to determine if the likes module itself is enabled
361     *
362     * @return bool
363     */
364    public function is_likes_module_enabled() {
365        global $wp_current_filter; // Used to apply 'sharing_show' filter.
366
367        $post    = get_post();
368        $enabled = true;
369
370        // Never show on feeds or previews.
371        if ( is_feed() || is_preview() ) {
372            $enabled = false;
373            // Not a feed or preview, so what is it?
374        } else {
375            if ( post_password_required() ) {
376                $enabled = false;
377            }
378
379            if ( in_array( 'get_the_excerpt', (array) $wp_current_filter, true ) ) {
380                $enabled = false;
381            }
382            // Sharing Setting Overrides ****************************************
383            // Single post including custom post types.
384            if ( is_single() ) {
385                if ( ! $this->is_single_post_enabled( ( $post instanceof WP_Post ) ? $post->post_type : 'post' ) ) {
386                    $enabled = false;
387                }
388
389                // Single page.
390            } elseif ( is_page() && ! is_front_page() ) {
391                if ( ! $this->is_single_page_enabled() ) {
392                    $enabled = false;
393                }
394
395                // Attachment.
396            } elseif ( is_attachment() ) {
397                if ( ! $this->is_attachment_enabled() ) {
398                    $enabled = false;
399                }
400
401                // All other loops.
402            } elseif ( ! $this->is_index_enabled() ) {
403                $enabled = false;
404            }
405        }
406
407        if ( $post instanceof WP_Post ) {
408            // Check that the post is a public, published post.
409            if ( 'attachment' === $post->post_type ) {
410                $post_status = get_post_status( $post->post_parent );
411            } else {
412                $post_status = $post->post_status;
413            }
414            if ( 'publish' !== $post_status ) {
415                $enabled = false;
416            }
417        }
418
419        // Run through the sharing filters.
420        /** This filter is documented in modules/sharedaddy/sharing-service.php */
421        $enabled = apply_filters( 'sharing_show', $enabled, $post );
422
423        /**
424         * Filters whether the Likes should be visible or not.
425         * Allows overwriting the options set in Settings > Sharing.
426         *
427         * @module likes
428         *
429         * @since 2.2.0
430         *
431         * @param bool $enabled Should the Likes be visible?
432         */
433        return (bool) apply_filters( 'wpl_is_likes_visible', $enabled );
434    }
435
436    /**
437     * Are Post Likes enabled on single posts?
438     *
439     * @param string $post_type custom post type identifier.
440     * @return bool
441     */
442    public function is_single_post_enabled( $post_type = 'post' ) {
443        $options = $this->get_options();
444
445        /**
446         * Filters whether Likes should be enabled on single posts.
447         *
448         * The dynamic part of the filter, {$post_type}, allows you to specific the post type where Likes should be enabled.
449         *
450         * @module likes
451         *
452         * @since 2.2.0
453         *
454         * @param bool $enabled Are Post Likes enabled on single posts?
455         */
456        $post_likes_enabled = apply_filters(
457            "wpl_is_single_{$post_type}_disabled",
458            in_array( $post_type, $options['show'], true )
459        );
460
461        return (bool) $post_likes_enabled;
462    }
463
464    /**
465     * Get the 'disabled_likes' option from the DB of the current blog.
466     *
467     * @return array
468     */
469    public function get_options() {
470        $setting             = array();
471        $setting['disabled'] = get_option( 'disabled_likes' );
472        $sharing             = get_option( 'sharing-options', array() );
473
474        if ( ! is_array( $sharing ) ) {
475            $sharing = array();
476        }
477        if ( ! isset( $sharing['global'] ) || ! is_array( $sharing['global'] ) ) {
478            $sharing['global'] = array();
479        }
480
481        // Default visibility settings
482        if ( ! isset( $sharing['global']['show'] ) ) {
483            $sharing['global']['show'] = array( 'post', 'page' );
484
485            // Scalar check
486        } elseif ( is_scalar( $sharing['global']['show'] ) ) {
487            switch ( $sharing['global']['show'] ) {
488                case 'posts':
489                    $sharing['global']['show'] = array( 'post', 'page' );
490                    break;
491                case 'index':
492                    $sharing['global']['show'] = array( 'index' );
493                    break;
494                case 'posts-index':
495                    $sharing['global']['show'] = array( 'post', 'page', 'index' );
496                    break;
497            }
498        }
499
500        // Ensure it's always an array (even if not previously empty or scalar)
501        $setting['show'] = ! empty( $sharing['global']['show'] ) ? (array) $sharing['global']['show'] : array();
502
503        /**
504         * Filters where the Likes are displayed.
505         *
506         * @module likes
507         *
508         * @since 2.2.0
509         *
510         * @param array $setting Array of Likes display settings.
511         */
512        return apply_filters( 'wpl_get_options', $setting );
513    }
514
515    /**
516     * Are Post Likes enabled on archive/front/search pages?
517     *
518     * @return bool
519     */
520    public function is_index_enabled() {
521        $options = $this->get_options();
522        /**
523         * Filters whether Likes should be enabled on archive/front/search pages.
524         *
525         * @module likes
526         *
527         * @since 2.2.0
528         *
529         * @param bool $enabled Are Post Likes enabled on archive/front/search pages?
530         */
531        return (bool) apply_filters( 'wpl_is_index_disabled', in_array( 'index', $options['show'], true ) );
532    }
533
534    /**
535     * Are Post Likes enabled on single pages?
536     *
537     * @return bool
538     */
539    public function is_single_page_enabled() {
540        $options = $this->get_options();
541        /**
542         * Filters whether Likes should be enabled on single pages.
543         *
544         * @module likes
545         *
546         * @since 2.2.0
547         *
548         * @param bool $enabled Are Post Likes enabled on single pages?
549         */
550        return (bool) apply_filters( 'wpl_is_single_page_disabled', in_array( 'page', $options['show'], true ) );
551    }
552
553    /**
554     * Are Media Likes enabled on single pages?
555     *
556     * @return bool
557     */
558    public function is_attachment_enabled() {
559        $options = $this->get_options();
560        /**
561         * Filters whether Likes should be enabled on attachment pages.
562         *
563         * @module likes
564         *
565         * @since 2.2.0
566         *
567         * @param bool $enabled Are Post Likes enabled on attachment pages?
568         */
569        return (bool) apply_filters( 'wpl_is_attachment_disabled', in_array( 'attachment', $options['show'], true ) );
570    }
571
572    /**
573     * The actual options block to be inserted into the sharing page.
574     */
575    public function admin_settings_init() {
576        ?>
577        <tr>
578            <th scope="row">
579                <label><?php esc_html_e( 'WordPress.com Likes are', 'jetpack' ); ?></label>
580            </th>
581            <td>
582                <div>
583                    <label>
584                        <input type="radio" class="code" name="wpl_default" value="on" <?php checked( $this->is_enabled_sitewide(), true ); ?> />
585                        <?php esc_html_e( 'On for all posts', 'jetpack' ); ?>
586                    </label>
587                </div>
588                <div>
589                    <label>
590                        <input type="radio" class="code" name="wpl_default" value="off" <?php checked( $this->is_enabled_sitewide(), false ); ?> />
591                        <?php esc_html_e( 'Turned on per post', 'jetpack' ); ?>
592                    </label>
593                    <div>
594            </td>
595        </tr>
596        <?php if ( ! $this->in_jetpack ) : ?>
597            <tr>
598                <th scope="row">
599                    <label><?php esc_html_e( 'WordPress.com Reblog Button', 'jetpack' ); ?></label>
600                </th>
601                <td>
602                    <div>
603                        <label>
604                            <input type="radio" class="code" name="jetpack_reblogs_enabled" value="on" <?php checked( $this->reblogs_enabled_sitewide(), true ); ?> />
605                            <?php esc_html_e( 'Show the Reblog button on posts', 'jetpack' ); ?>
606                        </label>
607                    </div>
608                    <div>
609                        <label>
610                            <input type="radio" class="code" name="jetpack_reblogs_enabled" value="off" <?php checked( $this->reblogs_enabled_sitewide(), false ); ?> />
611                            <?php esc_html_e( 'Don\'t show the Reblog button on posts', 'jetpack' ); ?>
612                        </label>
613                    </div>
614                </td>
615            </tr>
616            <!-- WPCOM only: Comment Likes -->
617            <?php if ( ! $this->in_jetpack ) : ?>
618                <tr>
619                    <th scope="row">
620                        <label><?php esc_html_e( 'Comment Likes are', 'jetpack' ); ?></label>
621                    </th>
622                    <td>
623                        <div>
624                            <label>
625                                <input type="checkbox" class="code" name="jetpack_comment_likes_enabled" value="1" <?php checked( $this->is_comments_enabled(), true ); ?> />
626                                <?php esc_html_e( 'On for all comments', 'jetpack' ); ?>
627                            </label>
628                        </div>
629                    </td>
630                </tr>
631            <?php endif; ?>
632        <?php endif; ?>
633        </tbody> <?php // closes the tbody attached to sharing_show_buttons_on_row_start... ?>
634        <?php
635    }
636
637    /**
638     * Returns the current state of the "WordPress.com Reblogs are" option.
639     *
640     * @return bool true if enabled sitewide, false if not
641     */
642    public function reblogs_enabled_sitewide() {
643        /**
644         * Filters whether Reblogs are enabled by default on all posts.
645         * true if enabled sitewide, false if not.
646         *
647         * @module likes
648         *
649         * @since 3.0.0
650         *
651         * @param bool $option Are Reblogs enabled sitewide.
652         */
653        return (bool) apply_filters( 'wpl_reblogging_enabled_sitewide', ! get_option( 'disabled_reblogs' ) );
654    }
655
656    /**
657     * Used for WPCOM ONLY. Comment likes are in their own module in Jetpack.
658     * Returns if comment likes are enabled. Defaults to 'off'
659     *
660     * @return boolean true if we should show comment likes, false if not
661     */
662    public function is_comments_enabled() {
663        /**
664         * Filters whether Comment Likes are enabled.
665         * true if enabled, false if not.
666         *
667         * @module comment-likes
668         *
669         * @since 2.2.0
670         *
671         * @param bool $option Are Comment Likes enabled sitewide.
672         */
673        return (bool) apply_filters( 'jetpack_comment_likes_enabled', get_option( 'jetpack_comment_likes_enabled', false ) );
674    }
675
676    /**
677     * Saves the setting in the database.
678     */
679    public function admin_settings_callback() {
680        if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'sharing-options' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- WordPress core doesn't unslash or verify nonces either.
681            return;
682        }
683
684        // We're looking for these, and doing a dance to set some stats and save
685        // them together in array option.
686        if ( ! empty( $_POST['wpl_default'] ) ) {
687            $new_state = sanitize_text_field( wp_unslash( $_POST['wpl_default'] ) );
688        } else {
689            $new_state = 'on';
690        }
691
692        if ( ! empty( $_POST['jetpack_reblogs_enabled'] ) ) {
693            $reblogs_new_state = sanitize_text_field( wp_unslash( $_POST['jetpack_reblogs_enabled'] ) );
694        } else {
695            $reblogs_new_state = 'on';
696        }
697
698        // Checked (enabled)
699        switch ( $new_state ) {
700            case 'off':
701                update_option( 'disabled_likes', 1 );
702                break;
703            case 'on':
704            default:
705                delete_option( 'disabled_likes' );
706                break;
707        }
708
709        switch ( $reblogs_new_state ) {
710            case 'off':
711                update_option( 'disabled_reblogs', 1 );
712                break;
713            case 'on':
714            default:
715                delete_option( 'disabled_reblogs' );
716                break;
717        }
718
719        // WPCOM only: Comment Likes
720        if ( ! $this->in_jetpack ) {
721            if ( ! empty( $_POST['jetpack_comment_likes_enabled'] ) ) {
722                $new_comments_state = sanitize_text_field( wp_unslash( $_POST['jetpack_comment_likes_enabled'] ) );
723            } else {
724                $new_comments_state = false;
725            }
726            switch ( (bool) $new_comments_state ) {
727                case true:
728                    update_option( 'jetpack_comment_likes_enabled', 1 );
729                    break;
730                case false:
731                default:
732                    update_option( 'jetpack_comment_likes_enabled', 0 );
733                    break;
734            }
735        }
736    }
737
738    /**
739     * Adds the admin update hook so we can save settings even if Sharedaddy is not enabled.
740     */
741    public function process_update_requests_if_sharedaddy_not_loaded() {
742        if ( isset( $_GET['page'] ) && ( $_GET['page'] === 'sharing.php' || $_GET['page'] === 'sharing' ) ) {
743            if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'sharing-options' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- WordPress core doesn't unslash or verify nonces either.
744                /** This action is documented in modules/sharedaddy/sharing.php */
745                do_action( 'sharing_admin_update' );
746                wp_safe_redirect( admin_url( 'options-general.php?page=sharing&update=saved' ) );
747                die( 0 );
748            }
749        }
750    }
751
752    /**
753     * If sharedaddy is not loaded, we don't have the "Show buttons on" yet, so we need to add that since it affects likes too.
754     */
755    public function admin_settings_showbuttonon_init() {
756        /** This action is documented in modules/sharedaddy/sharing.php */
757        echo apply_filters( 'sharing_show_buttons_on_row_start', '<tr valign="top">' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
758        ?>
759        <th scope="row"><label><?php esc_html_e( 'Show buttons on', 'jetpack' ); ?></label></th>
760        <td>
761            <?php
762            $br    = false;
763            $shows = array_values( get_post_types( array( 'public' => true ) ) );
764            array_unshift( $shows, 'index' );
765            $global = $this->get_options();
766            foreach ( $shows as $show ) :
767                if ( 'index' === $show ) {
768                    $label = __( 'Front Page, Archive Pages, and Search Results', 'jetpack' );
769                } else {
770                    $post_type_object = get_post_type_object( $show );
771                    $label            = $post_type_object->labels->name;
772                }
773
774                if ( $br ) {
775                    echo '<br />';
776                }
777                ?>
778                <label><input type="checkbox"<?php checked( in_array( $show, $global['show'], true ) ); ?> name="show[]" value="<?php echo esc_attr( $show ); ?>" /> <?php echo esc_html( $label ); ?></label>
779                <?php
780                $br = true;
781                endforeach;
782            ?>
783        </td>
784        <?php
785        /** This action is documented in modules/sharedaddy/sharing.php */
786        echo apply_filters( 'sharing_show_buttons_on_row_end', '</tr>' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
787    }
788
789    /**
790     * If sharedaddy is not loaded, we still need to save the the settings of the "Show buttons on" option.
791     */
792    public function admin_settings_showbuttonon_callback() {
793        $options = get_option( 'sharing-options' );
794        if ( ! is_array( $options ) ) {
795            $options = array();
796        }
797
798        $shows   = array_values( get_post_types( array( 'public' => true ) ) );
799        $shows[] = 'index';
800        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- triggered due to the 'sharing_admin_update' action, but the code in sharing.php checks for the nonce before firing the action.
801        $data = $_POST;
802
803        if ( isset( $data['show'] ) ) {
804            if ( is_scalar( $data['show'] ) ) {
805                switch ( $data['show'] ) {
806                    case 'posts':
807                        $data['show'] = array( 'post', 'page' );
808                        break;
809                    case 'index':
810                        $data['show'] = array( 'index' );
811                        break;
812                    case 'posts-index':
813                        $data['show'] = array( 'post', 'page', 'index' );
814                        break;
815                }
816            }
817
818            $data['show'] = array_intersect( $data['show'], $shows );
819            if ( $data['show'] ) {
820                $options['global']['show'] = $data['show'];
821            }
822        } else {
823            $options['global']['show'] = array();
824        }
825
826        update_option( 'sharing-options', $options );
827    }
828}