Completed
Branch BUG/fix-wordpress-heartbeat (c66ef1)
by
unknown
09:48 queued 34s
created

ThankYouPageIpnMonitor::heartbeatResponse()   B

Complexity

Conditions 8
Paths 10

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 10
nop 2
dl 0
loc 40
rs 8.0355
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\domain\services\admin\ajax;
4
5
use EE_Error;
6
use EE_Transaction;
7
use EED_Thank_You_Page;
8
use EEM_Transaction;
9
use EventEspresso\core\exceptions\InvalidDataTypeException;
10
use EventEspresso\core\exceptions\InvalidInterfaceException;
11
use InvalidArgumentException;
12
13
/**
14
 * Class ThankYouPageIpnMonitor
15
 * Handles WordPress Heartbeat AJAX requests for the Thank You Page
16
 *
17
 * @package EventEspresso\core\domain\services\admin\ajax
18
 * @author  Brent Christensen
19
 * @since   $VID:$
20
 */
21
class ThankYouPageIpnMonitor
22
{
23
24
    /**
25
     * @var EED_Thank_You_Page $thank_you_page
26
     */
27
    private $thank_you_page;
28
29
    /**
30
     * @var EE_Transaction $transaction
31
     */
32
    private $transaction;
33
34
    /**
35
     * EventEditorHeartbeat constructor.
36
     *
37
     */
38
    public function __construct()
39
    {
40
        add_filter('heartbeat_received', array($this, 'heartbeatResponse'), 10, 3);
41
        add_filter('heartbeat_nopriv_received', array($this, 'heartbeatResponse'), 10, 3);
42
    }
43
44
45
    /**
46
     * thank_you_page_IPN_monitor
47
     * this basically just pulls the TXN based on the reg_url_link sent from the server,
48
     * then checks that the TXN status is not failed, and that no other errors have been generated.
49
     * it also calculates the IPN wait time since the Thank You page was first loaded
50
     *
51
     * @param array $response
52
     * @param array $data
53
     * @return array
54
     * @throws EE_Error
55
     * @throws InvalidDataTypeException
56
     * @throws InvalidInterfaceException
57
     * @throws InvalidArgumentException
58
     */
59
    public function heartbeatResponse($response = array(), $data = array())
60
    {
61
        // does this heartbeat contain our data ?
62
        if (! isset($data['espresso_thank_you_page'])) {
63
            return $response;
64
        }
65
        // check for reg_url_link in the incoming heartbeat data
66
        if (! isset($data['espresso_thank_you_page']['e_reg_url_link'])) {
67
            $response['espresso_thank_you_page'] = array(
68
                'errors' => ! empty($notices['errors'])
0 ignored issues
show
Bug introduced by
The variable $notices seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
69
                    ? $notices['errors']
70
                    : __(
71
                        'No transaction information could be retrieved because the registration URL link is missing or invalid.',
72
                        'event_espresso'
73
                    ),
74
            );
75
            return $response;
76
        }
77
        // kk heartbeat has our data
78
        $response = $this->initializeThankYouPageAndTransaction($response, $data);
79
        // if something went wrong...
80
        if (isset($response['espresso_thank_you_page']['errors'])) {
81
            return $response;
82
        }
83
        // grab transient of Transaction's status
84
        $txn_status = isset($data['espresso_thank_you_page']['txn_status'])
85
            ? $data['espresso_thank_you_page']['txn_status']
86
            : null;
87
        $response = $this->getTransactionDetails($txn_status, $response, $data);
88
        // no payment data yet?
89
        if(isset($response['espresso_thank_you_page']['still_waiting'])) {
90
            return $response;
91
        }
92
        // TXN is happening so let's get the payments now
93
        // if we've already gotten payments then the heartbeat data will contain the timestamp of the last time we checked
94
        $since = isset($data['espresso_thank_you_page']['get_payments_since'])
95
            ? $data['espresso_thank_you_page']['get_payments_since']
96
            : 0;
97
        return $this->paymentDetails($since);
98
    }
99
100
101
    /**
102
     * @param array  $response
103
     * @param array  $data
104
     * @return array
105
     * @throws EE_Error
106
     * @throws InvalidArgumentException
107
     * @throws InvalidDataTypeException
108
     * @throws InvalidInterfaceException
109
     */
110
    private function initializeThankYouPageAndTransaction($response, $data)
111
    {
112
        require_once EE_MODULES . 'thank_you_page/EED_Thank_You_Page.module.php';
113
        // set_definitions, instantiate the thank you page class, and get the ball rolling
114
        EED_Thank_You_Page::set_definitions();
115
        $this->thank_you_page = EED_Thank_You_Page::instance();
116
        $this->thank_you_page->set_reg_url_link($data['espresso_thank_you_page']['e_reg_url_link']);
117
        $this->thank_you_page->init();
118
        $response['espresso_thank_you_page'] = array();
119
        // get TXN
120
        $transaction = $this->thank_you_page->get_txn();
121
        // no TXN? then get out
122
        if (! $transaction instanceof EE_Transaction) {
123
            $notices = EE_Error::get_notices();
124
            $response['espresso_thank_you_page'] = array(
125
                'errors' => ! empty($notices['errors'])
126
                    ? $notices['errors']
127
                    : sprintf(
128
                        __(
129
                            'The information for your transaction could not be retrieved from the server or the transaction data received was invalid because of a technical reason. (%s)',
130
                            'event_espresso'
131
                        ),
132
                        __LINE__
133
                    ),
134
            );
135
            return $response;
136
        }
137
        $this->transaction = $transaction;
138
        return $response;
139
    }
140
141
142
    /**
143
     * @param string $txn_status
144
     * @param array $response
145
     * @param array $data
146
     * @return array
147
     * @throws EE_Error
148
     */
149
    private function getTransactionDetails($txn_status, $response, $data)
150
    {
151
        // has the TXN status changed since we last checked (or empty because this is the first time running through this code)?
152
        if ($txn_status !== $this->transaction->status_ID()) {
153
            // switch between two possible basic outcomes
154
            switch ($this->transaction->status_ID()) {
155
                // TXN has been updated in some way
156
                case EEM_Transaction::overpaid_status_code:
157
                case EEM_Transaction::complete_status_code:
158
                case EEM_Transaction::incomplete_status_code:
159
                    // send updated TXN results back to client,
160
                    $response['espresso_thank_you_page'] = array(
161
                        'transaction_details' => $this->thank_you_page->get_transaction_details(),
162
                        'txn_status'          => $this->transaction->status_ID(),
163
                    );
164
                    return $response;
165
                // or we have a bad TXN, or really slow IPN, so calculate the wait time and send that back...
166
                case EEM_Transaction::failed_status_code:
167
                default:
168
                    // keep on waiting...
169
                    return $this->updateServerWaitTime($data['espresso_thank_you_page']);
170
            }
171
            // or is the TXN still failed (never been updated) ???
172
        } elseif ($this->transaction->failed()) {
173
            // keep on waiting...
174
            return $this->updateServerWaitTime($data['espresso_thank_you_page']);
175
        }
176
    }
177
178
179
    /**
180
     * @param int $since
181
     * @return array
182
     * @throws EE_Error
183
     */
184
    private function paymentDetails($since)
185
    {
186
        // then check for payments
187
        $payments = $this->thank_you_page->get_txn_payments($since);
188
        // has a payment been processed ?
189
        if (! empty($payments) || $this->thank_you_page->isOfflinePaymentMethod()) {
190
            if ($since) {
191
                $response['espresso_thank_you_page'] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
192
                    'new_payments'        => $this->thank_you_page->get_new_payments($payments),
193
                    'transaction_details' => $this->thank_you_page->get_transaction_details(),
194
                    'txn_status'          => $this->transaction->status_ID(),
195
                );
196
            } else {
197
                $response['espresso_thank_you_page']['payment_details'] = $this->thank_you_page->get_payment_details(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
198
                    $payments
199
                );
200
            }
201
            // reset time to check for payments
202
            $response['espresso_thank_you_page']['get_payments_since'] = time();
203
        } else {
204
            $response['espresso_thank_you_page']['get_payments_since'] = $since;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
205
        }
206
        return $response;
207
    }
208
209
210
    /**
211
     * @param array $thank_you_page_data    thank you page portion of the incoming JSON array
212
     *                                      from the WP heartbeat data
213
     * @return array
214
     * @throws EE_Error
215
     */
216 View Code Duplication
    private function updateServerWaitTime($thank_you_page_data)
217
    {
218
        $response['espresso_thank_you_page'] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
219
            'still_waiting' => isset($thank_you_page_data['initial_access'])
220
                ? time() - $thank_you_page_data['initial_access']
221
                : 0,
222
            'txn_status'    => $this->transaction->status_ID(),
223
        );
224
        return $response;
225
    }
226
}