Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
82.87% covered (success)
82.87%
150 / 181
75.00% covered (success)
75.00%
12 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
Settings
82.87% covered (success)
82.87%
150 / 181
75.00% covered (success)
75.00%
12 / 16
35.83
0.00% covered (danger)
0.00%
0 / 1
 __get
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 name
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 init
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 modify_cookie_expiry
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
7.04
 register_settings
100.00% covered (success)
100.00%
70 / 70
100.00% covered (success)
100.00%
1 / 1
1
 get_warning_classes
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 cookie_expiry_field
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 client_id_field
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 client_secret_field
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 user_registration
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
2
 one_tap_login
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 one_tap_login_screens
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 whitelisted_domains
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 settings_page
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 output
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 disabled
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * Register the settings under settings page and also
4 * provide the interface to retrieve the settings.
5 *
6 * @package RtCamp\GoogleLogin
7 * @since 1.0.0
8 * @author rtCamp <contact@rtcamp.com>
9 */
10
11declare(strict_types=1);
12
13namespace RtCamp\GoogleLogin\Modules;
14
15use RtCamp\GoogleLogin\Interfaces\Module as ModuleInterface;
16
17use RtCamp\GoogleLogin\Utils\Helper;
18
19use stdClass;
20
21use function RtCamp\GoogleLogin\plugin;
22
23/**
24 * Class Settings.
25 *
26 * @property string|null whitelisted_domains
27 * @property string|null client_id
28 * @property string|null client_secret
29 * @property bool|null registration_enabled
30 * @property bool|null one_tap_login
31 * @property string    one_tap_login_screen
32 * @property int|null  cookie_expiry
33 *
34 * @package RtCamp\GoogleLogin\Modules
35 */
36class Settings implements ModuleInterface {
37
38    /**
39     * Settings values.
40     *
41     * @var array
42     */
43    public $options;
44
45    /**
46     * Getters for settings values.
47     *
48     * @var string[]
49     */
50    private $getters = [
51        'WP_GOOGLE_LOGIN_CLIENT_ID'         => 'client_id',
52        'WP_GOOGLE_LOGIN_SECRET'            => 'client_secret',
53        'WP_GOOGLE_LOGIN_USER_REGISTRATION' => 'registration_enabled',
54        'WP_GOOGLE_LOGIN_WHITELIST_DOMAINS' => 'whitelisted_domains',
55        'WP_GOOGLE_ONE_TAP_LOGIN'           => 'one_tap_login',
56        'WP_GOOGLE_ONE_TAP_LOGIN_SCREEN'    => 'one_tap_login_screen',
57        'WP_GOOGLE_COOKIE_EXPIRY'           => 'cookie_expiry',
58    ];
59
60    /**
61     * Getter method.
62     *
63     * @param string $name Name of option to fetch.
64     */
65    public function __get( string $name ) {
66        if ( in_array( $name, $this->getters, true ) ) {
67            $constant_name = array_search( $name, $this->getters, true );
68
69            return defined( $constant_name ) ? constant( $constant_name ) : ( $this->options[ $name ] ?? '' );
70        }
71
72        return null;
73    }
74
75    /**
76     * Return module name.
77     *
78     * @return string
79     */
80    public function name(): string {
81        return 'settings';
82    }
83
84    /**
85     * Initialization of module.
86     *
87     * @return void
88     */
89    public function init(): void {
90        $this->options = get_option( 'wp_google_login_settings', [] );
91        add_action( 'admin_init', [ $this, 'register_settings' ] );
92        add_action( 'admin_menu', [ $this, 'settings_page' ] );
93        add_filter( 'auth_cookie_expiration', [ $this, 'modify_cookie_expiry' ] );
94    }
95
96    /**
97     * Modify cookie expiry.
98     *
99     * @param int $expiration Current cookie expiry.
100     *
101     * @return int
102     */
103    public function modify_cookie_expiry( int $expiration ): int {
104        $state = Helper::filter_input( INPUT_GET, 'state', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
105
106        if ( ! $state ) {
107            return $expiration;
108        }
109
110        $state = base64_decode( $state );
111        $state = $state ? json_decode( $state ) : null;
112
113        if ( ! ( $state instanceof stdClass ) || empty( $state->provider ) || 'google' !== $state->provider ) {
114            return $expiration;
115        }
116
117        if ( ! is_numeric( $this->cookie_expiry ) ) {
118            return $expiration;
119        }
120
121        $days = intval( $this->cookie_expiry );
122
123        return $days * DAY_IN_SECONDS;
124    }
125
126    /**
127     * Register the settings, section and fields.
128     *
129     * @return void
130     */
131    public function register_settings(): void {
132        register_setting( 'wp_google_login', 'wp_google_login_settings' );
133
134        add_settings_section(
135            'wp_google_login_section',
136            __( 'Log in with Google Settings', 'login-with-google' ),
137            function () {
138            },
139            'login-with-google'
140        );
141
142        add_settings_field(
143            'wp_google_login_client_id',
144            __( 'Client ID', 'login-with-google' ),
145            [ $this, 'client_id_field' ],
146            'login-with-google',
147            'wp_google_login_section',
148            [ 'label_for' => 'client-id' ]
149        );
150
151        add_settings_field(
152            'wp_google_login_client_secret',
153            __( 'Client Secret', 'login-with-google' ),
154            [ $this, 'client_secret_field' ],
155            'login-with-google',
156            'wp_google_login_section',
157            [ 'label_for' => 'client-secret' ]
158        );
159
160        add_settings_field(
161            'wp_google_allow_registration',
162            __( 'Create New User', 'login-with-google' ),
163            [ $this, 'user_registration' ],
164            'login-with-google',
165            'wp_google_login_section',
166            [ 'label_for' => 'user-registration' ]
167        );
168
169        add_settings_field(
170            'wp_google_one_tap_login',
171            __( 'Enable One Tap Login', 'login-with-google' ),
172            [ $this, 'one_tap_login' ],
173            'login-with-google',
174            'wp_google_login_section',
175            [ 'label_for' => 'one-tap-login', ]
176        );
177
178        add_settings_field(
179            'wp_google_one_tap_login_screen',
180            __( 'One Tap Login Locations', 'login-with-google' ),
181            [ $this, 'one_tap_login_screens' ],
182            'login-with-google',
183            'wp_google_login_section',
184            [
185                'label_for' => 'one-tap-login-screen',
186                'class'     => 'one-tap-login-screen-row',
187            ]
188        );
189
190        add_settings_field(
191            'wp_google_whitelisted_domain',
192            __( 'Whitelisted Domains', 'login-with-google' ),
193            [ $this, 'whitelisted_domains' ],
194            'login-with-google',
195            'wp_google_login_section',
196            [ 'label_for' => 'whitelisted-domains' ]
197        );
198
199        add_settings_field(
200            'wp_google_cookie_expiry',
201            __( 'Auto logout after', 'login-with-google' ),
202            [ $this, 'cookie_expiry_field' ],
203            'login-with-google',
204            'wp_google_login_section',
205            [
206                'label_for' => 'cookie-expiry',
207                'class'     => 'cookie-expiry-row',
208            ]
209        );
210    }
211
212    /**
213     * Get Warning classes.
214     *
215     * @param int $days Days.
216     *
217     * @return string
218     */
219    private function get_warning_classes( int $days ): string {
220        $warning_classes = 'warning';
221        if ( empty( $days ) || $days < 14 ) {
222            $warning_classes .= ' hidden';
223        }
224
225        return $warning_classes;
226    }
227
228    /**
229     * Render cookie expiry field.
230     *
231     * @return void
232     */
233    public function cookie_expiry_field(): void {
234
235        $days            = ! is_numeric( $this->cookie_expiry ) ? '' : intval( $this->cookie_expiry );
236        $warning_classes = $this->get_warning_classes( intval( $days ) );
237
238        ?>
239        <div class='cookie_expiry_settings_wrapper'>
240            <input placeholder="<?php esc_attr_e( 'Number of days, e.g., 12', 'login-with-google' ); ?>" type='number' inputmode='numeric' name='wp_google_login_settings[cookie_expiry]' id='cookie-expiry' value='<?php echo esc_attr( $days ); ?>' autocomplete='off' />
241        </div>
242        <p class='description'>
243            <?php echo esc_html__( 'The number of days after which the user will be automatically logged out (applicable only for Google login).', 'login-with-google' ); ?>
244        </p>
245
246        <p class='<?php echo esc_attr( $warning_classes ); ?>'>
247            <?php
248            echo esc_html__( 'Setting a cookie expiry for more than 14 days can have security implications. Proceed with caution!', 'login-with-google' );
249            ?>
250        </p>
251        <?php
252    }
253
254    /**
255     * Render client ID field.
256     *
257     * @return void
258     */
259    public function client_id_field(): void { ?>
260        <input type='text' name='wp_google_login_settings[client_id]' id="client-id" value='<?php echo esc_attr( $this->client_id ); ?>' autocomplete="off" <?php $this->disabled( 'client_id' ); ?> />
261        <p class="description">
262            <?php
263            echo wp_kses_post(
264                sprintf(
265                    '<p>%1s <a target="_blank" href="%2s">%3s</a>.</p>',
266                    esc_html__( 'Create oAuth Client ID and Client Secret at', 'login-with-google' ),
267                    'https://console.developers.google.com/apis/dashboard',
268                    'console.developers.google.com'
269                )
270            );
271            ?>
272        </p>
273        <?php
274    }
275
276    /**
277     * Render client secret field.
278     *
279     * @return void
280     */
281    public function client_secret_field(): void {
282        ?>
283        <input type='password' name='wp_google_login_settings[client_secret]' id="client-secret" value='<?php echo esc_attr( $this->client_secret ); ?>' autocomplete="off" <?php $this->disabled( 'client_secret' ); ?> />
284        <?php
285    }
286
287    /**
288     * User registration field.
289     *
290     * This will tell us whether or not to create the user
291     * if the user does not exist on WP application.
292     *
293     * This is irrespective of registration flag present in Settings > General
294     *
295     * @return void
296     */
297    public function user_registration(): void {
298        ?>
299        <label style='display:block;margin-top:6px;'><input <?php $this->disabled( 'registration_enabled' ); ?> type='checkbox'
300                                                            name='wp_google_login_settings[registration_enabled]'
301                                                            id="user-registration" <?php echo esc_attr( checked( $this->registration_enabled ) ); ?>
302                                                            value='1'>
303            <?php esc_html_e( 'Create a new user account if it does not exist already', 'login-with-google' ); ?>
304        </label>
305        <p class="description">
306            <?php
307            echo wp_kses_post(
308                sprintf(
309                /* translators: %1s will be replaced by page link */
310                    __( 'If this setting is checked, a new user will be created even if <a target="_blank" href="%1s">membership setting</a> is off.', 'login-with-google' ),
311                    is_multisite() ? 'network/settings.php' : 'options-general.php'
312                )
313            );
314            ?>
315        </p>
316        <?php
317    }
318
319    /**
320     * Toggle One Tap Login functionality.
321     *
322     * @return void
323     */
324    public function one_tap_login(): void {
325        ?>
326        <label style='display:block;margin-top:6px;'><input <?php $this->disabled( 'one_tap_login' ); ?>
327                    type='checkbox'
328                    name='wp_google_login_settings[one_tap_login]'
329                    id="one-tap-login" <?php echo esc_attr( checked( $this->one_tap_login ) ); ?>
330                    value='1'>
331            <?php esc_html_e( 'One Tap Login', 'login-with-google' ); ?>
332        </label>
333        <?php
334    }
335
336    /**
337     * One tap login screens.
338     *
339     * It can be enabled only for wp-login.php OR sitewide.
340     *
341     * @return void
342     */
343    public function one_tap_login_screens(): void {
344        $default = $this->one_tap_login_screen ?? '';
345        ?>
346        <label style='display:block;margin-top:6px;'><input <?php $this->disabled( 'one_tap_login' ); ?>
347                    type='radio'
348                    name='wp_google_login_settings[one_tap_login_screen]'
349                    id="one-tap-login-screen-login" <?php echo esc_attr( checked( $this->one_tap_login_screen, $default ) ); ?>
350                    value='login'>
351            <?php esc_html_e( 'Enable One Tap Login Only on Login Screen', 'login-with-google' ); ?>
352        </label>
353        <label style='display:block;margin-top:6px;'><input <?php $this->disabled( 'one_tap_login' ); ?>
354                    type='radio'
355                    name='wp_google_login_settings[one_tap_login_screen]'
356                    id="one-tap-login-screen-sitewide" <?php echo esc_attr( checked( $this->one_tap_login_screen, 'sitewide' ) ); ?>
357                    value='sitewide'>
358            <?php esc_html_e( 'Enable One Tap Login Site-wide', 'login-with-google' ); ?>
359        </label>
360        <?php
361    }
362
363    /**
364     * Whitelisted domains for registration.
365     *
366     * Only emails belonging to these domains would be preferred
367     * for registration.
368     *
369     * If left blank, all domains would be allowed.
370     *
371     * @return void
372     */
373    public function whitelisted_domains(): void {
374        ?>
375        <input <?php $this->disabled( 'whitelisted_domains' ); ?> type='text' name='wp_google_login_settings[whitelisted_domains]' id="whitelisted-domains" value='<?php echo esc_attr( $this->whitelisted_domains ); ?>' autocomplete="off" />
376        <p class="description">
377            <?php echo esc_html( __( 'Add each domain comma separated', 'login-with-google' ) ); ?>
378        </p>
379        <?php
380    }
381
382    /**
383     * Add settings sub-menu page in admin menu.
384     *
385     * @return void
386     */
387    public function settings_page(): void {
388        add_options_page(
389            __( 'Login with Google settings', 'login-with-google' ),
390            __( 'Login with Google', 'login-with-google' ),
391            'manage_options',
392            'login-with-google',
393            [ $this, 'output' ]
394        );
395    }
396
397    /**
398     * Output the plugin settings.
399     *
400     * @return void
401     */
402    public function output(): void {
403        ?>
404        <div class="wrap">
405        <form action='options.php' method='post'>
406            <?php
407            settings_fields( 'wp_google_login' );
408            do_settings_sections( 'login-with-google' );
409            submit_button();
410            ?>
411        </form>
412        </div>
413        <?php
414    }
415
416    /**
417     * Outputs the disabled attribute if field needs to
418     * be disabled.
419     *
420     * @param string $id Input ID.
421     *
422     * @return void
423     */
424    private function disabled( string $id ): void {
425        if ( empty( $id ) ) {
426            return;
427        }
428
429        $constant_name = array_search( $id, $this->getters, true );
430
431        if ( false !== $constant_name ) {
432            if ( defined( $constant_name ) ) {
433                echo esc_attr( 'disabled="disabled"' );
434            }
435        }
436    }
437}