Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 126
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
jetpack_register_eu_cookie_law_widget
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
Jetpack_EU_Cookie_Law_Widget
0.00% covered (danger)
0.00%
0 / 121
0.00% covered (danger)
0.00%
0 / 7
1892
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 enqueue_frontend_scripts
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 defaults
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
12
 widget
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
72
 form
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
6
 update
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
506
 filter_value
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * Main class file for EU Cookie Law Widget.
4 *
5 * @package automattic/jetpack
6 */
7
8use Automattic\Jetpack\Assets;
9
10/**
11 * Disable direct access/execution to/of the widget code.
12 */
13if ( ! defined( 'ABSPATH' ) ) {
14    exit( 0 );
15}
16
17if ( ! class_exists( 'Jetpack_EU_Cookie_Law_Widget' ) ) {
18    /**
19     * EU Cookie Law Widget
20     *
21     * Display the EU Cookie Law banner in the bottom part of the screen.
22     */
23    class Jetpack_EU_Cookie_Law_Widget extends WP_Widget {
24        /**
25         * EU Cookie Law cookie name.
26         *
27         * @var string
28         */
29        public static $cookie_name = 'eucookielaw';
30
31        /**
32         * Default hide options.
33         *
34         * @var array
35         */
36        private $hide_options = array(
37            'button',
38            'scroll',
39            'time',
40        );
41
42        /**
43         * Default text options.
44         *
45         * @var array
46         */
47        private $text_options = array(
48            'default',
49            'custom',
50        );
51
52        /**
53         * Default color scheme options.
54         *
55         * @var array
56         */
57        private $color_scheme_options = array(
58            'default',
59            'negative',
60        );
61
62        /**
63         * Default policy URL options.
64         *
65         * @var array
66         */
67        private $policy_url_options = array(
68            'default',
69            'custom',
70        );
71
72        /**
73         * Widget position options.
74         *
75         * @var array
76         */
77        private $position_options = array(
78            'bottom',
79            'top',
80        );
81
82        /**
83         * Constructor.
84         */
85        public function __construct() {
86            parent::__construct(
87                'eu_cookie_law_widget',
88                /** This filter is documented in modules/widgets/facebook-likebox.php */
89                apply_filters( 'jetpack_widget_name', esc_html__( 'Cookies & Consents Banner', 'jetpack' ) ),
90                array(
91                    'description'                 => esc_html__( 'Display a banner for EU Cookie Law and GDPR compliance.', 'jetpack' ),
92                    'customize_selective_refresh' => true,
93                ),
94                array()
95            );
96        }
97
98        /**
99         * Enqueue scripts and styles.
100         */
101        public function enqueue_frontend_scripts() {
102            wp_enqueue_style( 'eu-cookie-law-style', plugins_url( 'eu-cookie-law/style.css', __FILE__ ), array(), JETPACK__VERSION );
103
104            if ( ! class_exists( 'Jetpack_AMP_Support' ) || ! Jetpack_AMP_Support::is_amp_request() ) {
105                wp_enqueue_script(
106                    'eu-cookie-law-script',
107                    Assets::get_file_url_for_environment(
108                        '_inc/build/widgets/eu-cookie-law/eu-cookie-law.min.js',
109                        'modules/widgets/eu-cookie-law/eu-cookie-law.js'
110                    ),
111                    array(),
112                    '20180522',
113                    true
114                );
115            }
116        }
117
118        /**
119         * Return an associative array of default values.
120         *
121         * These values are used in new widgets.
122         *
123         * @return array Default values for the widget options.
124         */
125        public function defaults() {
126            return array(
127                'hide'               => $this->hide_options[0],
128                'hide-timeout'       => 30,
129                'consent-expiration' => 180,
130                'text'               => $this->text_options[0],
131                'customtext'         => '',
132                'color-scheme'       => $this->color_scheme_options[0],
133                'policy-url'         => get_option( 'wp_page_for_privacy_policy' ) ? $this->policy_url_options[1] : $this->policy_url_options[0],
134                'default-policy-url' => 'https://automattic.com/cookies/',
135                'custom-policy-url'  => get_option( 'wp_page_for_privacy_policy' ) ? get_permalink( (int) get_option( 'wp_page_for_privacy_policy' ) ) : '',
136                'position'           => $this->position_options[0],
137                'policy-link-text'   => esc_html__( 'Cookie Policy', 'jetpack' ),
138                'button'             => esc_html__( 'Close and accept', 'jetpack' ),
139                'default-text'       => esc_html__(
140                    'Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
141
142To find out more, including how to control cookies, see here:',
143                    'jetpack'
144                ),
145            );
146        }
147
148        /**
149         * Front-end display of the widget.
150         *
151         * @html-template-var array $instance
152         * @html-template-var array<string,string> $classes
153         *
154         * @param array $args     Widget arguments.
155         * @param array $instance Saved values from database.
156         */
157        public function widget( $args, $instance ) {
158            /**
159             * Filters the display of the EU Cookie Law widget.
160             *
161             * @since 6.1.1
162             *
163             * @param bool true Should the EU Cookie Law widget be disabled. Default to false.
164             */
165            if ( apply_filters( 'jetpack_disable_eu_cookie_law_widget', false ) ) {
166                return;
167            }
168
169            // Enqueue front end assets.
170            $this->enqueue_frontend_scripts();
171
172            $instance = wp_parse_args( $instance, $this->defaults() );
173
174            if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
175                require __DIR__ . '/eu-cookie-law/widget-amp.php';
176                return;
177            }
178
179            $classes         = array();
180            $classes['hide'] = 'hide-on-' . esc_attr( $instance['hide'] );
181            if ( 'negative' === $instance['color-scheme'] ) {
182                $classes['negative'] = 'negative';
183            }
184
185            if ( 'top' === $instance['position'] ) {
186                $classes['top'] = 'top';
187            }
188
189            if ( Jetpack::is_module_active( 'wordads' ) ) {
190                $classes['ads']  = 'ads-active';
191                $classes['hide'] = 'hide-on-button';
192            }
193
194            /**
195             * Check if widget is loaded in widgets.php.
196             *
197             * @return string widget Static version of the widget for better preview.
198             */
199            global $pagenow;
200            if ( 'widgets.php' === $pagenow ) {
201                // To prevent the widget from being added as a pop-up
202                // we do not echo the before and after $args. Instead we wrap
203                // it in a dummy `div` and return before the `widget_view` is
204                // added to stats.
205                echo '<div id="eu-cookie-law" style="padding: 0;margin: 5px">';
206                require_once __DIR__ . '/eu-cookie-law/widget.php';
207                echo '</div>';
208                return;
209            }
210
211            echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
212            require_once __DIR__ . '/eu-cookie-law/widget.php';
213            echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
214
215            /** This action is already documented in modules/widgets/gravatar-profile.php */
216            do_action( 'jetpack_stats_extra', 'widget_view', 'eu_cookie_law' );
217        }
218
219        /**
220         * Back-end widget form.
221         *
222         * @html-template-var array $instance
223         *
224         * @param array $instance Previously saved values from database.
225         * @return string|void
226         */
227        public function form( $instance ) {
228            $instance = wp_parse_args( $instance, $this->defaults() );
229            if ( Jetpack::is_module_active( 'wordads' ) ) {
230                $instance['hide'] = 'button';
231            }
232
233            wp_enqueue_script(
234                'eu-cookie-law-widget-admin',
235                Assets::get_file_url_for_environment(
236                    '_inc/build/widgets/eu-cookie-law/eu-cookie-law-admin.min.js',
237                    'modules/widgets/eu-cookie-law/eu-cookie-law-admin.js'
238                ),
239                array( 'jquery' ),
240                20180417,
241                false
242            );
243
244            require __DIR__ . '/eu-cookie-law/form.php';
245        }
246
247        /**
248         * Sanitize widget form values as they are saved.
249         *
250         * @param array $new_instance Values just sent to be saved.
251         * @param array $old_instance Previously saved values from database.
252         * @return array Updated safe values to be saved.
253         */
254        public function update( $new_instance, $old_instance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
255            $instance = array();
256            $defaults = $this->defaults();
257
258            $instance['hide']         = $this->filter_value( isset( $new_instance['hide'] ) ? $new_instance['hide'] : '', $this->hide_options );
259            $instance['text']         = $this->filter_value( isset( $new_instance['text'] ) ? $new_instance['text'] : '', $this->text_options );
260            $instance['color-scheme'] = $this->filter_value( isset( $new_instance['color-scheme'] ) ? $new_instance['color-scheme'] : '', $this->color_scheme_options );
261            $instance['policy-url']   = $this->filter_value( isset( $new_instance['policy-url'] ) ? $new_instance['policy-url'] : '', $this->policy_url_options );
262            $instance['position']     = $this->filter_value( isset( $new_instance['position'] ) ? $new_instance['position'] : '', $this->position_options );
263
264            if ( isset( $new_instance['hide-timeout'] ) ) {
265                // Time can be a value between 3 and 1000 seconds.
266                $instance['hide-timeout'] = min( 1000, max( 3, (int) $new_instance['hide-timeout'] ) );
267            }
268
269            if ( isset( $new_instance['consent-expiration'] ) ) {
270                // Time can be a value between 1 and 365 days.
271                $instance['consent-expiration'] = min( 365, max( 1, (int) $new_instance['consent-expiration'] ) );
272            }
273
274            if ( isset( $new_instance['customtext'] ) ) {
275                $instance['customtext'] = mb_substr( wp_kses( $new_instance['customtext'], array() ), 0, 4096 );
276            } else {
277                $instance['text'] = $this->text_options[0];
278            }
279
280            if ( isset( $new_instance['policy-url'] ) ) {
281                $instance['policy-url'] = 'custom' === $new_instance['policy-url']
282                    ? 'custom'
283                    : 'default';
284            } else {
285                $instance['policy-url'] = $this->policy_url_options[0];
286            }
287
288            if ( 'custom' === $instance['policy-url'] && isset( $new_instance['custom-policy-url'] ) ) {
289                $instance['custom-policy-url'] = esc_url( $new_instance['custom-policy-url'], array( 'http', 'https' ) );
290
291                if ( strlen( $instance['custom-policy-url'] ) < 10 ) {
292                    unset( $instance['custom-policy-url'] );
293                    global $wp_customize;
294                    if ( ! isset( $wp_customize ) ) {
295                        $instance['policy-url'] = $this->policy_url_options[0];
296                    }
297                }
298            }
299
300            if ( isset( $new_instance['policy-link-text'] ) ) {
301                $instance['policy-link-text'] = trim( mb_substr( wp_kses( $new_instance['policy-link-text'], array() ), 0, 100 ) );
302            }
303
304            if ( empty( $instance['policy-link-text'] ) || $instance['policy-link-text'] === $defaults['policy-link-text'] ) {
305                unset( $instance['policy-link-text'] );
306            }
307
308            if ( isset( $new_instance['button'] ) ) {
309                $instance['button'] = trim( mb_substr( wp_kses( $new_instance['button'], array() ), 0, 100 ) );
310            }
311
312            if ( empty( $instance['button'] ) || $instance['button'] === $defaults['button'] ) {
313                unset( $instance['button'] );
314            }
315
316            // Show the banner again if a setting has been changed.
317            // Sometimes plugins send headers already, so we can't set a cookie and any attempt will throw a warning.
318            if ( ! headers_sent() ) {
319                setcookie( self::$cookie_name, '', time() - 86400, '/', COOKIE_DOMAIN, is_ssl(), false ); // phpcs:ignore Jetpack.Functions.SetCookie -- Fine to have accessible.
320            }
321
322            return $instance;
323        }
324
325        /**
326         * Check if the value is allowed and not empty.
327         *
328         * @param  string $value Value to check.
329         * @param  array  $allowed Array of allowed values.
330         *
331         * @return string $value if pass the check or first value from allowed values.
332         */
333        public function filter_value( $value, $allowed = array() ) {
334            $allowed = (array) $allowed;
335            if ( empty( $value ) || ( ! empty( $allowed ) && ! in_array( $value, $allowed, true ) ) ) {
336                $value = $allowed[0];
337            }
338            return $value;
339        }
340    }
341
342    // phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move these functions to some other file.
343
344    /**
345     * Register Jetpack_EU_Cookie_Law_Widget widget.
346     */
347    function jetpack_register_eu_cookie_law_widget() {
348        register_widget( 'Jetpack_EU_Cookie_Law_Widget' );
349    }
350
351    add_action( 'widgets_init', 'jetpack_register_eu_cookie_law_widget' );
352}