Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Autologin_URLs
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 3
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 is_querystring_valid
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_wp_user_array
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
90
1<?php
2
3namespace BrianHenryIE\WP_Autologin_URLs\API\Integrations;
4
5use BrianHenryIE\WP_Autologin_URLs\API_Interface;
6use BrianHenryIE\WP_Autologin_URLs\API\User_Finder_Interface;
7use Psr\Log\LoggerAwareInterface;
8use Psr\Log\LoggerAwareTrait;
9use Psr\Log\LoggerInterface;
10use WP_User;
11
12/**
13 * The $_GET data is coming from links clicked outside WordPress; it will not have a nonce.
14 *
15 * phpcs:disable WordPress.Security.NonceVerification.Recommended
16 */
17class Autologin_URLs implements User_Finder_Interface, LoggerAwareInterface {
18    use LoggerAwareTrait;
19
20    const QUERYSTRING_PARAMETER_NAME = 'autologin';
21
22    protected API_Interface $api;
23
24    public function __construct( API_Interface $api, LoggerInterface $logger ) {
25        $this->setLogger( $logger );
26        $this->api = $api;
27    }
28
29    /**
30     * Determine is the querystring needed for this integration present.
31     */
32    public function is_querystring_valid(): bool {
33        return isset( $_GET[ self::QUERYSTRING_PARAMETER_NAME ] );
34    }
35
36    /**
37     * The actual code for logging the user in. Should run before wp_set_current_user
38     * so it is run before other code expects a user to be set, i.e. run it on
39     * plugins_loaded and not init.
40     *
41     * @hooked plugins_loaded
42     *
43     * @see https://codex.wordpress.org/Plugin_API/Action_Reference
44     * @see _wp_get_current_user()
45     *
46     * @return array{source:string, wp_user:WP_User|null, user_data?:array<string,string>}
47     */
48    public function get_wp_user_array(): array {
49
50        $result              = array();
51        $result['source']    = 'Autologin URL';
52        $result['wp_user']   = null;
53        $result['user_data'] = array();
54
55        // This input is not coming from a WordPress page so cannot have a nonce.
56        // phpcs:disable WordPress.Security.NonceVerification.Recommended
57
58        if ( ! isset( $_GET[ self::QUERYSTRING_PARAMETER_NAME ] ) ) {
59            return $result;
60        }
61
62        $autologin_querystring = sanitize_text_field( wp_unslash( $_GET[ self::QUERYSTRING_PARAMETER_NAME ] ) );
63
64        list( $user_id, $password ) = explode( '~', $autologin_querystring, 2 );
65
66        if ( empty( $user_id ) || empty( $password ) || ! is_numeric( $user_id ) || ! ctype_alnum( $password ) ) {
67
68            return $result;
69        }
70
71        $user_id = intval( $user_id );
72
73        if ( $this->api->verify_autologin_password( $user_id, $password ) ) {
74
75            $wp_user = get_user_by( 'id', $user_id );
76            if ( $wp_user instanceof WP_User ) {
77                // e.g. The user account may have been deleted since the link was created.
78                $result['wp_user'] = $wp_user;
79            }
80        }
81
82        if ( isset( $_GET['magic'] ) ) {
83            $result['source'] = 'Magic Email';
84        }
85
86        return $result;
87    }
88}