Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 158
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 2
Jetpack_Related_Posts_Customize
0.00% covered (danger)
0.00%
0 / 154
0.00% covered (danger)
0.00%
0 / 8
930
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 customize_register
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 1
306
 render_callback
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 contains_related_posts_block
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 is_single
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 is_not_single
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 get_options
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 1
12
 customize_controls_enqueue_scripts
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
Jetpack_Message_Control
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 render_content
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3use Automattic\Jetpack\Assets;
4
5// Exit if file is accessed directly.
6if ( ! defined( 'ABSPATH' ) ) {
7    exit( 0 );
8}
9
10/**
11 * Class to include elements to modify Related Posts look in Customizer.
12 *
13 * @since 4.4.0
14 * @phan-constructor-used-for-side-effects
15 */
16class Jetpack_Related_Posts_Customize {
17
18    /**
19     * Key for panel, section and prefix for options. Same option name than in Options > Reading.
20     *
21     * @var string
22     */
23    public $prefix = 'jetpack_relatedposts';
24
25    /**
26     * Control to focus when customizer loads
27     *
28     * @var string
29     */
30    public $focus = '';
31
32    /**
33     * Class initialization.
34     *
35     * @since 4.4.0
36     */
37    public function __construct() {
38        if ( ! wp_is_block_theme() ) {
39            add_action( 'customize_register', array( $this, 'customize_register' ) );
40            add_action( 'customize_controls_enqueue_scripts', array( $this, 'customize_controls_enqueue_scripts' ) );
41        }
42    }
43
44    /**
45     * Initialize Customizer controls.
46     *
47     * @since 4.4.0
48     *
49     * @param WP_Customize_Manager $wp_customize Customizer instance.
50     */
51    public function customize_register( $wp_customize ) {
52
53        $wp_customize->add_section(
54            $this->prefix,
55            array(
56                'title'       => esc_html__( 'Related Posts', 'jetpack' ),
57                'description' => '',
58                'capability'  => 'edit_theme_options',
59                'priority'    => 200,
60            )
61        );
62
63        $selective_options = array();
64
65        foreach ( $this->get_options( $wp_customize ) as $key => $field ) {
66            $control_id          = "$this->prefix[$key]";
67            $selective_options[] = $control_id;
68            $wp_customize->add_setting(
69                $control_id,
70                array(
71                    'default'    => isset( $field['default'] ) ? $field['default'] : '',
72                    'type'       => isset( $field['setting_type'] ) ? $field['setting_type'] : 'option',
73                    'capability' => isset( $field['capability'] ) ? $field['capability'] : 'edit_theme_options',
74                    'transport'  => isset( $field['transport'] ) ? $field['transport'] : 'postMessage',
75                )
76            );
77            $control_settings = array(
78                'label'           => isset( $field['label'] ) ? $field['label'] : '',
79                'description'     => isset( $field['description'] ) ? $field['description'] : '',
80                'settings'        => $control_id,
81                'type'            => isset( $field['control_type'] ) ? $field['control_type'] : 'text',
82                'section'         => $this->prefix,
83                'priority'        => 10,
84                'active_callback' => isset( $field['active_callback'] ) ? $field['active_callback'] : __CLASS__ . '::is_single',
85            );
86            switch ( $field['control_type'] ) {
87                case 'text':
88                case 'checkbox':
89                default:
90                    $wp_customize->add_control( new WP_Customize_Control( $wp_customize, $control_id, $control_settings ) );
91                    break;
92                case 'select':
93                    if ( isset( $field['choices'] ) ) {
94                        $control_settings['choices'] = $field['choices'];
95                        $wp_customize->add_control( new WP_Customize_Control( $wp_customize, $control_id, $control_settings ) );
96                    }
97                    break;
98                case 'message':
99                    $wp_customize->add_control( new Jetpack_Message_Control( $wp_customize, $control_id, $control_settings ) );
100                    break;
101            }
102        }
103
104        // If selective refresh is available, implement it.
105        if ( isset( $wp_customize->selective_refresh ) ) {
106            $wp_customize->selective_refresh->add_partial(
107                "$this->prefix",
108                array(
109                    'selector'            => '.jp-relatedposts:not(.jp-relatedposts-block)',
110                    'settings'            => $selective_options,
111                    'render_callback'     => __CLASS__ . '::render_callback',
112                    'container_inclusive' => false,
113                )
114            );
115        }
116    }
117
118    /**
119     * Callback that outputs the headline based on user choice.
120     *
121     * @since 4.4.0
122     */
123    public static function render_callback() {
124        echo Jetpack_RelatedPosts::init()->get_headline(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- content escaped in get_headline method
125    }
126
127    /**
128     * Check whether the current post contains a Related Posts block.
129     *
130     * @since 6.9.0
131     *
132     * @return bool
133     */
134    public static function contains_related_posts_block() {
135        if ( has_block( 'jetpack/related-posts' ) ) {
136            return true;
137        }
138
139        return false;
140    }
141
142    /**
143     * Check that we're in a single post view.
144     * Will return `false` if the current post contains a Related Posts block,
145     * because in that case we want to hide the Customizer controls.
146     *
147     * @since 4.4.0
148     *
149     * @return bool
150     */
151    public static function is_single() {
152        if ( self::contains_related_posts_block() ) {
153            return false;
154        }
155        return is_single();
156    }
157
158    /**
159     * Check that we're not in a single post view.
160     * Will return `false` if the current post contains a Related Posts block,
161     * because in that case we want to hide the Customizer controls.
162     *
163     * @since 4.4.0
164     *
165     * @return bool
166     */
167    public static function is_not_single() {
168        if ( self::contains_related_posts_block() ) {
169            return false;
170        }
171        return ! is_single();
172    }
173
174    /**
175     * Return list of options to modify.
176     *
177     * @since 4.4.0
178     *
179     * @param object $wp_customize Instance of WP Customizer.
180     *
181     * @return mixed|void
182     */
183    public function get_options( $wp_customize ) {
184        $transport = isset( $wp_customize->selective_refresh ) ? 'postMessage' : 'refresh';
185
186        $switched_locale = switch_to_locale( get_user_locale() );
187        $headline        = __( 'Related', 'jetpack' );
188        if ( $switched_locale ) {
189            restore_previous_locale();
190        }
191
192        /**
193         * The filter allows you to change the options used to display Related Posts in the Customizer.
194         *
195         * @module related-posts
196         *
197         * @since 4.4.0
198         *
199         * @param array $options Array of options used to display Related Posts in the Customizer.
200         */
201        return apply_filters(
202            'jetpack_related_posts_customize_options',
203            array(
204                'enabled'          => array(
205                    'control_type' => 'hidden',
206                    'default'      => 1,
207                    'setting_type' => 'option',
208                    'transport'    => $transport,
209                ),
210                'show_headline'    => array(
211                    'label'        => esc_html__( 'Show a headline', 'jetpack' ),
212                    'description'  => esc_html__( 'This helps to clearly separate the related posts from post content.', 'jetpack' ),
213                    'control_type' => 'checkbox',
214                    'default'      => 1,
215                    'setting_type' => 'option',
216                    'transport'    => $transport,
217                ),
218                'headline'         => array(
219                    'label'        => '',
220                    'description'  => esc_html__( 'Enter text to use as headline.', 'jetpack' ),
221                    'control_type' => 'text',
222                    'default'      => esc_html( $headline ),
223                    'setting_type' => 'option',
224                    'transport'    => $transport,
225                ),
226                'show_thumbnails'  => array(
227                    'label'        => esc_html__( 'Show thumbnails', 'jetpack' ),
228                    'description'  => esc_html__( 'Show a thumbnail image where available.', 'jetpack' ),
229                    'control_type' => 'checkbox',
230                    'default'      => 1,
231                    'setting_type' => 'option',
232                    'transport'    => $transport,
233                ),
234                'show_date'        => array(
235                    'label'        => esc_html__( 'Show date', 'jetpack' ),
236                    'description'  => esc_html__( 'Display date when entry was published.', 'jetpack' ),
237                    'control_type' => 'checkbox',
238                    'default'      => 1,
239                    'setting_type' => 'option',
240                    'transport'    => $transport,
241                ),
242                'show_context'     => array(
243                    'label'        => esc_html__( 'Show context', 'jetpack' ),
244                    'description'  => esc_html__( "Display entry's category or tag.", 'jetpack' ),
245                    'control_type' => 'checkbox',
246                    'default'      => 1,
247                    'setting_type' => 'option',
248                    'transport'    => $transport,
249                ),
250                'layout'           => array(
251                    'label'        => esc_html__( 'Layout', 'jetpack' ),
252                    'description'  => esc_html__( 'Arrange entries in different layouts.', 'jetpack' ),
253                    'control_type' => 'select',
254                    'choices'      => array(
255                        'grid' => esc_html__( 'Grid', 'jetpack' ),
256                        'list' => esc_html__( 'List', 'jetpack' ),
257                    ),
258                    'default'      => 'grid',
259                    'setting_type' => 'option',
260                    'transport'    => $transport,
261                ),
262                'msg_go_to_single' => array(
263                    'description'     => esc_html__( 'Please visit a single post view to reveal the customization options.', 'jetpack' ),
264                    'control_type'    => 'message',
265                    'active_callback' => __CLASS__ . '::is_not_single',
266                ),
267                'msg_example'      => array(
268                    'description'  => esc_html__( 'Please note that the related posts displayed now are only for previewing purposes.', 'jetpack' ),
269                    'control_type' => 'message',
270                ),
271            )
272        );
273    }
274
275    /**
276     * Enqueue assets for Customizer controls.
277     *
278     * @since 4.4.0
279     */
280    public function customize_controls_enqueue_scripts() {
281        wp_enqueue_script(
282            'jetpack_related-posts-customizer',
283            Assets::get_file_url_for_environment(
284                '_inc/build/related-posts/related-posts-customizer.min.js',
285                'modules/related-posts/related-posts-customizer.js'
286            ),
287            array( 'customize-controls' ),
288            JETPACK__VERSION,
289            false
290        );
291    }
292} // class end
293
294/**
295 * Control that displays a message in Customizer.
296 *
297 * @since 4.4.0
298 * @todo break this out into its own file.
299 */
300class Jetpack_Message_Control extends WP_Customize_Control { // phpcs:ignore
301
302    /**
303     * Render the message.
304     *
305     * @since 4.4.0
306     */
307    public function render_content() {
308        echo '<p class="description">' . esc_html( $this->description ) . '</p>';
309    }
310} // class end
311
312// Initialize controls.
313new Jetpack_Related_Posts_Customize();