Completed
Branch ENHANCE/255/add-wp-version-to-... (4d72b4)
by
unknown
19:52 queued 10:48
created

ThankYouPageIpnMonitor::setTransactionDetails()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 2
dl 0
loc 10
rs 9.9332
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
use ReflectionException;
13
14
/**
15
 * Class ThankYouPageIpnMonitor
16
 * Handles WordPress Heartbeat AJAX requests for the Thank You Page
17
 *
18
 * @package EventEspresso\core\domain\services\admin\ajax
19
 * @author  Brent Christensen
20
 * @since   4.9.76.p
21
 */
22
class ThankYouPageIpnMonitor
23
{
24
25
    /**
26
     * @var string $heartbeat
27
     */
28
    private $heartbeat;
29
30
    /**
31
     * @var EED_Thank_You_Page $thank_you_page
32
     */
33
    private $thank_you_page;
34
35
    /**
36
     * @var EE_Transaction $transaction
37
     */
38
    private $transaction;
39
40
41
    /**
42
     * EventEditorHeartbeat constructor.
43
     */
44
    public function __construct()
45
    {
46
        $this->heartbeat = WordpressHeartbeat::RESPONSE_KEY_THANK_YOU_PAGE;
47
        add_filter('heartbeat_received', array($this, 'heartbeatResponse'), 10, 3);
48
        add_filter('heartbeat_nopriv_received', array($this, 'heartbeatResponse'), 10, 3);
49
    }
50
51
52
    /**
53
     * thank_you_page_IPN_monitor
54
     * this basically just pulls the TXN based on the reg_url_link sent from the server,
55
     * then checks that the TXN status is not failed, and that no other errors have been generated.
56
     * it also calculates the IPN wait time since the Thank You page was first loaded
57
     *
58
     * @param array $response
59
     * @param array $data
60
     * @return array
61
     * @throws EE_Error
62
     * @throws InvalidArgumentException
63
     * @throws InvalidDataTypeException
64
     * @throws InvalidInterfaceException
65
     * @throws ReflectionException
66
     */
67
    public function heartbeatResponse($response = array(), $data = array())
68
    {
69
        // does this heartbeat contain our data ?
70
        if (! isset($data[ $this->heartbeat ])) {
71
            return $response;
72
        }
73
        // check for reg_url_link in the incoming heartbeat data
74
        if (! isset($data[ $this->heartbeat ]['e_reg_url_link'])) {
75
            $response[ $this->heartbeat ] = array(
76
                '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...
77
                    ? $notices['errors']
78
                    : __(
79
                        'No transaction information could be retrieved because the registration URL link is missing or invalid.',
80
                        'event_espresso'
81
                    ),
82
            );
83
            return $response;
84
        }
85
        // kk heartbeat has our data
86
        $response = $this->initializeThankYouPageAndTransaction($response, $data);
87
        // if something went wrong...
88
        if (isset($response[ $this->heartbeat ]['errors'])) {
89
            return $response;
90
        }
91
        // grab transient of Transaction's status
92
        $txn_status = isset($data[ $this->heartbeat ]['txn_status'])
93
            ? $data[ $this->heartbeat ]['txn_status']
94
            : null;
95
        $response = $this->getTransactionDetails($txn_status, $response, $data);
96
        // no payment data yet?
97
        if (isset($response[ $this->heartbeat ]['still_waiting'])) {
98
            return $response;
99
        }
100
        // TXN is happening so let's get the payments now
101
        // if we've already gotten payments then the heartbeat data will contain the timestamp of the last time we checked
102
        $since = isset($data[ $this->heartbeat ]['get_payments_since'])
103
            ? $data[ $this->heartbeat ]['get_payments_since']
104
            : 0;
105
        return $this->paymentDetails($response, $since);
106
    }
107
108
109
    /**
110
     * @param array $response
111
     * @param array $data
112
     * @return array
113
     * @throws EE_Error
114
     * @throws InvalidArgumentException
115
     * @throws InvalidDataTypeException
116
     * @throws InvalidInterfaceException
117
     */
118
    private function initializeThankYouPageAndTransaction($response, $data)
119
    {
120
        require_once EE_MODULES . 'thank_you_page/EED_Thank_You_Page.module.php';
121
        // set_definitions, instantiate the thank you page class, and get the ball rolling
122
        EED_Thank_You_Page::set_definitions();
123
        $this->thank_you_page = EED_Thank_You_Page::instance();
124
        $this->thank_you_page->set_reg_url_link($data[ $this->heartbeat ]['e_reg_url_link']);
125
        $this->thank_you_page->init();
126
        // get TXN
127
        $transaction = $this->thank_you_page->get_txn();
128
        // no TXN? then get out
129
        if (! $transaction instanceof EE_Transaction) {
130
            $notices = EE_Error::get_notices();
131
            $response[ $this->heartbeat ] = array(
132
                'errors' => ! empty($notices['errors'])
133
                    ? $notices['errors']
134
                    : sprintf(
135
                        __(
136
                            '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)',
137
                            'event_espresso'
138
                        ),
139
                        __LINE__
140
                    ),
141
            );
142
            return $response;
143
        }
144
        $this->transaction = $transaction;
145
        return $response;
146
    }
147
148
149
    /**
150
     * @param string $txn_status
151
     * @param array  $response
152
     * @param array  $data
153
     * @return array
154
     * @throws EE_Error
155
     * @throws InvalidArgumentException
156
     * @throws InvalidDataTypeException
157
     * @throws InvalidInterfaceException
158
     * @throws ReflectionException
159
     */
160
    private function getTransactionDetails($txn_status, $response, $data)
161
    {
162
        // has the TXN status changed since we last checked (or empty because this is the first time running through this code)?
163
        if ($txn_status !== $this->transaction->status_ID()) {
164
            // switch between two possible basic outcomes
165
            switch ($this->transaction->status_ID()) {
166
                // TXN has been updated in some way
167
                case EEM_Transaction::overpaid_status_code:
168
                case EEM_Transaction::complete_status_code:
169
                case EEM_Transaction::incomplete_status_code:
170
                    // send updated TXN results back to client,
171
                    return $this->setTransactionDetails($response);
172
                // or we have a bad TXN, or really slow IPN, so calculate the wait time and send that back...
173
                case EEM_Transaction::failed_status_code:
174
                default:
175
                    // keep on waiting...
176
                    return $this->updateServerWaitTime($data[ $this->heartbeat ]);
177
            }
178
            // or is the TXN still failed (never been updated) ???
179
        } elseif ($this->transaction->failed()) {
180
            // keep on waiting...
181
            return $this->updateServerWaitTime($data[ $this->heartbeat ]);
182
        }
183
        return $response;
184
    }
185
186
187
    /**
188
     * @param array $response
189
     * @param boolean $status_only
190
     * @return array
191
     * @throws EE_Error
192
     * @throws InvalidArgumentException
193
     * @throws InvalidDataTypeException
194
     * @throws InvalidInterfaceException
195
     * @throws ReflectionException
196
     */
197
    private function setTransactionDetails($response, $status_only = false)
198
    {
199
        if (! $status_only && ! isset($response[ $this->heartbeat ]['transaction_details'])) {
200
            $response[ $this->heartbeat ]['transaction_details'] = $this->thank_you_page->get_transaction_details();
201
        }
202
        if (! isset($response[ $this->heartbeat ]['txn_status'])) {
203
            $response[ $this->heartbeat ]['txn_status'] = $this->transaction->status_ID();
204
        }
205
        return $response;
206
    }
207
208
209
    /**
210
     * @param array $response
211
     * @param int $since
212
     * @return array
213
     * @throws EE_Error
214
     * @throws InvalidArgumentException
215
     * @throws InvalidDataTypeException
216
     * @throws InvalidInterfaceException
217
     * @throws ReflectionException
218
     */
219
    private function paymentDetails($response, $since)
220
    {
221
        // then check for payments
222
        $payments = $this->thank_you_page->get_txn_payments($since);
223
        // has a payment been processed ?
224
        if (! empty($payments) || $this->thank_you_page->isOfflinePaymentMethod()) {
225
            if ($since) {
226
                $response[ $this->heartbeat ]['new_payments'] = $this->thank_you_page->get_new_payments($payments);
227
                $response = $this->setTransactionDetails($response);
228
            } else {
229
                $response[ $this->heartbeat ]['payment_details'] = $this->thank_you_page->get_payment_details(
230
                    $payments
231
                );
232
            }
233
            // reset time to check for payments
234
            $response[ $this->heartbeat ]['get_payments_since'] = time();
235
        } else {
236
            $response[ $this->heartbeat ]['get_payments_since'] = $since;
237
        }
238
        return $response;
239
    }
240
241
242
    /**
243
     * @param array $thank_you_page_data    thank you page portion of the incoming JSON array
244
     *                                      from the WP heartbeat data
245
     * @return array
246
     * @throws EE_Error
247
     * @throws InvalidArgumentException
248
     * @throws InvalidDataTypeException
249
     * @throws InvalidInterfaceException
250
     * @throws ReflectionException
251
     */
252
    private function updateServerWaitTime($thank_you_page_data)
253
    {
254
        $response[ $this->heartbeat ]['still_waiting'] = isset($thank_you_page_data['initial_access'])
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...
255
            ? time() - $thank_you_page_data['initial_access']
256
            : 0;
257
        $response = $this->setTransactionDetails($response, true);
258
        return $response;
259
    }
260
}
261