Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
The_Newsletter_Plugin
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 3
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
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 / 57
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3namespace BrianHenryIE\WP_Autologin_URLs\API\Integrations;
4
5use BrianHenryIE\WP_Autologin_URLs\API\User_Finder_Interface;
6use Newsletter;
7use NewsletterStatistics;
8use Psr\Log\LoggerAwareInterface;
9use Psr\Log\LoggerAwareTrait;
10use Psr\Log\LoggerInterface;
11use WP_User;
12
13/**
14 * The $_GET data is coming from links clicked outside WordPress; it will not have a nonce.
15 *
16 * phpcs:disable WordPress.Security.NonceVerification.Recommended
17 */
18class The_Newsletter_Plugin implements User_Finder_Interface, LoggerAwareInterface {
19    use LoggerAwareTrait;
20
21    public function __construct( LoggerInterface $logger ) {
22        $this->setLogger( $logger );
23    }
24
25    /**
26     * Determine is the querystring needed for this integration present.
27     */
28    public function is_querystring_valid(): bool {
29        return isset( $_GET['nltr'] );
30    }
31
32    /**
33     * Check is the URL a tracking URL for The Newsletter Plugin and if so, log in the user being tracked.
34     *
35     * @hooked plugins_loaded
36     *
37     * @see https://wordpress.org/plugins/newsletter/
38     * @see NewsletterStatistics::hook_wp_loaded()
39     *
40     * @return array{source:string, wp_user:WP_User|null, user_data?:array<string,string>}
41     */
42    public function get_wp_user_array(): array {
43
44        $result              = array();
45        $result['source']    = 'The Newsletter Plugin';
46        $result['wp_user']   = null;
47        $result['user_data'] = array();
48
49        if ( ! isset( $_GET['nltr'] ) ) {
50            return $result;
51        }
52
53        if ( ! class_exists( NewsletterStatistics::class ) ) {
54            $this->logger->debug( '`nltr` querystring parameter set but `NewsletterStatistics` class not found.' );
55            return $result;
56        }
57
58        // This code mostly lifted from Newsletter plugin.
59
60        $input = filter_var( wp_unslash( $_GET['nltr'] ), FILTER_SANITIZE_STRIPPED );
61        if ( false === $input ) {
62            return $result;
63        }
64
65        // phpcs:disable WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
66        $nltr_param = base64_decode( $input );
67
68        // e.g. "1;2;https://example.org;;0bda890bd176d3e219614dde964cb07f".
69
70        $parts     = explode( ';', $nltr_param );
71        $email_id  = (int) array_shift( $parts );
72        $user_id   = (int) array_shift( $parts );
73        $signature = array_pop( $parts );
74        $anchor    = array_pop( $parts );
75
76        $url = implode( ';', $parts );
77
78        $key = NewsletterStatistics::instance()->options['key'];
79
80        $verified = ( md5( $email_id . ';' . $user_id . ';' . $url . ';' . $anchor . $key ) === $signature );
81
82        if ( ! $verified ) {
83            $this->logger->debug(
84                'Could not verify Newsletter URL: ' . $nltr_param,
85                array(
86                    'nltr_param' => $nltr_param,
87                    'email_id'   => $email_id,
88                    'user_id'    => $user_id,
89                    'signature'  => $signature,
90                    'anchor'     => $anchor,
91                    'url'        => $url,
92                    'key'        => $key,
93                )
94            );
95            return $result;
96        }
97        // TODO: ban IP for repeated abuse.
98
99        $tnp_user = Newsletter::instance()->get_user( $user_id );
100
101        if ( is_null( $tnp_user ) ) {
102            $this->logger->info( 'No user object returned for Newsletter user ' . $tnp_user );
103            return $result;
104        }
105
106        $user_email_address = $tnp_user->email;
107
108        $wp_user = get_user_by( 'email', $user_email_address );
109
110        if ( $wp_user instanceof WP_User ) {
111
112            $this->logger->info( "User `wp_user:{$wp_user->ID}` found from `tnp_user:{$tnp_user->id}` via Newsletter URL." );
113
114            $result['wp_user'] = $wp_user;
115
116        } else {
117
118            // We have their email address but they have no account, record the
119            // email address for WooCommerce UX and abandoned cart.
120            $user_info = array(
121                'email'      => $user_email_address,
122                'first_name' => $tnp_user->name,
123                'last_name'  => $tnp_user->surname,
124            );
125
126            $result['user_data'] = $user_info;
127
128            $this->logger->debug(
129                'No wp_user found for Newsletter user',
130                array(
131                    'result' => $result,
132                )
133            );
134        }
135
136        return $result;
137    }
138}