Completed
Branch RELEASE (416965)
by
unknown
12:55 queued 13s
created
payment_methods/Paypal_Pro/templates/paypal_pro_intro.template.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -1,10 +1,10 @@
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 printf(
4
-    esc_html__(
5
-        'PayPal Pro (Website Payments Pro) is an on-site payment method for accepting credit and debit cards and is available to event organizers in the United States, United Kingdom, and Canada. An account with PayPal is required to accept payments. Need a PayPal Pro account? Call 1-855-456-1338 or %1$sclick here to sign up for a merchant account%2$s.',
6
-        'event_espresso'
7
-    ),
8
-    '<a href="https://eventespresso.com/go/paypalpro/" target="_blank">',
9
-    '</a>'
4
+	esc_html__(
5
+		'PayPal Pro (Website Payments Pro) is an on-site payment method for accepting credit and debit cards and is available to event organizers in the United States, United Kingdom, and Canada. An account with PayPal is required to accept payments. Need a PayPal Pro account? Call 1-855-456-1338 or %1$sclick here to sign up for a merchant account%2$s.',
6
+		'event_espresso'
7
+	),
8
+	'<a href="https://eventespresso.com/go/paypalpro/" target="_blank">',
9
+	'</a>'
10 10
 );
Please login to merge, or discard this patch.
caffeinated/payment_methods/Aim/EEG_Aim.gateway.php 2 patches
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
                     $line_item->unit_price(),
192 192
                     'N'
193 193
                 );
194
-                $order_description .= $this->prepareStringForAuthnet($line_item->desc()) . ', ';
194
+                $order_description .= $this->prepareStringForAuthnet($line_item->desc()).', ';
195 195
             }
196 196
             foreach ($total_line_item->tax_descendants() as $tax_line_item) {
197 197
                 $this->addLineItem(
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
         $this->setField('last_name', $billing_info['last_name']);
217 217
         $this->setField('email', $billing_info['email']);
218 218
         $this->setField('company', $billing_info['company']);
219
-        $this->setField('address', $billing_info['address'] . ' ' . $billing_info['address2']);
219
+        $this->setField('address', $billing_info['address'].' '.$billing_info['address2']);
220 220
         $this->setField('city', $billing_info['city']);
221 221
         $this->setField('state', $billing_info['state']);
222 222
         $this->setField('country', $billing_info['country']);
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
         // invoice_num would be nice to have it be unique per SPCO page-load, that way if users
230 230
         // press back, they don't submit a duplicate. However, we may be keeping the user on teh same spco page
231 231
         // in which case, we need to generate teh invoice num per request right here...
232
-        $this->setField('invoice_num', wp_generate_password(12, false));// $billing_info['_reg-page-billing-invoice-'.$this->_gateway_name]['value']);
232
+        $this->setField('invoice_num', wp_generate_password(12, false)); // $billing_info['_reg-page-billing-invoice-'.$this->_gateway_name]['value']);
233 233
         // tell AIM that any duplicates sent in the next 5 minutes are to be ignored
234 234
         $this->setField('duplicate_window', 5 * MINUTE_IN_SECONDS);
235 235
 
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
         // Capture response
241 241
         $this->type = "AUTH_CAPTURE";
242 242
         $response = $this->_sendRequest($payment);
243
-        if (! empty($response)) {
243
+        if ( ! empty($response)) {
244 244
             if ($response->error_message) {
245 245
                 $payment->set_status($this->_pay_model->failed_status());
246 246
                 $payment->set_gateway_response($response->error_message);
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
     protected function _set_sensitive_billing_data($billing_info)
287 287
     {
288 288
         $this->setField('card_num', $billing_info['credit_card']);
289
-        $this->setField('exp_date', $billing_info['exp_month'] . $billing_info['exp_year']);
289
+        $this->setField('exp_date', $billing_info['exp_month'].$billing_info['exp_year']);
290 290
         $this->setField('card_code', $billing_info['cvv']);
291 291
     }
292 292
 
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
     protected function setField($name, $value)
327 327
     {
328 328
         if (in_array($name, $this->_all_aim_fields)) {
329
-            $this->_x_post_fields[ $name ] = $value;
329
+            $this->_x_post_fields[$name] = $value;
330 330
         } else {
331 331
             throw new AuthorizeNetException("Error: no field $name exists in the AIM API.
332 332
             To set a custom field use setCustomField('field','value') instead.");
@@ -346,11 +346,11 @@  discard block
 block discarded – undo
346 346
         $this->_x_post_fields['tran_key'] = $this->_transaction_key;
347 347
         $x_keys = array();
348 348
         foreach ($this->_x_post_fields as $key => $value) {
349
-            $x_keys[] = "x_$key=" . urlencode($this->_get_unsupported_character_remover()->format($value));
349
+            $x_keys[] = "x_$key=".urlencode($this->_get_unsupported_character_remover()->format($value));
350 350
         }
351 351
         // Add line items
352 352
         foreach ($this->_additional_line_items as $key => $value) {
353
-            $x_keys[] =  "x_line_item=" . urlencode($this->_get_unsupported_character_remover()->format($value));
353
+            $x_keys[] = "x_line_item=".urlencode($this->_get_unsupported_character_remover()->format($value));
354 354
         }
355 355
         $this->_log_clean_request($x_keys, $payment);
356 356
         $post_url = $this->_get_server_url();
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
         curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
363 363
         curl_setopt($curl_request, CURLOPT_SSL_VERIFYHOST, 2);
364 364
         if ($this->VERIFY_PEER) {
365
-            curl_setopt($curl_request, CURLOPT_CAINFO, dirname(__DIR__) . '/ssl/cert.pem');
365
+            curl_setopt($curl_request, CURLOPT_CAINFO, dirname(__DIR__).'/ssl/cert.pem');
366 366
         } else {
367 367
             curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, false);
368 368
         }
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
         $response = curl_exec($curl_request);
375 375
 
376 376
         curl_close($curl_request);
377
-        $response_obj =  new EE_AuthorizeNetAIM_Response($response);
377
+        $response_obj = new EE_AuthorizeNetAIM_Response($response);
378 378
 
379 379
         return $this->_log_and_clean_response($response_obj, $payment);
380 380
     }
@@ -394,7 +394,7 @@  discard block
 block discarded – undo
394 394
                 if (strpos($keyvaltogether, $key) === 0) {
395 395
                     // found it at the first character
396 396
                     // so its one of them
397
-                    unset($request_array[ $index ]);
397
+                    unset($request_array[$index]);
398 398
                 }
399 399
             }
400 400
         }
@@ -535,7 +535,7 @@  discard block
 block discarded – undo
535 535
             // Split Array
536 536
             $this->response = $response;
537 537
             if ($encap_char) {
538
-                $this->_response_array = explode($encap_char . $delimiter . $encap_char, substr($response, 1, -1));
538
+                $this->_response_array = explode($encap_char.$delimiter.$encap_char, substr($response, 1, -1));
539 539
             } else {
540 540
                 $this->_response_array = explode($delimiter, $response);
541 541
             }
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
     }
618 618
 }
619 619
 
620
-if (! class_exists('AuthorizeNetException')) {
620
+if ( ! class_exists('AuthorizeNetException')) {
621 621
     /**
622 622
      * Class AuthorizeNetException
623 623
      *
Please login to merge, or discard this patch.
Indentation   +590 added lines, -590 removed lines patch added patch discarded remove patch
@@ -25,413 +25,413 @@  discard block
 block discarded – undo
25 25
  */
26 26
 class EEG_Aim extends EE_Onsite_Gateway
27 27
 {
28
-    const LIVE_URL    = 'https://secure2.authorize.net/gateway/transact.dll'; // Authnet URL
29
-
30
-    const SANDBOX_URL = 'https://test.authorize.net/gateway/transact.dll';
31
-
32
-    protected $_login_id;
33
-
34
-    protected $_transaction_key;
35
-
36
-    protected $_currencies_supported = array(
37
-        'AUD',
38
-        'USD',
39
-        'CAD',
40
-        'EUR',
41
-        'GBP',
42
-        'NZD',
43
-    );
44
-
45
-    /**
46
-     * Whether to send test transactions (even to live site)
47
-     *
48
-     * @var boolean
49
-     */
50
-    protected $_test_transactions;
51
-
52
-    private $VERIFY_PEER = false;
53
-
54
-    private $_x_post_fields = array(
55
-        "version"        => "3.1",
56
-        "delim_char"     => ",",
57
-        "delim_data"     => "TRUE",
58
-        "relay_response" => "FALSE",
59
-        "encap_char"     => "|",
60
-    );
61
-
62
-    private $_additional_line_items = array();
63
-
64
-    /**
65
-     * A list of all fields in the AIM API.
66
-     * Used to warn user if they try to set a field not offered in the API.
67
-     */
68
-    private $_all_aim_fields = array(
69
-        "address",
70
-        "allow_partial_auth",
71
-        "amount",
72
-        "auth_code",
73
-        "authentication_indicator",
74
-        "bank_aba_code",
75
-        "bank_acct_name",
76
-        "bank_acct_num",
77
-        "bank_acct_type",
78
-        "bank_check_number",
79
-        "bank_name",
80
-        "card_code",
81
-        "card_num",
82
-        "cardholder_authentication_value",
83
-        "city",
84
-        "company",
85
-        "country",
86
-        "cust_id",
87
-        "customer_ip",
88
-        "delim_char",
89
-        "delim_data",
90
-        "description",
91
-        "duplicate_window",
92
-        "duty",
93
-        "echeck_type",
94
-        "email",
95
-        "email_customer",
96
-        "encap_char",
97
-        "exp_date",
98
-        "fax",
99
-        "first_name",
100
-        "footer_email_receipt",
101
-        "freight",
102
-        "header_email_receipt",
103
-        "invoice_num",
104
-        "last_name",
105
-        "line_item",
106
-        "login",
107
-        "method",
108
-        "phone",
109
-        "po_num",
110
-        "recurring_billing",
111
-        "relay_response",
112
-        "ship_to_address",
113
-        "ship_to_city",
114
-        "ship_to_company",
115
-        "ship_to_country",
116
-        "ship_to_first_name",
117
-        "ship_to_last_name",
118
-        "ship_to_state",
119
-        "ship_to_zip",
120
-        "split_tender_id",
121
-        "state",
122
-        "tax",
123
-        "tax_exempt",
124
-        "test_request",
125
-        "tran_key",
126
-        "trans_id",
127
-        "type",
128
-        "version",
129
-        "zip",
130
-        "solution_id",
131
-        "currency_code"
132
-    );
133
-
134
-
135
-    /**
136
-     * Gets the URL where the request should go. This is filterable
137
-     *
138
-     * @return string
139
-     */
140
-    protected function _get_server_url()
141
-    {
142
-        return apply_filters(
143
-            'FHEE__EEG_Aim___get_server_url',
144
-            $this->_debug_mode ? self::SANDBOX_URL : self::LIVE_URL,
145
-            $this
146
-        );
147
-    }
148
-
149
-
150
-    /**
151
-     * Asks the gateway to do whatever it does to process the payment. Onsite gateways will
152
-     * usually send a request directly to the payment provider and update the payment's status based on that;
153
-     * whereas offsite gateways will usually just update the payment with the URL and query parameters to use
154
-     * for sending the request via http_remote_request()
155
-     *
156
-     * @param EE_Payment|null $payment
157
-     * @param array|null $billing_info
158
-     * @return EE_Payment
159
-     * @throws EE_Error
160
-     * @throws ReflectionException
161
-     */
162
-    public function do_direct_payment($payment, $billing_info = null)
163
-    {
164
-        // Enable test mode if needed
165
-        // 4007000000027  <-- test successful visa
166
-        // 4222222222222  <-- test failure card number
167
-
168
-        $item_num = 1;
169
-        $transaction = $payment->transaction();
170
-        $gateway_formatter = $this->_get_gateway_formatter();
171
-        $order_description = $this->prepareStringForAuthnet($gateway_formatter->formatOrderDescription($payment));
172
-        $primary_registrant = $transaction->primary_registration();
173
-        // if we're are charging for the full amount, show the normal line items
174
-        // and the itemized total adds up properly
175
-        if ($this->_can_easily_itemize_transaction_for($payment)) {
176
-            $total_line_item = $transaction->total_line_item();
177
-            foreach ($total_line_item->get_items() as $line_item) {
178
-                if ($line_item->quantity() == 0) {
179
-                    continue;
180
-                }
181
-                $this->addLineItem(
182
-                    $item_num++,
183
-                    $gateway_formatter->formatLineItemName($line_item, $payment),
184
-                    $gateway_formatter->formatLineItemDesc($line_item, $payment),
185
-                    $line_item->quantity(),
186
-                    $line_item->unit_price(),
187
-                    'N'
188
-                );
189
-                $order_description .= $this->prepareStringForAuthnet($line_item->desc()) . ', ';
190
-            }
191
-            foreach ($total_line_item->tax_descendants() as $tax_line_item) {
192
-                $this->addLineItem(
193
-                    $item_num++,
194
-                    $tax_line_item->name(),
195
-                    $tax_line_item->desc(),
196
-                    1,
197
-                    $tax_line_item->total(),
198
-                    'N'
199
-                );
200
-            }
201
-        }
202
-
203
-        // start transaction
204
-        // if in debug mode, use authorize.net's sandbox id; otherwise use the Event Espresso partner id
205
-        $partner_id = $this->_debug_mode ? 'AAA100302' : 'AAA105363';
206
-        $this->setField('solution_id', $partner_id);
207
-        $this->setField('amount', $gateway_formatter->formatCurrency($payment->amount()));
208
-        $this->setField('description', substr(rtrim($order_description, ', '), 0, 255));
209
-        $this->_set_sensitive_billing_data($billing_info);
210
-        $this->setField('first_name', $billing_info['first_name']);
211
-        $this->setField('last_name', $billing_info['last_name']);
212
-        $this->setField('email', $billing_info['email']);
213
-        $this->setField('company', $billing_info['company']);
214
-        $this->setField('address', $billing_info['address'] . ' ' . $billing_info['address2']);
215
-        $this->setField('city', $billing_info['city']);
216
-        $this->setField('state', $billing_info['state']);
217
-        $this->setField('country', $billing_info['country']);
218
-        $this->setField('zip', $billing_info['zip']);
219
-        $this->setField('fax', $billing_info['fax']);
220
-        $this->setField('cust_id', $primary_registrant->ID());
221
-        $this->setField('phone', $billing_info['phone']);
222
-        $currency_config = LoaderFactory::getLoader()->load('EE_Currency_Config');
223
-        $this->setField('currency_code', $currency_config->code);
224
-        // invoice_num would be nice to have it be unique per SPCO page-load, that way if users
225
-        // press back, they don't submit a duplicate. However, we may be keeping the user on teh same spco page
226
-        // in which case, we need to generate teh invoice num per request right here...
227
-        $this->setField('invoice_num', wp_generate_password(12, false));// $billing_info['_reg-page-billing-invoice-'.$this->_gateway_name]['value']);
228
-        // tell AIM that any duplicates sent in the next 5 minutes are to be ignored
229
-        $this->setField('duplicate_window', 5 * MINUTE_IN_SECONDS);
230
-
231
-        if ($this->_test_transactions) {
232
-            $this->test_request = "true";
233
-        }
234
-
235
-        // Capture response
236
-        $this->type = "AUTH_CAPTURE";
237
-        $response = $this->_sendRequest($payment);
238
-        if (! empty($response)) {
239
-            if ($response->error_message) {
240
-                $payment->set_status($this->_pay_model->failed_status());
241
-                $payment->set_gateway_response($response->error_message);
242
-            } else {
243
-                $payment_status = $response->approved
244
-                    ? $this->_pay_model->approved_status()
245
-                    : $this->_pay_model->declined_status();
246
-                $payment->set_status($payment_status);
247
-                // make sure we interpret the AMT as a float, not an international string (where periods are thousand separators)
248
-                $payment->set_amount((float) $response->amount);
249
-                $payment->set_gateway_response(
250
-                    sprintf(
251
-                        esc_html__('%1$s (Reason Code: %2$s)', 'event_espresso'),
252
-                        $response->response_reason_text,
253
-                        $response->response_reason_code
254
-                    )
255
-                );
256
-                if ($this->_debug_mode) {
257
-                    $txn_id = $response->invoice_number;
258
-                } else {
259
-                    $txn_id = $response->transaction_id;
260
-                }
261
-                $payment->set_txn_id_chq_nmbr($txn_id);
262
-            }
263
-            $payment->set_extra_accntng($primary_registrant->reg_code());
264
-            $payment->set_details(print_r($response, true));
265
-        } else {
266
-            $payment->set_status($this->_pay_model->failed_status());
267
-            $payment->set_gateway_response(esc_html__("There was no response from Authorize.net", 'event_espresso'));
268
-            $payment->set_details(print_r($response, true));
269
-        }
270
-        return $payment;
271
-    }
272
-
273
-
274
-    /**
275
-     * Sets billing data for the upcoming request to AIM that is considered sensitive;
276
-     * also this method can be overridden by children classes to easily change
277
-     * what billing data gets sent
278
-     *
279
-     * @param array $billing_info
280
-     */
281
-    protected function _set_sensitive_billing_data($billing_info)
282
-    {
283
-        $this->setField('card_num', $billing_info['credit_card']);
284
-        $this->setField('exp_date', $billing_info['exp_month'] . $billing_info['exp_year']);
285
-        $this->setField('card_code', $billing_info['cvv']);
286
-    }
287
-
288
-
289
-    /**
290
-     * Add a line item.
291
-     *
292
-     * @param string $item_id
293
-     * @param string $item_name
294
-     * @param string $item_description
295
-     * @param string $item_quantity
296
-     * @param string $item_unit_price
297
-     * @param string $item_taxable
298
-     */
299
-    public function addLineItem($item_id, $item_name, $item_description, $item_quantity, $item_unit_price, $item_taxable)
300
-    {
301
-        $args = array(
302
-            substr($item_id, 0, 31),
303
-            substr($this->prepareStringForAuthnet($item_name), 0, 31),
304
-            substr($this->prepareStringForAuthnet($item_description), 0, 255),
305
-            number_format(abs($item_quantity), 2, '.', ''),
306
-            number_format(abs($item_unit_price), 2, '.', ''),
307
-            $item_taxable === 'N' ? 'N' : 'Y'
308
-        );
309
-        $this->_additional_line_items[] = implode('<|>', $args);
310
-    }
311
-
312
-
313
-    /**
314
-     * Set an individual name/value pair. This will append x_ to the name
315
-     * before posting.
316
-     *
317
-     * @param string $name
318
-     * @param string $value
319
-     * @throws AuthorizeNetException
320
-     */
321
-    protected function setField($name, $value)
322
-    {
323
-        if (in_array($name, $this->_all_aim_fields)) {
324
-            $this->_x_post_fields[ $name ] = $value;
325
-        } else {
326
-            throw new AuthorizeNetException("Error: no field $name exists in the AIM API.
28
+	const LIVE_URL    = 'https://secure2.authorize.net/gateway/transact.dll'; // Authnet URL
29
+
30
+	const SANDBOX_URL = 'https://test.authorize.net/gateway/transact.dll';
31
+
32
+	protected $_login_id;
33
+
34
+	protected $_transaction_key;
35
+
36
+	protected $_currencies_supported = array(
37
+		'AUD',
38
+		'USD',
39
+		'CAD',
40
+		'EUR',
41
+		'GBP',
42
+		'NZD',
43
+	);
44
+
45
+	/**
46
+	 * Whether to send test transactions (even to live site)
47
+	 *
48
+	 * @var boolean
49
+	 */
50
+	protected $_test_transactions;
51
+
52
+	private $VERIFY_PEER = false;
53
+
54
+	private $_x_post_fields = array(
55
+		"version"        => "3.1",
56
+		"delim_char"     => ",",
57
+		"delim_data"     => "TRUE",
58
+		"relay_response" => "FALSE",
59
+		"encap_char"     => "|",
60
+	);
61
+
62
+	private $_additional_line_items = array();
63
+
64
+	/**
65
+	 * A list of all fields in the AIM API.
66
+	 * Used to warn user if they try to set a field not offered in the API.
67
+	 */
68
+	private $_all_aim_fields = array(
69
+		"address",
70
+		"allow_partial_auth",
71
+		"amount",
72
+		"auth_code",
73
+		"authentication_indicator",
74
+		"bank_aba_code",
75
+		"bank_acct_name",
76
+		"bank_acct_num",
77
+		"bank_acct_type",
78
+		"bank_check_number",
79
+		"bank_name",
80
+		"card_code",
81
+		"card_num",
82
+		"cardholder_authentication_value",
83
+		"city",
84
+		"company",
85
+		"country",
86
+		"cust_id",
87
+		"customer_ip",
88
+		"delim_char",
89
+		"delim_data",
90
+		"description",
91
+		"duplicate_window",
92
+		"duty",
93
+		"echeck_type",
94
+		"email",
95
+		"email_customer",
96
+		"encap_char",
97
+		"exp_date",
98
+		"fax",
99
+		"first_name",
100
+		"footer_email_receipt",
101
+		"freight",
102
+		"header_email_receipt",
103
+		"invoice_num",
104
+		"last_name",
105
+		"line_item",
106
+		"login",
107
+		"method",
108
+		"phone",
109
+		"po_num",
110
+		"recurring_billing",
111
+		"relay_response",
112
+		"ship_to_address",
113
+		"ship_to_city",
114
+		"ship_to_company",
115
+		"ship_to_country",
116
+		"ship_to_first_name",
117
+		"ship_to_last_name",
118
+		"ship_to_state",
119
+		"ship_to_zip",
120
+		"split_tender_id",
121
+		"state",
122
+		"tax",
123
+		"tax_exempt",
124
+		"test_request",
125
+		"tran_key",
126
+		"trans_id",
127
+		"type",
128
+		"version",
129
+		"zip",
130
+		"solution_id",
131
+		"currency_code"
132
+	);
133
+
134
+
135
+	/**
136
+	 * Gets the URL where the request should go. This is filterable
137
+	 *
138
+	 * @return string
139
+	 */
140
+	protected function _get_server_url()
141
+	{
142
+		return apply_filters(
143
+			'FHEE__EEG_Aim___get_server_url',
144
+			$this->_debug_mode ? self::SANDBOX_URL : self::LIVE_URL,
145
+			$this
146
+		);
147
+	}
148
+
149
+
150
+	/**
151
+	 * Asks the gateway to do whatever it does to process the payment. Onsite gateways will
152
+	 * usually send a request directly to the payment provider and update the payment's status based on that;
153
+	 * whereas offsite gateways will usually just update the payment with the URL and query parameters to use
154
+	 * for sending the request via http_remote_request()
155
+	 *
156
+	 * @param EE_Payment|null $payment
157
+	 * @param array|null $billing_info
158
+	 * @return EE_Payment
159
+	 * @throws EE_Error
160
+	 * @throws ReflectionException
161
+	 */
162
+	public function do_direct_payment($payment, $billing_info = null)
163
+	{
164
+		// Enable test mode if needed
165
+		// 4007000000027  <-- test successful visa
166
+		// 4222222222222  <-- test failure card number
167
+
168
+		$item_num = 1;
169
+		$transaction = $payment->transaction();
170
+		$gateway_formatter = $this->_get_gateway_formatter();
171
+		$order_description = $this->prepareStringForAuthnet($gateway_formatter->formatOrderDescription($payment));
172
+		$primary_registrant = $transaction->primary_registration();
173
+		// if we're are charging for the full amount, show the normal line items
174
+		// and the itemized total adds up properly
175
+		if ($this->_can_easily_itemize_transaction_for($payment)) {
176
+			$total_line_item = $transaction->total_line_item();
177
+			foreach ($total_line_item->get_items() as $line_item) {
178
+				if ($line_item->quantity() == 0) {
179
+					continue;
180
+				}
181
+				$this->addLineItem(
182
+					$item_num++,
183
+					$gateway_formatter->formatLineItemName($line_item, $payment),
184
+					$gateway_formatter->formatLineItemDesc($line_item, $payment),
185
+					$line_item->quantity(),
186
+					$line_item->unit_price(),
187
+					'N'
188
+				);
189
+				$order_description .= $this->prepareStringForAuthnet($line_item->desc()) . ', ';
190
+			}
191
+			foreach ($total_line_item->tax_descendants() as $tax_line_item) {
192
+				$this->addLineItem(
193
+					$item_num++,
194
+					$tax_line_item->name(),
195
+					$tax_line_item->desc(),
196
+					1,
197
+					$tax_line_item->total(),
198
+					'N'
199
+				);
200
+			}
201
+		}
202
+
203
+		// start transaction
204
+		// if in debug mode, use authorize.net's sandbox id; otherwise use the Event Espresso partner id
205
+		$partner_id = $this->_debug_mode ? 'AAA100302' : 'AAA105363';
206
+		$this->setField('solution_id', $partner_id);
207
+		$this->setField('amount', $gateway_formatter->formatCurrency($payment->amount()));
208
+		$this->setField('description', substr(rtrim($order_description, ', '), 0, 255));
209
+		$this->_set_sensitive_billing_data($billing_info);
210
+		$this->setField('first_name', $billing_info['first_name']);
211
+		$this->setField('last_name', $billing_info['last_name']);
212
+		$this->setField('email', $billing_info['email']);
213
+		$this->setField('company', $billing_info['company']);
214
+		$this->setField('address', $billing_info['address'] . ' ' . $billing_info['address2']);
215
+		$this->setField('city', $billing_info['city']);
216
+		$this->setField('state', $billing_info['state']);
217
+		$this->setField('country', $billing_info['country']);
218
+		$this->setField('zip', $billing_info['zip']);
219
+		$this->setField('fax', $billing_info['fax']);
220
+		$this->setField('cust_id', $primary_registrant->ID());
221
+		$this->setField('phone', $billing_info['phone']);
222
+		$currency_config = LoaderFactory::getLoader()->load('EE_Currency_Config');
223
+		$this->setField('currency_code', $currency_config->code);
224
+		// invoice_num would be nice to have it be unique per SPCO page-load, that way if users
225
+		// press back, they don't submit a duplicate. However, we may be keeping the user on teh same spco page
226
+		// in which case, we need to generate teh invoice num per request right here...
227
+		$this->setField('invoice_num', wp_generate_password(12, false));// $billing_info['_reg-page-billing-invoice-'.$this->_gateway_name]['value']);
228
+		// tell AIM that any duplicates sent in the next 5 minutes are to be ignored
229
+		$this->setField('duplicate_window', 5 * MINUTE_IN_SECONDS);
230
+
231
+		if ($this->_test_transactions) {
232
+			$this->test_request = "true";
233
+		}
234
+
235
+		// Capture response
236
+		$this->type = "AUTH_CAPTURE";
237
+		$response = $this->_sendRequest($payment);
238
+		if (! empty($response)) {
239
+			if ($response->error_message) {
240
+				$payment->set_status($this->_pay_model->failed_status());
241
+				$payment->set_gateway_response($response->error_message);
242
+			} else {
243
+				$payment_status = $response->approved
244
+					? $this->_pay_model->approved_status()
245
+					: $this->_pay_model->declined_status();
246
+				$payment->set_status($payment_status);
247
+				// make sure we interpret the AMT as a float, not an international string (where periods are thousand separators)
248
+				$payment->set_amount((float) $response->amount);
249
+				$payment->set_gateway_response(
250
+					sprintf(
251
+						esc_html__('%1$s (Reason Code: %2$s)', 'event_espresso'),
252
+						$response->response_reason_text,
253
+						$response->response_reason_code
254
+					)
255
+				);
256
+				if ($this->_debug_mode) {
257
+					$txn_id = $response->invoice_number;
258
+				} else {
259
+					$txn_id = $response->transaction_id;
260
+				}
261
+				$payment->set_txn_id_chq_nmbr($txn_id);
262
+			}
263
+			$payment->set_extra_accntng($primary_registrant->reg_code());
264
+			$payment->set_details(print_r($response, true));
265
+		} else {
266
+			$payment->set_status($this->_pay_model->failed_status());
267
+			$payment->set_gateway_response(esc_html__("There was no response from Authorize.net", 'event_espresso'));
268
+			$payment->set_details(print_r($response, true));
269
+		}
270
+		return $payment;
271
+	}
272
+
273
+
274
+	/**
275
+	 * Sets billing data for the upcoming request to AIM that is considered sensitive;
276
+	 * also this method can be overridden by children classes to easily change
277
+	 * what billing data gets sent
278
+	 *
279
+	 * @param array $billing_info
280
+	 */
281
+	protected function _set_sensitive_billing_data($billing_info)
282
+	{
283
+		$this->setField('card_num', $billing_info['credit_card']);
284
+		$this->setField('exp_date', $billing_info['exp_month'] . $billing_info['exp_year']);
285
+		$this->setField('card_code', $billing_info['cvv']);
286
+	}
287
+
288
+
289
+	/**
290
+	 * Add a line item.
291
+	 *
292
+	 * @param string $item_id
293
+	 * @param string $item_name
294
+	 * @param string $item_description
295
+	 * @param string $item_quantity
296
+	 * @param string $item_unit_price
297
+	 * @param string $item_taxable
298
+	 */
299
+	public function addLineItem($item_id, $item_name, $item_description, $item_quantity, $item_unit_price, $item_taxable)
300
+	{
301
+		$args = array(
302
+			substr($item_id, 0, 31),
303
+			substr($this->prepareStringForAuthnet($item_name), 0, 31),
304
+			substr($this->prepareStringForAuthnet($item_description), 0, 255),
305
+			number_format(abs($item_quantity), 2, '.', ''),
306
+			number_format(abs($item_unit_price), 2, '.', ''),
307
+			$item_taxable === 'N' ? 'N' : 'Y'
308
+		);
309
+		$this->_additional_line_items[] = implode('<|>', $args);
310
+	}
311
+
312
+
313
+	/**
314
+	 * Set an individual name/value pair. This will append x_ to the name
315
+	 * before posting.
316
+	 *
317
+	 * @param string $name
318
+	 * @param string $value
319
+	 * @throws AuthorizeNetException
320
+	 */
321
+	protected function setField($name, $value)
322
+	{
323
+		if (in_array($name, $this->_all_aim_fields)) {
324
+			$this->_x_post_fields[ $name ] = $value;
325
+		} else {
326
+			throw new AuthorizeNetException("Error: no field $name exists in the AIM API.
327 327
             To set a custom field use setCustomField('field','value') instead.");
328
-        }
329
-    }
330
-
331
-
332
-    /**
333
-     * Posts the request to AuthorizeNet & returns response.
334
-     *
335
-     * @param $payment
336
-     * @return EE_AuthorizeNetAIM_Response
337
-     */
338
-    private function _sendRequest($payment)
339
-    {
340
-        $this->_x_post_fields['login'] = $this->_login_id;
341
-        $this->_x_post_fields['tran_key'] = $this->_transaction_key;
342
-        $x_keys = array();
343
-        foreach ($this->_x_post_fields as $key => $value) {
344
-            $x_keys[] = "x_$key=" . urlencode($this->_get_unsupported_character_remover()->format($value));
345
-        }
346
-        // Add line items
347
-        foreach ($this->_additional_line_items as $key => $value) {
348
-            $x_keys[] =  "x_line_item=" . urlencode($this->_get_unsupported_character_remover()->format($value));
349
-        }
350
-        $this->_log_clean_request($x_keys, $payment);
351
-        $post_url = $this->_get_server_url();
352
-        $curl_request = curl_init($post_url);
353
-        $post_body = implode("&", $x_keys);
354
-        curl_setopt($curl_request, CURLOPT_POSTFIELDS, $post_body);
355
-        curl_setopt($curl_request, CURLOPT_HEADER, 0);
356
-        curl_setopt($curl_request, CURLOPT_TIMEOUT, 45);
357
-        curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
358
-        curl_setopt($curl_request, CURLOPT_SSL_VERIFYHOST, 2);
359
-        if ($this->VERIFY_PEER) {
360
-            curl_setopt($curl_request, CURLOPT_CAINFO, dirname(__DIR__) . '/ssl/cert.pem');
361
-        } else {
362
-            curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, false);
363
-        }
364
-
365
-        if (preg_match('/xml/', $post_url)) {
366
-            curl_setopt($curl_request, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
367
-        }
368
-
369
-        $response = curl_exec($curl_request);
370
-
371
-        curl_close($curl_request);
372
-        $response_obj =  new EE_AuthorizeNetAIM_Response($response);
373
-
374
-        return $this->_log_and_clean_response($response_obj, $payment);
375
-    }
376
-
377
-
378
-    /**
379
-     * Logs the clean data only
380
-     *
381
-     * @param array $request_array
382
-     * @param EE_Payment $payment
383
-     */
384
-    protected function _log_clean_request($request_array, $payment)
385
-    {
386
-        $keys_to_filter_out = array('x_card_num', 'x_card_code', 'x_exp_date');
387
-        foreach ($request_array as $index => $keyvaltogether) {
388
-            foreach ($keys_to_filter_out as $key) {
389
-                if (strpos($keyvaltogether, $key) === 0) {
390
-                    // found it at the first character
391
-                    // so its one of them
392
-                    unset($request_array[ $index ]);
393
-                }
394
-            }
395
-        }
396
-        $this->log(
397
-            array(
398
-                'AIM Request sent:' => $request_array,
399
-                'Server URL'        => $this->_get_server_url()
400
-            ),
401
-            $payment
402
-        );
403
-    }
404
-
405
-
406
-
407
-    /**
408
-     * Logs the response and cleans it
409
-     *
410
-     * @param EE_AuthorizeNetAIM_Response $response_obj
411
-     * @param EE_Payment                  $payment
412
-     * @return EE_AuthorizeNetAIM_Response
413
-     */
414
-    private function _log_and_clean_response($response_obj, $payment)
415
-    {
416
-        $response_obj->account_number = '';
417
-        $this->log(array('AIM Response received:' => (array) $response_obj), $payment);
418
-        return $response_obj;
419
-    }
420
-
421
-    /**
422
-     * Removes characters Authorize.net doesn't handle well.
423
-     * @since 4.9.82.p
424
-     * @param $text
425
-     * @return string
426
-     */
427
-    private function prepareStringForAuthnet($text)
428
-    {
429
-        return str_replace(
430
-            '\'',
431
-            '',
432
-            $text
433
-        );
434
-    }
328
+		}
329
+	}
330
+
331
+
332
+	/**
333
+	 * Posts the request to AuthorizeNet & returns response.
334
+	 *
335
+	 * @param $payment
336
+	 * @return EE_AuthorizeNetAIM_Response
337
+	 */
338
+	private function _sendRequest($payment)
339
+	{
340
+		$this->_x_post_fields['login'] = $this->_login_id;
341
+		$this->_x_post_fields['tran_key'] = $this->_transaction_key;
342
+		$x_keys = array();
343
+		foreach ($this->_x_post_fields as $key => $value) {
344
+			$x_keys[] = "x_$key=" . urlencode($this->_get_unsupported_character_remover()->format($value));
345
+		}
346
+		// Add line items
347
+		foreach ($this->_additional_line_items as $key => $value) {
348
+			$x_keys[] =  "x_line_item=" . urlencode($this->_get_unsupported_character_remover()->format($value));
349
+		}
350
+		$this->_log_clean_request($x_keys, $payment);
351
+		$post_url = $this->_get_server_url();
352
+		$curl_request = curl_init($post_url);
353
+		$post_body = implode("&", $x_keys);
354
+		curl_setopt($curl_request, CURLOPT_POSTFIELDS, $post_body);
355
+		curl_setopt($curl_request, CURLOPT_HEADER, 0);
356
+		curl_setopt($curl_request, CURLOPT_TIMEOUT, 45);
357
+		curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
358
+		curl_setopt($curl_request, CURLOPT_SSL_VERIFYHOST, 2);
359
+		if ($this->VERIFY_PEER) {
360
+			curl_setopt($curl_request, CURLOPT_CAINFO, dirname(__DIR__) . '/ssl/cert.pem');
361
+		} else {
362
+			curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, false);
363
+		}
364
+
365
+		if (preg_match('/xml/', $post_url)) {
366
+			curl_setopt($curl_request, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
367
+		}
368
+
369
+		$response = curl_exec($curl_request);
370
+
371
+		curl_close($curl_request);
372
+		$response_obj =  new EE_AuthorizeNetAIM_Response($response);
373
+
374
+		return $this->_log_and_clean_response($response_obj, $payment);
375
+	}
376
+
377
+
378
+	/**
379
+	 * Logs the clean data only
380
+	 *
381
+	 * @param array $request_array
382
+	 * @param EE_Payment $payment
383
+	 */
384
+	protected function _log_clean_request($request_array, $payment)
385
+	{
386
+		$keys_to_filter_out = array('x_card_num', 'x_card_code', 'x_exp_date');
387
+		foreach ($request_array as $index => $keyvaltogether) {
388
+			foreach ($keys_to_filter_out as $key) {
389
+				if (strpos($keyvaltogether, $key) === 0) {
390
+					// found it at the first character
391
+					// so its one of them
392
+					unset($request_array[ $index ]);
393
+				}
394
+			}
395
+		}
396
+		$this->log(
397
+			array(
398
+				'AIM Request sent:' => $request_array,
399
+				'Server URL'        => $this->_get_server_url()
400
+			),
401
+			$payment
402
+		);
403
+	}
404
+
405
+
406
+
407
+	/**
408
+	 * Logs the response and cleans it
409
+	 *
410
+	 * @param EE_AuthorizeNetAIM_Response $response_obj
411
+	 * @param EE_Payment                  $payment
412
+	 * @return EE_AuthorizeNetAIM_Response
413
+	 */
414
+	private function _log_and_clean_response($response_obj, $payment)
415
+	{
416
+		$response_obj->account_number = '';
417
+		$this->log(array('AIM Response received:' => (array) $response_obj), $payment);
418
+		return $response_obj;
419
+	}
420
+
421
+	/**
422
+	 * Removes characters Authorize.net doesn't handle well.
423
+	 * @since 4.9.82.p
424
+	 * @param $text
425
+	 * @return string
426
+	 */
427
+	private function prepareStringForAuthnet($text)
428
+	{
429
+		return str_replace(
430
+			'\'',
431
+			'',
432
+			$text
433
+		);
434
+	}
435 435
 }
436 436
 
437 437
 
@@ -446,191 +446,191 @@  discard block
 block discarded – undo
446 446
  */
447 447
 class EE_AuthorizeNetAIM_Response
448 448
 {
449
-    const APPROVED = '1';
450
-    const DECLINED = '2';
451
-    const ERROR = '3';
452
-    const HELD = '4';
453
-
454
-    protected $_x_post_fields = array(
455
-        "version"        => "3.1",
456
-        "delim_char"     => ",",
457
-        "delim_data"     => "TRUE",
458
-        "relay_response" => "FALSE",
459
-        "encap_char"     => "|",
460
-    );
461
-    public $approved;
462
-    public $declined;
463
-    public $error;
464
-    public $held;
465
-    public $response_code;
466
-    public $response_subcode;
467
-    public $response_reason_code;
468
-    public $response_reason_text;
469
-    public $authorization_code;
470
-    public $avs_response;
471
-    public $transaction_id;
472
-    public $invoice_number;
473
-    public $description;
474
-    public $amount;
475
-    public $method;
476
-    public $transaction_type;
477
-    public $customer_id;
478
-    public $first_name;
479
-    public $last_name;
480
-    public $company;
481
-    public $address;
482
-    public $city;
483
-    public $state;
484
-    public $zip_code;
485
-    public $country;
486
-    public $phone;
487
-    public $fax;
488
-    public $email_address;
489
-    public $ship_to_first_name;
490
-    public $ship_to_last_name;
491
-    public $ship_to_company;
492
-    public $ship_to_address;
493
-    public $ship_to_city;
494
-    public $ship_to_state;
495
-    public $ship_to_zip_code;
496
-    public $ship_to_country;
497
-    public $tax;
498
-    public $duty;
499
-    public $freight;
500
-    public $tax_exempt;
501
-    public $purchase_order_number;
502
-    public $md5_hash;
503
-    public $card_code_response;
504
-    public $cavv_response; // cardholder_authentication_verification_response
505
-    public $account_number;
506
-    public $card_type;
507
-    public $split_tender_id;
508
-    public $requested_amount;
509
-    public $balance_on_card;
510
-    public $response; // The response string from AuthorizeNet.
511
-    public $error_message;
512
-    private $_response_array = array(); // An array with the split response.
513
-
514
-
515
-    /**
516
-     * Constructor. Parses the AuthorizeNet response string
517
-     *
518
-     * @param string $response The response from the AuthNet server.
519
-     * @var string   $delimiter The delimiter used (default is ",")
520
-     * @var string   $encap_char The encap_char used (default is "|")
521
-     * @var array    $custom_fields Any custom fields set in the request.
522
-     */
523
-
524
-    public function __construct($response)
525
-    {
526
-        $encap_char = $this->_x_post_fields['encap_char'];
527
-        $delimiter = $this->_x_post_fields['delim_char'];
528
-        if ($response) {
529
-            // Split Array
530
-            $this->response = $response;
531
-            if ($encap_char) {
532
-                $this->_response_array = explode($encap_char . $delimiter . $encap_char, substr($response, 1, -1));
533
-            } else {
534
-                $this->_response_array = explode($delimiter, $response);
535
-            }
536
-
537
-            /**
538
-             * If AuthorizeNet doesn't return a delimited response.
539
-             */
540
-            if (count($this->_response_array) < 10) {
541
-                $this->approved = false;
542
-                $this->error = true;
543
-                $this->error_message = sprintf(
544
-                    esc_html__('Unrecognized response from Authorize.net: %1$s', 'event_espresso'),
545
-                    esc_html($response)
546
-                );
547
-                return;
548
-            }
549
-
550
-
551
-
552
-            // Set all fields
553
-            $this->response_code = $this->_response_array[0];
554
-            $this->response_subcode = $this->_response_array[1];
555
-            $this->response_reason_code = $this->_response_array[2];
556
-            $this->response_reason_text = $this->_response_array[3];
557
-            $this->authorization_code = $this->_response_array[4];
558
-            $this->avs_response = $this->_response_array[5];
559
-            $this->transaction_id = $this->_response_array[6];
560
-            $this->invoice_number = $this->_response_array[7];
561
-            $this->description = $this->_response_array[8];
562
-            $this->amount = $this->_response_array[9];
563
-            $this->method = $this->_response_array[10];
564
-            $this->transaction_type = $this->_response_array[11];
565
-            $this->customer_id = $this->_response_array[12];
566
-            $this->first_name = $this->_response_array[13];
567
-            $this->last_name = $this->_response_array[14];
568
-            $this->company = $this->_response_array[15];
569
-            $this->address = $this->_response_array[16];
570
-            $this->city = $this->_response_array[17];
571
-            $this->state = $this->_response_array[18];
572
-            $this->zip_code = $this->_response_array[19];
573
-            $this->country = $this->_response_array[20];
574
-            $this->phone = $this->_response_array[21];
575
-            $this->fax = $this->_response_array[22];
576
-            $this->email_address = $this->_response_array[23];
577
-            $this->ship_to_first_name = $this->_response_array[24];
578
-            $this->ship_to_last_name = $this->_response_array[25];
579
-            $this->ship_to_company = $this->_response_array[26];
580
-            $this->ship_to_address = $this->_response_array[27];
581
-            $this->ship_to_city = $this->_response_array[28];
582
-            $this->ship_to_state = $this->_response_array[29];
583
-            $this->ship_to_zip_code = $this->_response_array[30];
584
-            $this->ship_to_country = $this->_response_array[31];
585
-            $this->tax = $this->_response_array[32];
586
-            $this->duty = $this->_response_array[33];
587
-            $this->freight = $this->_response_array[34];
588
-            $this->tax_exempt = $this->_response_array[35];
589
-            $this->purchase_order_number = $this->_response_array[36];
590
-            $this->md5_hash = $this->_response_array[37];
591
-            $this->card_code_response = $this->_response_array[38];
592
-            $this->cavv_response = $this->_response_array[39];
593
-            $this->account_number = $this->_response_array[50];
594
-            $this->card_type = $this->_response_array[51];
595
-            $this->split_tender_id = $this->_response_array[52];
596
-            $this->requested_amount = $this->_response_array[53];
597
-            $this->balance_on_card = $this->_response_array[54];
598
-
599
-            $this->approved = ($this->response_code === self::APPROVED);
600
-            $this->declined = ($this->response_code === self::DECLINED);
601
-            $this->error = ($this->response_code === self::ERROR);
602
-            $this->held = ($this->response_code === self::HELD);
603
-        } else {
604
-            $this->approved = false;
605
-            $this->error = true;
606
-            $this->error_message = esc_html__(
607
-                'Error connecting to Authorize.net',
608
-                'event_espresso'
609
-            );
610
-        }
611
-    }
449
+	const APPROVED = '1';
450
+	const DECLINED = '2';
451
+	const ERROR = '3';
452
+	const HELD = '4';
453
+
454
+	protected $_x_post_fields = array(
455
+		"version"        => "3.1",
456
+		"delim_char"     => ",",
457
+		"delim_data"     => "TRUE",
458
+		"relay_response" => "FALSE",
459
+		"encap_char"     => "|",
460
+	);
461
+	public $approved;
462
+	public $declined;
463
+	public $error;
464
+	public $held;
465
+	public $response_code;
466
+	public $response_subcode;
467
+	public $response_reason_code;
468
+	public $response_reason_text;
469
+	public $authorization_code;
470
+	public $avs_response;
471
+	public $transaction_id;
472
+	public $invoice_number;
473
+	public $description;
474
+	public $amount;
475
+	public $method;
476
+	public $transaction_type;
477
+	public $customer_id;
478
+	public $first_name;
479
+	public $last_name;
480
+	public $company;
481
+	public $address;
482
+	public $city;
483
+	public $state;
484
+	public $zip_code;
485
+	public $country;
486
+	public $phone;
487
+	public $fax;
488
+	public $email_address;
489
+	public $ship_to_first_name;
490
+	public $ship_to_last_name;
491
+	public $ship_to_company;
492
+	public $ship_to_address;
493
+	public $ship_to_city;
494
+	public $ship_to_state;
495
+	public $ship_to_zip_code;
496
+	public $ship_to_country;
497
+	public $tax;
498
+	public $duty;
499
+	public $freight;
500
+	public $tax_exempt;
501
+	public $purchase_order_number;
502
+	public $md5_hash;
503
+	public $card_code_response;
504
+	public $cavv_response; // cardholder_authentication_verification_response
505
+	public $account_number;
506
+	public $card_type;
507
+	public $split_tender_id;
508
+	public $requested_amount;
509
+	public $balance_on_card;
510
+	public $response; // The response string from AuthorizeNet.
511
+	public $error_message;
512
+	private $_response_array = array(); // An array with the split response.
513
+
514
+
515
+	/**
516
+	 * Constructor. Parses the AuthorizeNet response string
517
+	 *
518
+	 * @param string $response The response from the AuthNet server.
519
+	 * @var string   $delimiter The delimiter used (default is ",")
520
+	 * @var string   $encap_char The encap_char used (default is "|")
521
+	 * @var array    $custom_fields Any custom fields set in the request.
522
+	 */
523
+
524
+	public function __construct($response)
525
+	{
526
+		$encap_char = $this->_x_post_fields['encap_char'];
527
+		$delimiter = $this->_x_post_fields['delim_char'];
528
+		if ($response) {
529
+			// Split Array
530
+			$this->response = $response;
531
+			if ($encap_char) {
532
+				$this->_response_array = explode($encap_char . $delimiter . $encap_char, substr($response, 1, -1));
533
+			} else {
534
+				$this->_response_array = explode($delimiter, $response);
535
+			}
536
+
537
+			/**
538
+			 * If AuthorizeNet doesn't return a delimited response.
539
+			 */
540
+			if (count($this->_response_array) < 10) {
541
+				$this->approved = false;
542
+				$this->error = true;
543
+				$this->error_message = sprintf(
544
+					esc_html__('Unrecognized response from Authorize.net: %1$s', 'event_espresso'),
545
+					esc_html($response)
546
+				);
547
+				return;
548
+			}
549
+
550
+
551
+
552
+			// Set all fields
553
+			$this->response_code = $this->_response_array[0];
554
+			$this->response_subcode = $this->_response_array[1];
555
+			$this->response_reason_code = $this->_response_array[2];
556
+			$this->response_reason_text = $this->_response_array[3];
557
+			$this->authorization_code = $this->_response_array[4];
558
+			$this->avs_response = $this->_response_array[5];
559
+			$this->transaction_id = $this->_response_array[6];
560
+			$this->invoice_number = $this->_response_array[7];
561
+			$this->description = $this->_response_array[8];
562
+			$this->amount = $this->_response_array[9];
563
+			$this->method = $this->_response_array[10];
564
+			$this->transaction_type = $this->_response_array[11];
565
+			$this->customer_id = $this->_response_array[12];
566
+			$this->first_name = $this->_response_array[13];
567
+			$this->last_name = $this->_response_array[14];
568
+			$this->company = $this->_response_array[15];
569
+			$this->address = $this->_response_array[16];
570
+			$this->city = $this->_response_array[17];
571
+			$this->state = $this->_response_array[18];
572
+			$this->zip_code = $this->_response_array[19];
573
+			$this->country = $this->_response_array[20];
574
+			$this->phone = $this->_response_array[21];
575
+			$this->fax = $this->_response_array[22];
576
+			$this->email_address = $this->_response_array[23];
577
+			$this->ship_to_first_name = $this->_response_array[24];
578
+			$this->ship_to_last_name = $this->_response_array[25];
579
+			$this->ship_to_company = $this->_response_array[26];
580
+			$this->ship_to_address = $this->_response_array[27];
581
+			$this->ship_to_city = $this->_response_array[28];
582
+			$this->ship_to_state = $this->_response_array[29];
583
+			$this->ship_to_zip_code = $this->_response_array[30];
584
+			$this->ship_to_country = $this->_response_array[31];
585
+			$this->tax = $this->_response_array[32];
586
+			$this->duty = $this->_response_array[33];
587
+			$this->freight = $this->_response_array[34];
588
+			$this->tax_exempt = $this->_response_array[35];
589
+			$this->purchase_order_number = $this->_response_array[36];
590
+			$this->md5_hash = $this->_response_array[37];
591
+			$this->card_code_response = $this->_response_array[38];
592
+			$this->cavv_response = $this->_response_array[39];
593
+			$this->account_number = $this->_response_array[50];
594
+			$this->card_type = $this->_response_array[51];
595
+			$this->split_tender_id = $this->_response_array[52];
596
+			$this->requested_amount = $this->_response_array[53];
597
+			$this->balance_on_card = $this->_response_array[54];
598
+
599
+			$this->approved = ($this->response_code === self::APPROVED);
600
+			$this->declined = ($this->response_code === self::DECLINED);
601
+			$this->error = ($this->response_code === self::ERROR);
602
+			$this->held = ($this->response_code === self::HELD);
603
+		} else {
604
+			$this->approved = false;
605
+			$this->error = true;
606
+			$this->error_message = esc_html__(
607
+				'Error connecting to Authorize.net',
608
+				'event_espresso'
609
+			);
610
+		}
611
+	}
612 612
 }
613 613
 
614 614
 if (! class_exists('AuthorizeNetException')) {
615
-    /**
616
-     * Class AuthorizeNetException
617
-     *
618
-     * @package    AuthorizeNet
619
-     */
620
-    class AuthorizeNetException extends Exception
621
-    {
622
-        /**
623
-         * Construct the exception. Note: The message is NOT binary safe.
624
-         *
625
-         * @link http://php.net/manual/en/exception.construct.php
626
-         * @param string $message [optional] The Exception message to throw.
627
-         * @param int $code [optional] The Exception code.
628
-         * @param Exception $previous [optional] The previous exception used for the exception chaining. Since 5.3.0
629
-         * @since 5.1.0
630
-         */
631
-        public function __construct($message = "", $code = 0, Exception $previous = null)
632
-        {
633
-            parent::__construct($message, $code, $previous);
634
-        }
635
-    }
615
+	/**
616
+	 * Class AuthorizeNetException
617
+	 *
618
+	 * @package    AuthorizeNet
619
+	 */
620
+	class AuthorizeNetException extends Exception
621
+	{
622
+		/**
623
+		 * Construct the exception. Note: The message is NOT binary safe.
624
+		 *
625
+		 * @link http://php.net/manual/en/exception.construct.php
626
+		 * @param string $message [optional] The Exception message to throw.
627
+		 * @param int $code [optional] The Exception code.
628
+		 * @param Exception $previous [optional] The previous exception used for the exception chaining. Since 5.3.0
629
+		 * @since 5.1.0
630
+		 */
631
+		public function __construct($message = "", $code = 0, Exception $previous = null)
632
+		{
633
+			parent::__construct($message, $code, $previous);
634
+		}
635
+	}
636 636
 }
Please login to merge, or discard this patch.
caffeinated/payment_methods/Aim/templates/aim_intro.template.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -1,10 +1,10 @@
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 printf(
4
-    esc_html__(
5
-        'Authorize.Net AIM is an on-site payment method for accepting credit and debit card payments and is available to event organizers in the United States, Canada, United Kingdom, and Australia. An account with Authorize.Net is required to accept payments. Need an Authorize.Net account? %1$sClick here to sign up for a merchant account%2$s.',
6
-        'event_espresso'
7
-    ),
8
-    '<a href="https://eventespresso.com/go/authorizenetaim/" target="_blank">',
9
-    '</a>'
4
+	esc_html__(
5
+		'Authorize.Net AIM is an on-site payment method for accepting credit and debit card payments and is available to event organizers in the United States, Canada, United Kingdom, and Australia. An account with Authorize.Net is required to accept payments. Need an Authorize.Net account? %1$sClick here to sign up for a merchant account%2$s.',
6
+		'event_espresso'
7
+	),
8
+	'<a href="https://eventespresso.com/go/authorizenetaim/" target="_blank">',
9
+	'</a>'
10 10
 );
Please login to merge, or discard this patch.
caffeinated/modules/recaptcha/autoload.php 2 patches
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -7,33 +7,33 @@
 block discarded – undo
7 7
  */
8 8
 
9 9
 spl_autoload_register(function ($class) {
10
-    if (substr($class, 0, 10) !== 'ReCaptcha\\') {
11
-        /* If the class does not lie under the "ReCaptcha" namespace,
10
+	if (substr($class, 0, 10) !== 'ReCaptcha\\') {
11
+		/* If the class does not lie under the "ReCaptcha" namespace,
12 12
          * then we can exit immediately.
13 13
          */
14
-        return;
15
-    }
14
+		return;
15
+	}
16 16
 
17
-    /* All of the classes have names like "ReCaptcha\Foo", so we need
17
+	/* All of the classes have names like "ReCaptcha\Foo", so we need
18 18
      * to replace the backslashes with frontslashes if we want the
19 19
      * name to map directly to a location in the filesystem.
20 20
      */
21
-    $class = str_replace('\\', '/', $class);
21
+	$class = str_replace('\\', '/', $class);
22 22
 
23
-    /* First, check under the current directory. It is important that
23
+	/* First, check under the current directory. It is important that
24 24
      * we look here first, so that we don't waste time searching for
25 25
      * test classes in the common case.
26 26
      */
27
-    $path = dirname(__FILE__) . '/' . $class . '.php';
28
-    if (is_readable($path)) {
29
-        require_once $path;
30
-    }
27
+	$path = dirname(__FILE__) . '/' . $class . '.php';
28
+	if (is_readable($path)) {
29
+		require_once $path;
30
+	}
31 31
 
32
-    /* If we didn't find what we're looking for already, maybe it's
32
+	/* If we didn't find what we're looking for already, maybe it's
33 33
      * a test class?
34 34
      */
35
-    $path = dirname(__FILE__) . '/../tests/' . $class . '.php';
36
-    if (is_readable($path)) {
37
-        require_once $path;
38
-    }
35
+	$path = dirname(__FILE__) . '/../tests/' . $class . '.php';
36
+	if (is_readable($path)) {
37
+		require_once $path;
38
+	}
39 39
 });
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
  * classes.
7 7
  */
8 8
 
9
-spl_autoload_register(function ($class) {
9
+spl_autoload_register(function($class) {
10 10
     if (substr($class, 0, 10) !== 'ReCaptcha\\') {
11 11
         /* If the class does not lie under the "ReCaptcha" namespace,
12 12
          * then we can exit immediately.
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
      * we look here first, so that we don't waste time searching for
25 25
      * test classes in the common case.
26 26
      */
27
-    $path = dirname(__FILE__) . '/' . $class . '.php';
27
+    $path = dirname(__FILE__).'/'.$class.'.php';
28 28
     if (is_readable($path)) {
29 29
         require_once $path;
30 30
     }
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
     /* If we didn't find what we're looking for already, maybe it's
33 33
      * a test class?
34 34
      */
35
-    $path = dirname(__FILE__) . '/../tests/' . $class . '.php';
35
+    $path = dirname(__FILE__).'/../tests/'.$class.'.php';
36 36
     if (is_readable($path)) {
37 37
         require_once $path;
38 38
     }
Please login to merge, or discard this patch.
core/libraries/rest_api/Capabilities.php 2 patches
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
     ) {
100 100
         $has_password = $model->hasPassword();
101 101
         if ($has_password) {
102
-            $entity[ $model->getPasswordField()->get_name() ] = ModelDataTranslator::prepareFieldValueForJson(
102
+            $entity[$model->getPasswordField()->get_name()] = ModelDataTranslator::prepareFieldValueForJson(
103 103
                 $model->getPasswordField(),
104 104
                 $model->getPasswordField()->get_default_value(),
105 105
                 $model_version_info->requestedVersion()
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
             if (
110 110
                 $has_password
111 111
                 && $model->getPasswordField()->fieldIsProtected($field_name)
112
-                && $entity[ $field_name ]
112
+                && $entity[$field_name]
113 113
             ) {
114 114
                 $replacement_value = ModelDataTranslator::prepareFieldValueForJson(
115 115
                     $field_obj,
@@ -117,10 +117,10 @@  discard block
 block discarded – undo
117 117
                     $model_version_info->requestedVersion()
118 118
                 );
119 119
                 if ($model_version_info->fieldHasRenderedFormat($field_obj)) {
120
-                    $entity[ $field_name ]['rendered'] = $replacement_value;
120
+                    $entity[$field_name]['rendered'] = $replacement_value;
121 121
                 } elseif ($model_version_info->fieldHasPrettyFormat($field_obj)) {
122
-                    $entity[ $field_name ]['raw'] = $replacement_value;
123
-                    $entity[ $field_name ]['pretty'] = ModelDataTranslator::prepareFieldValueForJson(
122
+                    $entity[$field_name]['raw'] = $replacement_value;
123
+                    $entity[$field_name]['pretty'] = ModelDataTranslator::prepareFieldValueForJson(
124 124
                         $field_obj,
125 125
                         $field_obj->prepare_for_pretty_echoing($field_obj->get_default_value()),
126 126
                         $model_version_info->requestedVersion()
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
                     // so just remove it (or rather, set its default)
132 132
                     // API clients will just need to look to fields with rendered formats to know if these have
133 133
                     // been redacted. Sorry.
134
-                    $entity[ $field_name ] = $replacement_value;
134
+                    $entity[$field_name] = $replacement_value;
135 135
                 }
136 136
             }
137 137
         }
@@ -160,11 +160,11 @@  discard block
 block discarded – undo
160 160
         foreach ($model->field_settings() as $field_name => $field_obj) {
161 161
             if (
162 162
                 $model_version_info->fieldHasRenderedFormat($field_obj)
163
-                && isset($entity[ $field_name ])
164
-                && is_array($entity[ $field_name ])
165
-                && isset($entity[ $field_name ]['raw'])
163
+                && isset($entity[$field_name])
164
+                && is_array($entity[$field_name])
165
+                && isset($entity[$field_name]['raw'])
166 166
             ) {
167
-                unset($entity[ $field_name ]['raw']);
167
+                unset($entity[$field_name]['raw']);
168 168
             }
169 169
         }
170 170
         // theoretically we may want to filter out specific fields for specific models
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
      */
191 191
     public static function verifyAtLeastPartialAccessTo($model, $model_action_context, $action_name = 'list')
192 192
     {
193
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
193
+        if ( ! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
194 194
             $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
195 195
             throw new RestException(
196 196
                 sprintf('rest_cannot_%s_%s', strtolower($action_name), $model_name_plural),
Please login to merge, or discard this patch.
Indentation   +177 added lines, -177 removed lines patch added patch discarded remove patch
@@ -18,190 +18,190 @@
 block discarded – undo
18 18
  */
19 19
 class Capabilities
20 20
 {
21
-    /**
22
-     * The current user can see at least SOME of these entities.
23
-     *
24
-     * @param EEM_Base $model
25
-     * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
26
-     * @return boolean
27
-     */
28
-    public static function currentUserHasPartialAccessTo($model, $model_context = EEM_Base::caps_read)
29
-    {
30
-        if (
31
-            apply_filters(
32
-                'FHEE__Capabilities__current_user_has_partial_access_to__override_begin',
33
-                false,
34
-                $model,
35
-                $model
36
-            )
37
-        ) {
38
-            return true;
39
-        }
40
-        foreach ($model->caps_missing($model_context) as $capability_name => $restriction_obj) {
41
-            if ($restriction_obj instanceof EE_Return_None_Where_Conditions) {
42
-                return false;
43
-            }
44
-        }
45
-        if (
46
-            apply_filters(
47
-                'FHEE__Capabilities__current_user_has_partial_access_to__override_end',
48
-                false,
49
-                $model,
50
-                $model
51
-            )
52
-        ) {
53
-            return false;
54
-        }
55
-        return true;
56
-    }
21
+	/**
22
+	 * The current user can see at least SOME of these entities.
23
+	 *
24
+	 * @param EEM_Base $model
25
+	 * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
26
+	 * @return boolean
27
+	 */
28
+	public static function currentUserHasPartialAccessTo($model, $model_context = EEM_Base::caps_read)
29
+	{
30
+		if (
31
+			apply_filters(
32
+				'FHEE__Capabilities__current_user_has_partial_access_to__override_begin',
33
+				false,
34
+				$model,
35
+				$model
36
+			)
37
+		) {
38
+			return true;
39
+		}
40
+		foreach ($model->caps_missing($model_context) as $capability_name => $restriction_obj) {
41
+			if ($restriction_obj instanceof EE_Return_None_Where_Conditions) {
42
+				return false;
43
+			}
44
+		}
45
+		if (
46
+			apply_filters(
47
+				'FHEE__Capabilities__current_user_has_partial_access_to__override_end',
48
+				false,
49
+				$model,
50
+				$model
51
+			)
52
+		) {
53
+			return false;
54
+		}
55
+		return true;
56
+	}
57 57
 
58 58
 
59
-    /**
60
-     * Gets an array of all the capabilities the current user is missing that affected
61
-     * the query
62
-     *
63
-     * @param EEM_Base $model
64
-     * @param string   $request_type one of the constants on WP_JSON_Server
65
-     * @return array
66
-     */
67
-    public static function getMissingPermissions($model, $request_type = EEM_Base::caps_read)
68
-    {
69
-        return $model->caps_missing($request_type);
70
-    }
59
+	/**
60
+	 * Gets an array of all the capabilities the current user is missing that affected
61
+	 * the query
62
+	 *
63
+	 * @param EEM_Base $model
64
+	 * @param string   $request_type one of the constants on WP_JSON_Server
65
+	 * @return array
66
+	 */
67
+	public static function getMissingPermissions($model, $request_type = EEM_Base::caps_read)
68
+	{
69
+		return $model->caps_missing($request_type);
70
+	}
71 71
 
72 72
 
73
-    /**
74
-     * Gets a string of all the capabilities the current user is missing that affected
75
-     * the query
76
-     *
77
-     * @param EEM_Base $model
78
-     * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
79
-     * @return string
80
-     */
81
-    public static function getMissingPermissionsString($model, $model_context = EEM_Base::caps_read)
82
-    {
83
-        return implode(',', array_keys(self::getMissingPermissions($model, $model_context)));
84
-    }
73
+	/**
74
+	 * Gets a string of all the capabilities the current user is missing that affected
75
+	 * the query
76
+	 *
77
+	 * @param EEM_Base $model
78
+	 * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
79
+	 * @return string
80
+	 */
81
+	public static function getMissingPermissionsString($model, $model_context = EEM_Base::caps_read)
82
+	{
83
+		return implode(',', array_keys(self::getMissingPermissions($model, $model_context)));
84
+	}
85 85
 
86
-    /**
87
-     * "Removes" password-protected fields. Currently that means setting their values to their default.
88
-     * @since 4.9.74.p
89
-     * @param array $entity
90
-     * @param EEM_Base $model
91
-     * @param ModelVersionInfo $model_version_info
92
-     * @return array
93
-     * @throws EE_Error
94
-     */
95
-    public static function filterOutPasswordProtectedFields(
96
-        $entity,
97
-        $model,
98
-        $model_version_info
99
-    ) {
100
-        $has_password = $model->hasPassword();
101
-        if ($has_password) {
102
-            $entity[ $model->getPasswordField()->get_name() ] = ModelDataTranslator::prepareFieldValueForJson(
103
-                $model->getPasswordField(),
104
-                $model->getPasswordField()->get_default_value(),
105
-                $model_version_info->requestedVersion()
106
-            );
107
-        }
108
-        foreach ($model->field_settings() as $field_name => $field_obj) {
109
-            if (
110
-                $has_password
111
-                && $model->getPasswordField()->fieldIsProtected($field_name)
112
-                && $entity[ $field_name ]
113
-            ) {
114
-                $replacement_value = ModelDataTranslator::prepareFieldValueForJson(
115
-                    $field_obj,
116
-                    $field_obj->get_default_value(),
117
-                    $model_version_info->requestedVersion()
118
-                );
119
-                if ($model_version_info->fieldHasRenderedFormat($field_obj)) {
120
-                    $entity[ $field_name ]['rendered'] = $replacement_value;
121
-                } elseif ($model_version_info->fieldHasPrettyFormat($field_obj)) {
122
-                    $entity[ $field_name ]['raw'] = $replacement_value;
123
-                    $entity[ $field_name ]['pretty'] = ModelDataTranslator::prepareFieldValueForJson(
124
-                        $field_obj,
125
-                        $field_obj->prepare_for_pretty_echoing($field_obj->get_default_value()),
126
-                        $model_version_info->requestedVersion()
127
-                    );
128
-                } else {
129
-                    // this is most likely an excerpt field. (These should have also had "rendered" and "raw"
130
-                    // versions, but we missed that, and can't change it without breaking backward compatibility)
131
-                    // so just remove it (or rather, set its default)
132
-                    // API clients will just need to look to fields with rendered formats to know if these have
133
-                    // been redacted. Sorry.
134
-                    $entity[ $field_name ] = $replacement_value;
135
-                }
136
-            }
137
-        }
138
-        return $entity;
139
-    }
86
+	/**
87
+	 * "Removes" password-protected fields. Currently that means setting their values to their default.
88
+	 * @since 4.9.74.p
89
+	 * @param array $entity
90
+	 * @param EEM_Base $model
91
+	 * @param ModelVersionInfo $model_version_info
92
+	 * @return array
93
+	 * @throws EE_Error
94
+	 */
95
+	public static function filterOutPasswordProtectedFields(
96
+		$entity,
97
+		$model,
98
+		$model_version_info
99
+	) {
100
+		$has_password = $model->hasPassword();
101
+		if ($has_password) {
102
+			$entity[ $model->getPasswordField()->get_name() ] = ModelDataTranslator::prepareFieldValueForJson(
103
+				$model->getPasswordField(),
104
+				$model->getPasswordField()->get_default_value(),
105
+				$model_version_info->requestedVersion()
106
+			);
107
+		}
108
+		foreach ($model->field_settings() as $field_name => $field_obj) {
109
+			if (
110
+				$has_password
111
+				&& $model->getPasswordField()->fieldIsProtected($field_name)
112
+				&& $entity[ $field_name ]
113
+			) {
114
+				$replacement_value = ModelDataTranslator::prepareFieldValueForJson(
115
+					$field_obj,
116
+					$field_obj->get_default_value(),
117
+					$model_version_info->requestedVersion()
118
+				);
119
+				if ($model_version_info->fieldHasRenderedFormat($field_obj)) {
120
+					$entity[ $field_name ]['rendered'] = $replacement_value;
121
+				} elseif ($model_version_info->fieldHasPrettyFormat($field_obj)) {
122
+					$entity[ $field_name ]['raw'] = $replacement_value;
123
+					$entity[ $field_name ]['pretty'] = ModelDataTranslator::prepareFieldValueForJson(
124
+						$field_obj,
125
+						$field_obj->prepare_for_pretty_echoing($field_obj->get_default_value()),
126
+						$model_version_info->requestedVersion()
127
+					);
128
+				} else {
129
+					// this is most likely an excerpt field. (These should have also had "rendered" and "raw"
130
+					// versions, but we missed that, and can't change it without breaking backward compatibility)
131
+					// so just remove it (or rather, set its default)
132
+					// API clients will just need to look to fields with rendered formats to know if these have
133
+					// been redacted. Sorry.
134
+					$entity[ $field_name ] = $replacement_value;
135
+				}
136
+			}
137
+		}
138
+		return $entity;
139
+	}
140 140
 
141 141
 
142
-    /**
143
-     * Takes a entity that's ready to be returned and removes fields which the user shouldn't be able to access.
144
-     *
145
-     * @param array $entity
146
-     * @param EEM_Base $model
147
-     * @param string $request_type one of the return values from EEM_Base::valid_cap_contexts()
148
-     * @param ModelVersionInfo $model_version_info
149
-     * @param string $primary_key_string result of EEM_Base::get_index_primary_key_string(), so that we can
150
-     *                                               use this with models that have no primary key
151
-     * @return array ready for converting into json
152
-     */
153
-    public static function filterOutInaccessibleEntityFields(
154
-        $entity,
155
-        $model,
156
-        $request_type,
157
-        $model_version_info,
158
-        $primary_key_string = null
159
-    ) {
160
-        foreach ($model->field_settings() as $field_name => $field_obj) {
161
-            if (
162
-                $model_version_info->fieldHasRenderedFormat($field_obj)
163
-                && isset($entity[ $field_name ])
164
-                && is_array($entity[ $field_name ])
165
-                && isset($entity[ $field_name ]['raw'])
166
-            ) {
167
-                unset($entity[ $field_name ]['raw']);
168
-            }
169
-        }
170
-        // theoretically we may want to filter out specific fields for specific models
171
-        return apply_filters(
172
-            'FHEE__Capabilities__filter_out_inaccessible_entity_fields',
173
-            $entity,
174
-            $model,
175
-            $request_type
176
-        );
177
-    }
142
+	/**
143
+	 * Takes a entity that's ready to be returned and removes fields which the user shouldn't be able to access.
144
+	 *
145
+	 * @param array $entity
146
+	 * @param EEM_Base $model
147
+	 * @param string $request_type one of the return values from EEM_Base::valid_cap_contexts()
148
+	 * @param ModelVersionInfo $model_version_info
149
+	 * @param string $primary_key_string result of EEM_Base::get_index_primary_key_string(), so that we can
150
+	 *                                               use this with models that have no primary key
151
+	 * @return array ready for converting into json
152
+	 */
153
+	public static function filterOutInaccessibleEntityFields(
154
+		$entity,
155
+		$model,
156
+		$request_type,
157
+		$model_version_info,
158
+		$primary_key_string = null
159
+	) {
160
+		foreach ($model->field_settings() as $field_name => $field_obj) {
161
+			if (
162
+				$model_version_info->fieldHasRenderedFormat($field_obj)
163
+				&& isset($entity[ $field_name ])
164
+				&& is_array($entity[ $field_name ])
165
+				&& isset($entity[ $field_name ]['raw'])
166
+			) {
167
+				unset($entity[ $field_name ]['raw']);
168
+			}
169
+		}
170
+		// theoretically we may want to filter out specific fields for specific models
171
+		return apply_filters(
172
+			'FHEE__Capabilities__filter_out_inaccessible_entity_fields',
173
+			$entity,
174
+			$model,
175
+			$request_type
176
+		);
177
+	}
178 178
 
179 179
 
180
-    /**
181
-     * Verifies the current user has at least partial access to do this action on this model.
182
-     * If not, throws an exception (so we can define the code that sets up this error object
183
-     * once)
184
-     *
185
-     * @param EEM_Base $model
186
-     * @param string   $model_action_context
187
-     * @param string   $action_name
188
-     * @return void
189
-     * @throws RestException
190
-     */
191
-    public static function verifyAtLeastPartialAccessTo($model, $model_action_context, $action_name = 'list')
192
-    {
193
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
194
-            $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
195
-            throw new RestException(
196
-                sprintf('rest_cannot_%s_%s', strtolower($action_name), $model_name_plural),
197
-                sprintf(
198
-                    esc_html__('Sorry, you are not allowed to %1$s %2$s. Missing permissions: %3$s', 'event_espresso'),
199
-                    $action_name,
200
-                    $model_name_plural,
201
-                    Capabilities::getMissingPermissionsString($model, $model_action_context)
202
-                ),
203
-                array('status' => 403)
204
-            );
205
-        }
206
-    }
180
+	/**
181
+	 * Verifies the current user has at least partial access to do this action on this model.
182
+	 * If not, throws an exception (so we can define the code that sets up this error object
183
+	 * once)
184
+	 *
185
+	 * @param EEM_Base $model
186
+	 * @param string   $model_action_context
187
+	 * @param string   $action_name
188
+	 * @return void
189
+	 * @throws RestException
190
+	 */
191
+	public static function verifyAtLeastPartialAccessTo($model, $model_action_context, $action_name = 'list')
192
+	{
193
+		if (! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
194
+			$model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
195
+			throw new RestException(
196
+				sprintf('rest_cannot_%s_%s', strtolower($action_name), $model_name_plural),
197
+				sprintf(
198
+					esc_html__('Sorry, you are not allowed to %1$s %2$s. Missing permissions: %3$s', 'event_espresso'),
199
+					$action_name,
200
+					$model_name_plural,
201
+					Capabilities::getMissingPermissionsString($model, $model_action_context)
202
+				),
203
+				array('status' => 403)
204
+			);
205
+		}
206
+	}
207 207
 }
Please login to merge, or discard this patch.
core/libraries/rest_api/RestIncomingQueryParamMetadata.php 2 patches
Indentation   +701 added lines, -701 removed lines patch added patch discarded remove patch
@@ -28,707 +28,707 @@
 block discarded – undo
28 28
  */
29 29
 class RestIncomingQueryParamMetadata
30 30
 {
31
-    private $query_param_key;
32
-    private $query_param_value;
33
-    /**
34
-     * @var RestIncomingQueryParamContext
35
-     */
36
-    private $context;
37
-
38
-    /**
39
-     * @var EE_Model_Field_Base|null
40
-     */
41
-    private $field;
42
-
43
-    /**
44
-     * @var string same as $query_param_key but has the * and anything after it removed
45
-     */
46
-    private $query_param_key_sans_stars;
47
-
48
-    /**
49
-     * @var string for timezone or timezone offset
50
-     */
51
-    private $timezone;
52
-
53
-    /**
54
-     * @var boolean if the field in $query_param_key is for a GMT field (eg `EVT_modified_gmt`)
55
-     */
56
-    private $is_gmt_field = false;
57
-
58
-    /**
59
-     * RestIncomingQueryParamMetadata constructor.
60
-     * You probably want to call
61
-     * @param string $query_param_key
62
-     * @param string $query_param_value
63
-     * @param RestIncomingQueryParamContext $context
64
-     */
65
-    public function __construct($query_param_key, $query_param_value, RestIncomingQueryParamContext $context)
66
-    {
67
-        $this->query_param_key = $query_param_key;
68
-        $this->query_param_value = $query_param_value;
69
-        $this->context = $context;
70
-        $this->determineFieldAndTimezone();
71
-    }
72
-
73
-    /**
74
-     * Gets the query parameter key. This may have been modified (see setQueryParamValue())
75
-     * @return string
76
-     */
77
-    public function getQueryParamKey()
78
-    {
79
-        return $this->query_param_key;
80
-    }
81
-
82
-    /**
83
-     * Modifies the query parameter key passed in (Eg this is done when rewriting the simplified specified operator REST
84
-     * query parameters into the legacy structure)
85
-     * @param string|array|int|float $query_param_value
86
-     */
87
-    private function setQueryParamValue($query_param_value)
88
-    {
89
-        $this->query_param_value = $query_param_value;
90
-    }
91
-
92
-    /**
93
-     * Gets the original query parameter value passed in.
94
-     * @return string
95
-     */
96
-    public function getQueryParamValue()
97
-    {
98
-        return $this->query_param_value;
99
-    }
100
-
101
-    /**
102
-     * Gets the context object.
103
-     * @return RestIncomingQueryParamContext
104
-     */
105
-    public function getContext()
106
-    {
107
-        return $this->context;
108
-    }
109
-
110
-    /**
111
-     * Sets the query parameter key. This may be used to rewrite a key into its non-GMT alternative.
112
-     * @param string $query_param_key
113
-     */
114
-    private function setQueryParamKey($query_param_key)
115
-    {
116
-        $this->query_param_key = $query_param_key;
117
-    }
118
-
119
-    /**
120
-     * Gets the field the query parameter key indicated. This may be null (in cases where the query parameter key
121
-     * did not indicate a field, eg if it were `OR`).
122
-     * @return EE_Model_Field_Base|null
123
-     */
124
-    public function getField()
125
-    {
126
-        return $this->field;
127
-    }
128
-
129
-    /**
130
-     * Gets the query parameter key (with the star and everything afterwards removed).
131
-     * @return string
132
-     */
133
-    public function getQueryParamKeySansStars()
134
-    {
135
-        return $this->query_param_key_sans_stars;
136
-    }
137
-
138
-    /**
139
-     * Gets the timezone associated with this model (the site timezone, except for GMT datetime fields).
140
-     * @return string
141
-     */
142
-    public function getTimezone()
143
-    {
144
-        return $this->timezone;
145
-    }
146
-
147
-    /**
148
-     * Returns whether or not this is a GMT field
149
-     * @return boolean
150
-     */
151
-    public function isGmtField()
152
-    {
153
-        return $this->is_gmt_field;
154
-    }
155
-
156
-    /**
157
-     * Sets the field indicated by the query parameter key (might be null).
158
-     * @param EE_Model_Field_Base|null $field
159
-     */
160
-    private function setField(EE_Model_Field_Base $field = null)
161
-    {
162
-        $this->field = $field;
163
-    }
164
-
165
-    /**
166
-     * Sets the query parameter key-with-stars-removed.
167
-     * @param string $query_param_key_sans_stars
168
-     */
169
-    private function setQueryParamKeySansStars($query_param_key_sans_stars)
170
-    {
171
-        $this->query_param_key_sans_stars = $query_param_key_sans_stars;
172
-    }
173
-
174
-    /**
175
-     * Sets the timezone (this could be a timezeon offset string).
176
-     * @param string $timezone
177
-     */
178
-    private function setTimezone($timezone)
179
-    {
180
-        $this->timezone = $timezone;
181
-    }
182
-
183
-    /**
184
-     * @param mixed $is_gmt_field
185
-     */
186
-    private function setIsGmtField($is_gmt_field)
187
-    {
188
-        $this->is_gmt_field = $is_gmt_field;
189
-    }
190
-
191
-    /**
192
-     * Determines what field, query param name, and query param name without stars, and timezone to use.
193
-     * @since 4.9.72.p
194
-     * @type EE_Model_Field_Base $field
195
-     * @return void {
196
-     * @throws EE_Error
197
-     * @throws InvalidDataTypeException
198
-     * @throws InvalidInterfaceException
199
-     * @throws InvalidArgumentException
200
-     */
201
-    private function determineFieldAndTimezone()
202
-    {
203
-        $this->setQueryParamKeySansStars(ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
204
-            $this->getQueryParamKey()
205
-        ));
206
-        $this->setField(ModelDataTranslator::deduceFieldFromQueryParam(
207
-            $this->getQueryParamKeySansStars(),
208
-            $this->getContext()->getModel()
209
-        ));
210
-        // double-check is it a *_gmt field?
211
-        if (
212
-            !$this->getField() instanceof EE_Model_Field_Base
213
-            && ModelDataTranslator::isGmtDateFieldName($this->getQueryParamKeySansStars())
214
-        ) {
215
-            // yep, take off '_gmt', and find the field
216
-            $this->setQueryParamKey(ModelDataTranslator::removeGmtFromFieldName($this->getQueryParamKeySansStars()));
217
-            $this->setField(ModelDataTranslator::deduceFieldFromQueryParam(
218
-                $this->getQueryParamKey(),
219
-                $this->context->getModel()
220
-            ));
221
-            $this->setTimezone('UTC');
222
-            $this->setIsGmtField(true);
223
-        } elseif ($this->getField() instanceof EE_Datetime_Field) {
224
-            // so it's not a GMT field. Set the timezone on the model to the default
225
-            $this->setTimezone(EEH_DTT_Helper::get_valid_timezone_string());
226
-        } else {
227
-            // just keep using what's already set for the timezone
228
-            $this->setTimezone($this->context->getModel()->get_timezone());
229
-        }
230
-        $this->assertOnlyAdminCanReadPasswordFields();
231
-    }
232
-
233
-    /**
234
-     * Throws an exception if a non-admin is trying to query by password.
235
-     * @since 4.9.74.p
236
-     * @throws RestException
237
-     */
238
-    private function assertOnlyAdminCanReadPasswordFields()
239
-    {
240
-        if (
241
-            $this->getField() instanceof EE_Password_Field
242
-            && ! current_user_can(EE_Restriction_Generator_Base::get_default_restrictions_cap())
243
-        ) {
244
-            // only full admins can query by password. sorry bub!
245
-            throw new RestException(
246
-                'only_admins_can_query_by_password',
247
-                // @codingStandardsIgnoreStart
248
-                esc_html__('You attempted to filter by a password field without the needed privileges. Only a full admin is allowed to do that.', 'event_espresso'),
249
-                // @codingStandardsIgnoreEnd
250
-                array(
251
-                    'status' => 403
252
-                )
253
-            );
254
-        }
255
-    }
256
-
257
-    /**
258
-     * Given a ton of input, determines the value to use for the models.
259
-     * @since 4.9.72.p
260
-     * @return array|null
261
-     * @throws DomainException
262
-     * @throws EE_Error
263
-     * @throws RestException
264
-     * @throws DomainException
265
-     */
266
-    public function determineConditionsQueryParameterValue()
267
-    {
268
-        if ($this->valueIsArrayDuringRead()) {
269
-            return $this->determineModelValueGivenRestInputArray();
270
-        }
271
-        return ModelDataTranslator::prepareFieldValueFromJson(
272
-            $this->getField(),
273
-            $this->getQueryParamValue(),
274
-            $this->getContext()->getRequestedVersion(),
275
-            $this->getTimezone()
276
-        );
277
-    }
278
-
279
-    /**
280
-     * Given that the array value provided was itself an array, handles finding the correct value to pass to the model.
281
-     * @since 4.9.72.p
282
-     * @return array|null
283
-     * @throws RestException
284
-     */
285
-    private function determineModelValueGivenRestInputArray()
286
-    {
287
-        $this->transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax();
288
-        // did they specify an operator?
289
-        if ($this->valueIsLegacySpecifiedOperator()) {
290
-            $query_param_value = $this->getQueryParamValue();
291
-            $sub_array_key = $query_param_value[0];
292
-            $translated_value = array($sub_array_key);
293
-            if ($this->operatorIsNAry($sub_array_key)) {
294
-                $translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
295
-            } elseif ($this->operatorIsTernary($sub_array_key)) {
296
-                $translated_value[] = array(
297
-                    $this->prepareValuesFromJson($query_param_value[1][0]),
298
-                    $this->prepareValuesFromJson($query_param_value[1][1])
299
-                );
300
-            } elseif ($this->operatorIsLike($sub_array_key)) {
301
-                // we want to leave this value mostly-as-is (eg don't force it to be a float
302
-                // or a boolean or an enum value. Leave it as-is with wildcards etc)
303
-                // but do verify it at least doesn't have any serialized data
304
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
305
-                $translated_value[] = $query_param_value[1];
306
-            } elseif ($this->operatorIsUnary($sub_array_key)) {
307
-                // no arguments should have been provided, so don't look for any
308
-            } elseif ($this->operatorisBinary($sub_array_key)) {
309
-                // it's a valid operator, but none of the exceptions. Treat it normally.
310
-                $translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
311
-            } else {
312
-                // so they provided a valid operator, but wrong number of arguments
313
-                $this->throwWrongNumberOfArgsExceptionIfDebugging($sub_array_key);
314
-                $translated_value = null;
315
-            }
316
-        } else {
317
-            // so they didn't provide a valid operator
318
-            // if we aren't in debug mode, then just try our best to fulfill the user's request
319
-            $this->throwInvalidOperatorExceptionIfDebugging();
320
-            $translated_value = null;
321
-        }
322
-        return $translated_value;
323
-    }
324
-
325
-    /**
326
-     * Returns if this request is a "read" request and the value provided was an array.
327
-     * This will indicate is such things as `array('<', 123)` and `array('IN', array(1,2,3))` are acceptable or not.
328
-     * @since 4.9.72.p
329
-     * @return boolean
330
-     */
331
-    private function valueIsArrayDuringRead()
332
-    {
333
-        return !$this->getContext()->isWriting() && is_array($this->getQueryParamValue());
334
-    }
335
-
336
-    /**
337
-     * Returns if the value provided was an associative array (we should have already verified it's an array of some
338
-     * sort). If the value is an associative array, it had better be in the simplified specified operator structure.
339
-     * @since 4.9.72.p
340
-     * @return boolean
341
-     */
342
-    private function valueIsAssociativeArray()
343
-    {
344
-        return !EEH_Array::is_array_numerically_and_sequentially_indexed($this->getQueryParamValue());
345
-    }
346
-
347
-    /**
348
-     * Checks if the array value is itself an array that fits into the simplified specified operator structure
349
-     * (eg `array('!=' => 123)`).
350
-     * @since 4.9.72.p
351
-     * @return boolean
352
-     */
353
-    private function valueIsSimplifiedSpecifiedOperator()
354
-    {
355
-        return count($this->getQueryParamValue()) === 1
356
-            && array_key_exists(
357
-                key($this->getQueryParamValue()),
358
-                $this->getContext()->getModel()->valid_operators()
359
-            );
360
-    }
361
-
362
-    /**
363
-     * Throws an exception if the sub-value is an array (eg `array('!=' => array())`). It needs to just be a string,
364
-     * of either comma-separated-values, or a JSON array.
365
-     * @since 4.9.72.p
366
-     * @param $sub_array_key
367
-     * @param $sub_array_value
368
-     * @throws RestException
369
-     */
370
-    private function assertSubValueIsntArray($sub_array_key, $sub_array_value)
371
-    {
372
-        if (is_array($sub_array_value) && EED_Core_Rest_Api::debugMode()) {
373
-            throw new RestException(
374
-                'csv_or_json_string_only',
375
-                sprintf(
376
-                    /* translators: 1: variable name*/
377
-                    esc_html__(
378
-                        'The value provided for the operator "%1$s" should be comma-separated value string or a JSON array.',
379
-                        'event_espresso'
380
-                    ),
381
-                    $sub_array_key
382
-                ),
383
-                array(
384
-                    'status' => 400,
385
-                )
386
-            );
387
-        }
388
-    }
389
-
390
-    /**
391
-     * Determines if the sub-array key is an operator taking 3 or more operators.
392
-     * @since 4.9.72.p
393
-     * @param $sub_array_key
394
-     * @return boolean
395
-     */
396
-    private function subArrayKeyIsNonBinaryOperator($sub_array_key)
397
-    {
398
-        return array_key_exists(
399
-            $sub_array_key,
400
-            array_merge(
401
-                $this->getContext()->getModel()->valid_in_style_operators(),
402
-                $this->getContext()->getModel()->valid_between_style_operators()
403
-            )
404
-        );
405
-    }
406
-
407
-    /**
408
-     * Given that the $sub_array_key is a string, checks if it's an operator taking only 1 argument.
409
-     * @since 4.9.72.p
410
-     * @param string $sub_array_key
411
-     * @return boolean
412
-     */
413
-    private function subArrayKeyIsUnaryOperator($sub_array_key)
414
-    {
415
-        return array_key_exists(
416
-            $sub_array_key,
417
-            $this->getContext()->getModel()->valid_null_style_operators()
418
-        );
419
-    }
420
-
421
-    /**
422
-     * Parses the $sub_array_value string into an array (given it could either be a comma-separated-list or a JSON
423
-     * array). eg `"1,2,3"` or `"[1,2,3]"` into `array(1,2,3)`.
424
-     * @since 4.9.72.p
425
-     * @param $sub_array_value
426
-     * @return array|mixed|object
427
-     */
428
-    private function extractQuickStyleSpecifiedOperatorValue($sub_array_value)
429
-    {
430
-        // the value should be JSON or CSV
431
-        $values = json_decode($sub_array_value);
432
-        if (!is_array($values)) {
433
-            $values = array_filter(
434
-                array_map(
435
-                    'trim',
436
-                    explode(
437
-                        ',',
438
-                        $sub_array_value
439
-                    )
440
-                )
441
-            );
442
-        }
443
-        return $values;
444
-    }
445
-
446
-    /**
447
-     * Throws an exception if the value isn't a simplified specified operator (only called when we expect that).
448
-     * @since 4.9.72.p
449
-     * @throws RestException
450
-     */
451
-    private function assertSimplifiedSpecifiedOperator()
452
-    {
453
-        if (!$this->valueIsSimplifiedSpecifiedOperator() && EED_Core_Rest_Api::debugMode()) {
454
-            throw new RestException(
455
-                'numerically_indexed_array_of_values_only',
456
-                sprintf(
457
-                    /* translators: 1: variable name*/
458
-                    esc_html__(
459
-                        'The array provided for the parameter "%1$s" should be numerically indexed.',
460
-                        'event_espresso'
461
-                    ),
462
-                    $this->getQueryParamKey()
463
-                ),
464
-                array(
465
-                    'status' => 400,
466
-                )
467
-            );
468
-        }
469
-    }
470
-
471
-    /**
472
-     * If query_param_value were in the simplified specific operator structure, change it into the legacy structure.
473
-     * @since 4.9.72.p
474
-     * @throws RestException
475
-     */
476
-    private function transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax()
477
-    {
478
-        if ($this->valueIsAssociativeArray()) {
479
-            $this->assertSimplifiedSpecifiedOperator();
480
-            $query_param_value = $this->getQueryParamValue();
481
-            $sub_array_value = reset($query_param_value);
482
-            $sub_array_key = key($query_param_value);
483
-            $this->assertSubValueIsntArray($sub_array_key, $sub_array_value);
484
-            // they're doing something like "&where[EVT_ID][IN]=1,2,3" or "&where[EVT_ID][>]=5"
485
-            if ($this->subArrayKeyIsNonBinaryOperator($sub_array_key)) {
486
-                $this->setQueryParamValue(array(
487
-                    $sub_array_key,
488
-                    $this->extractQuickStyleSpecifiedOperatorValue($sub_array_value)
489
-                ));
490
-            } elseif ($this->subArrayKeyIsUnaryOperator($sub_array_key)) {
491
-                $this->setQueryParamValue(array($sub_array_key));
492
-            } else {
493
-                $this->setQueryParamValue(array($sub_array_key, $sub_array_value));
494
-            }
495
-        }
496
-    }
497
-
498
-    /**
499
-     * Returns true is the value is an array using the legacy structure to specify the operator. Eg `array('!=',123)`.
500
-     * @since 4.9.72.p
501
-     * @return boolean
502
-     */
503
-    private function valueIsLegacySpecifiedOperator()
504
-    {
505
-        $valid_operators = $this->getContext()->getModel()->valid_operators();
506
-        $query_param_value = $this->getQueryParamValue();
507
-        return isset($query_param_value[0])
508
-            && isset($valid_operators[ $query_param_value[0] ]);
509
-    }
510
-
511
-    /**
512
-     * Returns true if the value specified operator accepts arbitrary number of arguments, like "IN".
513
-     * @since 4.9.72.p
514
-     * @param $operator
515
-     * @return boolean
516
-     */
517
-    private function operatorIsNAry($operator)
518
-    {
519
-        $valueArray = $this->getQueryParamValue();
520
-        return array_key_exists(
521
-            $operator,
522
-            $this->getContext()->getModel()->valid_in_style_operators()
523
-        )
524
-            && isset($valueArray[1])
525
-            && is_array($valueArray[1])
526
-            && !isset($valueArray[2]);
527
-    }
528
-
529
-    /**
530
-     * Returns true if the operator accepts 3 arguments (eg "BETWEEN").
531
-     * So we're looking for a value that looks like
532
-     * `array('BETWEEN', array('2015-01-01T00:00:00', '2016-01-01T00:00:00'))`.
533
-     * @since 4.9.72.p
534
-     * @param $operator
535
-     * @return boolean
536
-     */
537
-    private function operatorIsTernary($operator)
538
-    {
539
-        $query_param_value = $this->getQueryParamValue();
540
-        return array_key_exists($operator, $this->getContext()->getModel()->valid_between_style_operators())
541
-            && isset($query_param_value[1])
542
-            && is_array($query_param_value[1])
543
-            && isset($query_param_value[1][0], $query_param_value[1][1])
544
-            && !isset($query_param_value[1][2])
545
-            && !isset($query_param_value[2]);
546
-    }
547
-
548
-    /**
549
-     * Returns true if the operator is a similar to LIKE, indicating the value may have wildcards we should leave alone.
550
-     * @since 4.9.72.p
551
-     * @param $operator
552
-     * @return boolean
553
-     */
554
-    private function operatorIsLike($operator)
555
-    {
556
-        $query_param_value = $this->getQueryParamValue();
557
-        return array_key_exists($operator, $this->getContext()->getModel()->valid_like_style_operators())
558
-            && isset($query_param_value[1])
559
-            && !isset($query_param_value[2]);
560
-    }
561
-
562
-    /**
563
-     * Returns true if the operator only takes one argument (eg it's like `IS NULL`).
564
-     * @since 4.9.72.p
565
-     * @param $operator
566
-     * @return boolean
567
-     */
568
-    private function operatorIsUnary($operator)
569
-    {
570
-        $query_param_value = $this->getQueryParamValue();
571
-        return array_key_exists($operator, $this->getContext()->getModel()->valid_null_style_operators())
572
-            && !isset($query_param_value[1]);
573
-    }
574
-
575
-    /**
576
-     * Returns true if the operator specified is a binary opeator (eg `=`, `!=`)
577
-     * @since 4.9.72.p
578
-     * @param $operator
579
-     * @return boolean
580
-     */
581
-    private function operatorisBinary($operator)
582
-    {
583
-        $query_param_value = $this->getQueryParamValue();
584
-        $model = $this->getContext()->getModel();
585
-        return isset($query_param_value[1])
586
-            && !isset($query_param_value[2])
587
-            && !array_key_exists(
588
-                $operator,
589
-                array_merge(
590
-                    $model->valid_in_style_operators(),
591
-                    $model->valid_null_style_operators(),
592
-                    $model->valid_like_style_operators(),
593
-                    $model->valid_between_style_operators()
594
-                )
595
-            );
596
-    }
597
-
598
-    /**
599
-     * If we're debugging, throws an exception saying that the wrong number of arguments was provided.
600
-     * @since 4.9.72.p
601
-     * @param $operator
602
-     * @throws RestException
603
-     */
604
-    private function throwWrongNumberOfArgsExceptionIfDebugging($operator)
605
-    {
606
-        if (EED_Core_Rest_Api::debugMode()) {
607
-            throw new RestException(
608
-                'wrong_number_of_arguments',
609
-                sprintf(
610
-                    esc_html__(
611
-                        'The operator you provided, "%1$s" had the wrong number of arguments',
612
-                        'event_espresso'
613
-                    ),
614
-                    $operator
615
-                ),
616
-                array(
617
-                    'status' => 400,
618
-                )
619
-            );
620
-        }
621
-    }
622
-
623
-    /**
624
-     * Wrapper for ModelDataTranslator::prepareFieldValuesFromJson(), just a tad more DRY.
625
-     * @since 4.9.72.p
626
-     * @param $value
627
-     * @return mixed
628
-     * @throws RestException
629
-     */
630
-    private function prepareValuesFromJson($value)
631
-    {
632
-        return ModelDataTranslator::prepareFieldValuesFromJson(
633
-            $this->getField(),
634
-            $value,
635
-            $this->getContext()->getRequestedVersion(),
636
-            $this->getTimezone()
637
-        );
638
-    }
639
-
640
-    /**
641
-     * Throws an exception if an invalid operator was specified and we're debugging.
642
-     * @since 4.9.72.p
643
-     * @throws RestException
644
-     */
645
-    private function throwInvalidOperatorExceptionIfDebugging()
646
-    {
647
-        // so they didn't provide a valid operator
648
-        if (EED_Core_Rest_Api::debugMode()) {
649
-            throw new RestException(
650
-                'invalid_operator',
651
-                sprintf(
652
-                    esc_html__(
653
-                        'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
654
-                        'event_espresso'
655
-                    ),
656
-                    $this->getQueryParamKey(),
657
-                    $this->getQueryParamValue()
658
-                ),
659
-                array(
660
-                    'status' => 400,
661
-                )
662
-            );
663
-        }
664
-    }
665
-
666
-    /**
667
-     * Returns true if the query_param_key was a logic query parameter, eg `OR`, `AND`, `NOT`, `OR*`, etc.
668
-     * @since 4.9.72.p
669
-     * @return boolean
670
-     */
671
-    private function isLogicQueryParam()
672
-    {
673
-        return in_array($this->getQueryParamKeySansStars(), $this->getContext()->getModel()->logic_query_param_keys());
674
-    }
675
-
676
-
677
-    /**
678
-     * If the query param isn't for a field, it must be a nested query parameter which requires different logic.
679
-     * @since 4.9.72.p
680
-     * @return array
681
-     * @throws DomainException
682
-     * @throws EE_Error
683
-     * @throws RestException
684
-     * @throws InvalidDataTypeException
685
-     * @throws InvalidInterfaceException
686
-     * @throws InvalidArgumentException
687
-     */
688
-    public function determineNestedConditionQueryParameters()
689
-    {
690
-
691
-        // so this param doesn't correspond to a field eh?
692
-        if ($this->getContext()->isWriting()) {
693
-            // always tell API clients about invalid parameters when they're creating data. Otherwise,
694
-            // they are probably going to create invalid data
695
-            throw new RestException(
696
-                'invalid_field',
697
-                sprintf(
698
-                    /* translators: 1: variable name */
699
-                    esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
700
-                    $this->getQueryParamKey()
701
-                )
702
-            );
703
-        }
704
-        // so it's not for a field, is it a logic query param key?
705
-        if ($this->isLogicQueryParam()) {
706
-            return ModelDataTranslator::prepareConditionsQueryParamsForModels(
707
-                $this->getQueryParamValue(),
708
-                $this->getContext()->getModel(),
709
-                $this->getContext()->getRequestedVersion()
710
-            );
711
-        }
712
-        if (EED_Core_Rest_Api::debugMode()) {
713
-            // only tell API clients they got it wrong if we're in debug mode
714
-            // otherwise try our best ot fulfill their request by ignoring this invalid data
715
-            throw new RestException(
716
-                'invalid_parameter',
717
-                sprintf(
718
-                    /* translators: 1: variable name */
719
-                    esc_html__(
720
-                        'You provided an invalid parameter, with key "%1$s"',
721
-                        'event_espresso'
722
-                    ),
723
-                    $this->getQueryParamKey()
724
-                ),
725
-                array(
726
-                    'status' => 400,
727
-                )
728
-            );
729
-        }
730
-        return null;
731
-    }
31
+	private $query_param_key;
32
+	private $query_param_value;
33
+	/**
34
+	 * @var RestIncomingQueryParamContext
35
+	 */
36
+	private $context;
37
+
38
+	/**
39
+	 * @var EE_Model_Field_Base|null
40
+	 */
41
+	private $field;
42
+
43
+	/**
44
+	 * @var string same as $query_param_key but has the * and anything after it removed
45
+	 */
46
+	private $query_param_key_sans_stars;
47
+
48
+	/**
49
+	 * @var string for timezone or timezone offset
50
+	 */
51
+	private $timezone;
52
+
53
+	/**
54
+	 * @var boolean if the field in $query_param_key is for a GMT field (eg `EVT_modified_gmt`)
55
+	 */
56
+	private $is_gmt_field = false;
57
+
58
+	/**
59
+	 * RestIncomingQueryParamMetadata constructor.
60
+	 * You probably want to call
61
+	 * @param string $query_param_key
62
+	 * @param string $query_param_value
63
+	 * @param RestIncomingQueryParamContext $context
64
+	 */
65
+	public function __construct($query_param_key, $query_param_value, RestIncomingQueryParamContext $context)
66
+	{
67
+		$this->query_param_key = $query_param_key;
68
+		$this->query_param_value = $query_param_value;
69
+		$this->context = $context;
70
+		$this->determineFieldAndTimezone();
71
+	}
72
+
73
+	/**
74
+	 * Gets the query parameter key. This may have been modified (see setQueryParamValue())
75
+	 * @return string
76
+	 */
77
+	public function getQueryParamKey()
78
+	{
79
+		return $this->query_param_key;
80
+	}
81
+
82
+	/**
83
+	 * Modifies the query parameter key passed in (Eg this is done when rewriting the simplified specified operator REST
84
+	 * query parameters into the legacy structure)
85
+	 * @param string|array|int|float $query_param_value
86
+	 */
87
+	private function setQueryParamValue($query_param_value)
88
+	{
89
+		$this->query_param_value = $query_param_value;
90
+	}
91
+
92
+	/**
93
+	 * Gets the original query parameter value passed in.
94
+	 * @return string
95
+	 */
96
+	public function getQueryParamValue()
97
+	{
98
+		return $this->query_param_value;
99
+	}
100
+
101
+	/**
102
+	 * Gets the context object.
103
+	 * @return RestIncomingQueryParamContext
104
+	 */
105
+	public function getContext()
106
+	{
107
+		return $this->context;
108
+	}
109
+
110
+	/**
111
+	 * Sets the query parameter key. This may be used to rewrite a key into its non-GMT alternative.
112
+	 * @param string $query_param_key
113
+	 */
114
+	private function setQueryParamKey($query_param_key)
115
+	{
116
+		$this->query_param_key = $query_param_key;
117
+	}
118
+
119
+	/**
120
+	 * Gets the field the query parameter key indicated. This may be null (in cases where the query parameter key
121
+	 * did not indicate a field, eg if it were `OR`).
122
+	 * @return EE_Model_Field_Base|null
123
+	 */
124
+	public function getField()
125
+	{
126
+		return $this->field;
127
+	}
128
+
129
+	/**
130
+	 * Gets the query parameter key (with the star and everything afterwards removed).
131
+	 * @return string
132
+	 */
133
+	public function getQueryParamKeySansStars()
134
+	{
135
+		return $this->query_param_key_sans_stars;
136
+	}
137
+
138
+	/**
139
+	 * Gets the timezone associated with this model (the site timezone, except for GMT datetime fields).
140
+	 * @return string
141
+	 */
142
+	public function getTimezone()
143
+	{
144
+		return $this->timezone;
145
+	}
146
+
147
+	/**
148
+	 * Returns whether or not this is a GMT field
149
+	 * @return boolean
150
+	 */
151
+	public function isGmtField()
152
+	{
153
+		return $this->is_gmt_field;
154
+	}
155
+
156
+	/**
157
+	 * Sets the field indicated by the query parameter key (might be null).
158
+	 * @param EE_Model_Field_Base|null $field
159
+	 */
160
+	private function setField(EE_Model_Field_Base $field = null)
161
+	{
162
+		$this->field = $field;
163
+	}
164
+
165
+	/**
166
+	 * Sets the query parameter key-with-stars-removed.
167
+	 * @param string $query_param_key_sans_stars
168
+	 */
169
+	private function setQueryParamKeySansStars($query_param_key_sans_stars)
170
+	{
171
+		$this->query_param_key_sans_stars = $query_param_key_sans_stars;
172
+	}
173
+
174
+	/**
175
+	 * Sets the timezone (this could be a timezeon offset string).
176
+	 * @param string $timezone
177
+	 */
178
+	private function setTimezone($timezone)
179
+	{
180
+		$this->timezone = $timezone;
181
+	}
182
+
183
+	/**
184
+	 * @param mixed $is_gmt_field
185
+	 */
186
+	private function setIsGmtField($is_gmt_field)
187
+	{
188
+		$this->is_gmt_field = $is_gmt_field;
189
+	}
190
+
191
+	/**
192
+	 * Determines what field, query param name, and query param name without stars, and timezone to use.
193
+	 * @since 4.9.72.p
194
+	 * @type EE_Model_Field_Base $field
195
+	 * @return void {
196
+	 * @throws EE_Error
197
+	 * @throws InvalidDataTypeException
198
+	 * @throws InvalidInterfaceException
199
+	 * @throws InvalidArgumentException
200
+	 */
201
+	private function determineFieldAndTimezone()
202
+	{
203
+		$this->setQueryParamKeySansStars(ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
204
+			$this->getQueryParamKey()
205
+		));
206
+		$this->setField(ModelDataTranslator::deduceFieldFromQueryParam(
207
+			$this->getQueryParamKeySansStars(),
208
+			$this->getContext()->getModel()
209
+		));
210
+		// double-check is it a *_gmt field?
211
+		if (
212
+			!$this->getField() instanceof EE_Model_Field_Base
213
+			&& ModelDataTranslator::isGmtDateFieldName($this->getQueryParamKeySansStars())
214
+		) {
215
+			// yep, take off '_gmt', and find the field
216
+			$this->setQueryParamKey(ModelDataTranslator::removeGmtFromFieldName($this->getQueryParamKeySansStars()));
217
+			$this->setField(ModelDataTranslator::deduceFieldFromQueryParam(
218
+				$this->getQueryParamKey(),
219
+				$this->context->getModel()
220
+			));
221
+			$this->setTimezone('UTC');
222
+			$this->setIsGmtField(true);
223
+		} elseif ($this->getField() instanceof EE_Datetime_Field) {
224
+			// so it's not a GMT field. Set the timezone on the model to the default
225
+			$this->setTimezone(EEH_DTT_Helper::get_valid_timezone_string());
226
+		} else {
227
+			// just keep using what's already set for the timezone
228
+			$this->setTimezone($this->context->getModel()->get_timezone());
229
+		}
230
+		$this->assertOnlyAdminCanReadPasswordFields();
231
+	}
232
+
233
+	/**
234
+	 * Throws an exception if a non-admin is trying to query by password.
235
+	 * @since 4.9.74.p
236
+	 * @throws RestException
237
+	 */
238
+	private function assertOnlyAdminCanReadPasswordFields()
239
+	{
240
+		if (
241
+			$this->getField() instanceof EE_Password_Field
242
+			&& ! current_user_can(EE_Restriction_Generator_Base::get_default_restrictions_cap())
243
+		) {
244
+			// only full admins can query by password. sorry bub!
245
+			throw new RestException(
246
+				'only_admins_can_query_by_password',
247
+				// @codingStandardsIgnoreStart
248
+				esc_html__('You attempted to filter by a password field without the needed privileges. Only a full admin is allowed to do that.', 'event_espresso'),
249
+				// @codingStandardsIgnoreEnd
250
+				array(
251
+					'status' => 403
252
+				)
253
+			);
254
+		}
255
+	}
256
+
257
+	/**
258
+	 * Given a ton of input, determines the value to use for the models.
259
+	 * @since 4.9.72.p
260
+	 * @return array|null
261
+	 * @throws DomainException
262
+	 * @throws EE_Error
263
+	 * @throws RestException
264
+	 * @throws DomainException
265
+	 */
266
+	public function determineConditionsQueryParameterValue()
267
+	{
268
+		if ($this->valueIsArrayDuringRead()) {
269
+			return $this->determineModelValueGivenRestInputArray();
270
+		}
271
+		return ModelDataTranslator::prepareFieldValueFromJson(
272
+			$this->getField(),
273
+			$this->getQueryParamValue(),
274
+			$this->getContext()->getRequestedVersion(),
275
+			$this->getTimezone()
276
+		);
277
+	}
278
+
279
+	/**
280
+	 * Given that the array value provided was itself an array, handles finding the correct value to pass to the model.
281
+	 * @since 4.9.72.p
282
+	 * @return array|null
283
+	 * @throws RestException
284
+	 */
285
+	private function determineModelValueGivenRestInputArray()
286
+	{
287
+		$this->transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax();
288
+		// did they specify an operator?
289
+		if ($this->valueIsLegacySpecifiedOperator()) {
290
+			$query_param_value = $this->getQueryParamValue();
291
+			$sub_array_key = $query_param_value[0];
292
+			$translated_value = array($sub_array_key);
293
+			if ($this->operatorIsNAry($sub_array_key)) {
294
+				$translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
295
+			} elseif ($this->operatorIsTernary($sub_array_key)) {
296
+				$translated_value[] = array(
297
+					$this->prepareValuesFromJson($query_param_value[1][0]),
298
+					$this->prepareValuesFromJson($query_param_value[1][1])
299
+				);
300
+			} elseif ($this->operatorIsLike($sub_array_key)) {
301
+				// we want to leave this value mostly-as-is (eg don't force it to be a float
302
+				// or a boolean or an enum value. Leave it as-is with wildcards etc)
303
+				// but do verify it at least doesn't have any serialized data
304
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
305
+				$translated_value[] = $query_param_value[1];
306
+			} elseif ($this->operatorIsUnary($sub_array_key)) {
307
+				// no arguments should have been provided, so don't look for any
308
+			} elseif ($this->operatorisBinary($sub_array_key)) {
309
+				// it's a valid operator, but none of the exceptions. Treat it normally.
310
+				$translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
311
+			} else {
312
+				// so they provided a valid operator, but wrong number of arguments
313
+				$this->throwWrongNumberOfArgsExceptionIfDebugging($sub_array_key);
314
+				$translated_value = null;
315
+			}
316
+		} else {
317
+			// so they didn't provide a valid operator
318
+			// if we aren't in debug mode, then just try our best to fulfill the user's request
319
+			$this->throwInvalidOperatorExceptionIfDebugging();
320
+			$translated_value = null;
321
+		}
322
+		return $translated_value;
323
+	}
324
+
325
+	/**
326
+	 * Returns if this request is a "read" request and the value provided was an array.
327
+	 * This will indicate is such things as `array('<', 123)` and `array('IN', array(1,2,3))` are acceptable or not.
328
+	 * @since 4.9.72.p
329
+	 * @return boolean
330
+	 */
331
+	private function valueIsArrayDuringRead()
332
+	{
333
+		return !$this->getContext()->isWriting() && is_array($this->getQueryParamValue());
334
+	}
335
+
336
+	/**
337
+	 * Returns if the value provided was an associative array (we should have already verified it's an array of some
338
+	 * sort). If the value is an associative array, it had better be in the simplified specified operator structure.
339
+	 * @since 4.9.72.p
340
+	 * @return boolean
341
+	 */
342
+	private function valueIsAssociativeArray()
343
+	{
344
+		return !EEH_Array::is_array_numerically_and_sequentially_indexed($this->getQueryParamValue());
345
+	}
346
+
347
+	/**
348
+	 * Checks if the array value is itself an array that fits into the simplified specified operator structure
349
+	 * (eg `array('!=' => 123)`).
350
+	 * @since 4.9.72.p
351
+	 * @return boolean
352
+	 */
353
+	private function valueIsSimplifiedSpecifiedOperator()
354
+	{
355
+		return count($this->getQueryParamValue()) === 1
356
+			&& array_key_exists(
357
+				key($this->getQueryParamValue()),
358
+				$this->getContext()->getModel()->valid_operators()
359
+			);
360
+	}
361
+
362
+	/**
363
+	 * Throws an exception if the sub-value is an array (eg `array('!=' => array())`). It needs to just be a string,
364
+	 * of either comma-separated-values, or a JSON array.
365
+	 * @since 4.9.72.p
366
+	 * @param $sub_array_key
367
+	 * @param $sub_array_value
368
+	 * @throws RestException
369
+	 */
370
+	private function assertSubValueIsntArray($sub_array_key, $sub_array_value)
371
+	{
372
+		if (is_array($sub_array_value) && EED_Core_Rest_Api::debugMode()) {
373
+			throw new RestException(
374
+				'csv_or_json_string_only',
375
+				sprintf(
376
+					/* translators: 1: variable name*/
377
+					esc_html__(
378
+						'The value provided for the operator "%1$s" should be comma-separated value string or a JSON array.',
379
+						'event_espresso'
380
+					),
381
+					$sub_array_key
382
+				),
383
+				array(
384
+					'status' => 400,
385
+				)
386
+			);
387
+		}
388
+	}
389
+
390
+	/**
391
+	 * Determines if the sub-array key is an operator taking 3 or more operators.
392
+	 * @since 4.9.72.p
393
+	 * @param $sub_array_key
394
+	 * @return boolean
395
+	 */
396
+	private function subArrayKeyIsNonBinaryOperator($sub_array_key)
397
+	{
398
+		return array_key_exists(
399
+			$sub_array_key,
400
+			array_merge(
401
+				$this->getContext()->getModel()->valid_in_style_operators(),
402
+				$this->getContext()->getModel()->valid_between_style_operators()
403
+			)
404
+		);
405
+	}
406
+
407
+	/**
408
+	 * Given that the $sub_array_key is a string, checks if it's an operator taking only 1 argument.
409
+	 * @since 4.9.72.p
410
+	 * @param string $sub_array_key
411
+	 * @return boolean
412
+	 */
413
+	private function subArrayKeyIsUnaryOperator($sub_array_key)
414
+	{
415
+		return array_key_exists(
416
+			$sub_array_key,
417
+			$this->getContext()->getModel()->valid_null_style_operators()
418
+		);
419
+	}
420
+
421
+	/**
422
+	 * Parses the $sub_array_value string into an array (given it could either be a comma-separated-list or a JSON
423
+	 * array). eg `"1,2,3"` or `"[1,2,3]"` into `array(1,2,3)`.
424
+	 * @since 4.9.72.p
425
+	 * @param $sub_array_value
426
+	 * @return array|mixed|object
427
+	 */
428
+	private function extractQuickStyleSpecifiedOperatorValue($sub_array_value)
429
+	{
430
+		// the value should be JSON or CSV
431
+		$values = json_decode($sub_array_value);
432
+		if (!is_array($values)) {
433
+			$values = array_filter(
434
+				array_map(
435
+					'trim',
436
+					explode(
437
+						',',
438
+						$sub_array_value
439
+					)
440
+				)
441
+			);
442
+		}
443
+		return $values;
444
+	}
445
+
446
+	/**
447
+	 * Throws an exception if the value isn't a simplified specified operator (only called when we expect that).
448
+	 * @since 4.9.72.p
449
+	 * @throws RestException
450
+	 */
451
+	private function assertSimplifiedSpecifiedOperator()
452
+	{
453
+		if (!$this->valueIsSimplifiedSpecifiedOperator() && EED_Core_Rest_Api::debugMode()) {
454
+			throw new RestException(
455
+				'numerically_indexed_array_of_values_only',
456
+				sprintf(
457
+					/* translators: 1: variable name*/
458
+					esc_html__(
459
+						'The array provided for the parameter "%1$s" should be numerically indexed.',
460
+						'event_espresso'
461
+					),
462
+					$this->getQueryParamKey()
463
+				),
464
+				array(
465
+					'status' => 400,
466
+				)
467
+			);
468
+		}
469
+	}
470
+
471
+	/**
472
+	 * If query_param_value were in the simplified specific operator structure, change it into the legacy structure.
473
+	 * @since 4.9.72.p
474
+	 * @throws RestException
475
+	 */
476
+	private function transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax()
477
+	{
478
+		if ($this->valueIsAssociativeArray()) {
479
+			$this->assertSimplifiedSpecifiedOperator();
480
+			$query_param_value = $this->getQueryParamValue();
481
+			$sub_array_value = reset($query_param_value);
482
+			$sub_array_key = key($query_param_value);
483
+			$this->assertSubValueIsntArray($sub_array_key, $sub_array_value);
484
+			// they're doing something like "&where[EVT_ID][IN]=1,2,3" or "&where[EVT_ID][>]=5"
485
+			if ($this->subArrayKeyIsNonBinaryOperator($sub_array_key)) {
486
+				$this->setQueryParamValue(array(
487
+					$sub_array_key,
488
+					$this->extractQuickStyleSpecifiedOperatorValue($sub_array_value)
489
+				));
490
+			} elseif ($this->subArrayKeyIsUnaryOperator($sub_array_key)) {
491
+				$this->setQueryParamValue(array($sub_array_key));
492
+			} else {
493
+				$this->setQueryParamValue(array($sub_array_key, $sub_array_value));
494
+			}
495
+		}
496
+	}
497
+
498
+	/**
499
+	 * Returns true is the value is an array using the legacy structure to specify the operator. Eg `array('!=',123)`.
500
+	 * @since 4.9.72.p
501
+	 * @return boolean
502
+	 */
503
+	private function valueIsLegacySpecifiedOperator()
504
+	{
505
+		$valid_operators = $this->getContext()->getModel()->valid_operators();
506
+		$query_param_value = $this->getQueryParamValue();
507
+		return isset($query_param_value[0])
508
+			&& isset($valid_operators[ $query_param_value[0] ]);
509
+	}
510
+
511
+	/**
512
+	 * Returns true if the value specified operator accepts arbitrary number of arguments, like "IN".
513
+	 * @since 4.9.72.p
514
+	 * @param $operator
515
+	 * @return boolean
516
+	 */
517
+	private function operatorIsNAry($operator)
518
+	{
519
+		$valueArray = $this->getQueryParamValue();
520
+		return array_key_exists(
521
+			$operator,
522
+			$this->getContext()->getModel()->valid_in_style_operators()
523
+		)
524
+			&& isset($valueArray[1])
525
+			&& is_array($valueArray[1])
526
+			&& !isset($valueArray[2]);
527
+	}
528
+
529
+	/**
530
+	 * Returns true if the operator accepts 3 arguments (eg "BETWEEN").
531
+	 * So we're looking for a value that looks like
532
+	 * `array('BETWEEN', array('2015-01-01T00:00:00', '2016-01-01T00:00:00'))`.
533
+	 * @since 4.9.72.p
534
+	 * @param $operator
535
+	 * @return boolean
536
+	 */
537
+	private function operatorIsTernary($operator)
538
+	{
539
+		$query_param_value = $this->getQueryParamValue();
540
+		return array_key_exists($operator, $this->getContext()->getModel()->valid_between_style_operators())
541
+			&& isset($query_param_value[1])
542
+			&& is_array($query_param_value[1])
543
+			&& isset($query_param_value[1][0], $query_param_value[1][1])
544
+			&& !isset($query_param_value[1][2])
545
+			&& !isset($query_param_value[2]);
546
+	}
547
+
548
+	/**
549
+	 * Returns true if the operator is a similar to LIKE, indicating the value may have wildcards we should leave alone.
550
+	 * @since 4.9.72.p
551
+	 * @param $operator
552
+	 * @return boolean
553
+	 */
554
+	private function operatorIsLike($operator)
555
+	{
556
+		$query_param_value = $this->getQueryParamValue();
557
+		return array_key_exists($operator, $this->getContext()->getModel()->valid_like_style_operators())
558
+			&& isset($query_param_value[1])
559
+			&& !isset($query_param_value[2]);
560
+	}
561
+
562
+	/**
563
+	 * Returns true if the operator only takes one argument (eg it's like `IS NULL`).
564
+	 * @since 4.9.72.p
565
+	 * @param $operator
566
+	 * @return boolean
567
+	 */
568
+	private function operatorIsUnary($operator)
569
+	{
570
+		$query_param_value = $this->getQueryParamValue();
571
+		return array_key_exists($operator, $this->getContext()->getModel()->valid_null_style_operators())
572
+			&& !isset($query_param_value[1]);
573
+	}
574
+
575
+	/**
576
+	 * Returns true if the operator specified is a binary opeator (eg `=`, `!=`)
577
+	 * @since 4.9.72.p
578
+	 * @param $operator
579
+	 * @return boolean
580
+	 */
581
+	private function operatorisBinary($operator)
582
+	{
583
+		$query_param_value = $this->getQueryParamValue();
584
+		$model = $this->getContext()->getModel();
585
+		return isset($query_param_value[1])
586
+			&& !isset($query_param_value[2])
587
+			&& !array_key_exists(
588
+				$operator,
589
+				array_merge(
590
+					$model->valid_in_style_operators(),
591
+					$model->valid_null_style_operators(),
592
+					$model->valid_like_style_operators(),
593
+					$model->valid_between_style_operators()
594
+				)
595
+			);
596
+	}
597
+
598
+	/**
599
+	 * If we're debugging, throws an exception saying that the wrong number of arguments was provided.
600
+	 * @since 4.9.72.p
601
+	 * @param $operator
602
+	 * @throws RestException
603
+	 */
604
+	private function throwWrongNumberOfArgsExceptionIfDebugging($operator)
605
+	{
606
+		if (EED_Core_Rest_Api::debugMode()) {
607
+			throw new RestException(
608
+				'wrong_number_of_arguments',
609
+				sprintf(
610
+					esc_html__(
611
+						'The operator you provided, "%1$s" had the wrong number of arguments',
612
+						'event_espresso'
613
+					),
614
+					$operator
615
+				),
616
+				array(
617
+					'status' => 400,
618
+				)
619
+			);
620
+		}
621
+	}
622
+
623
+	/**
624
+	 * Wrapper for ModelDataTranslator::prepareFieldValuesFromJson(), just a tad more DRY.
625
+	 * @since 4.9.72.p
626
+	 * @param $value
627
+	 * @return mixed
628
+	 * @throws RestException
629
+	 */
630
+	private function prepareValuesFromJson($value)
631
+	{
632
+		return ModelDataTranslator::prepareFieldValuesFromJson(
633
+			$this->getField(),
634
+			$value,
635
+			$this->getContext()->getRequestedVersion(),
636
+			$this->getTimezone()
637
+		);
638
+	}
639
+
640
+	/**
641
+	 * Throws an exception if an invalid operator was specified and we're debugging.
642
+	 * @since 4.9.72.p
643
+	 * @throws RestException
644
+	 */
645
+	private function throwInvalidOperatorExceptionIfDebugging()
646
+	{
647
+		// so they didn't provide a valid operator
648
+		if (EED_Core_Rest_Api::debugMode()) {
649
+			throw new RestException(
650
+				'invalid_operator',
651
+				sprintf(
652
+					esc_html__(
653
+						'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
654
+						'event_espresso'
655
+					),
656
+					$this->getQueryParamKey(),
657
+					$this->getQueryParamValue()
658
+				),
659
+				array(
660
+					'status' => 400,
661
+				)
662
+			);
663
+		}
664
+	}
665
+
666
+	/**
667
+	 * Returns true if the query_param_key was a logic query parameter, eg `OR`, `AND`, `NOT`, `OR*`, etc.
668
+	 * @since 4.9.72.p
669
+	 * @return boolean
670
+	 */
671
+	private function isLogicQueryParam()
672
+	{
673
+		return in_array($this->getQueryParamKeySansStars(), $this->getContext()->getModel()->logic_query_param_keys());
674
+	}
675
+
676
+
677
+	/**
678
+	 * If the query param isn't for a field, it must be a nested query parameter which requires different logic.
679
+	 * @since 4.9.72.p
680
+	 * @return array
681
+	 * @throws DomainException
682
+	 * @throws EE_Error
683
+	 * @throws RestException
684
+	 * @throws InvalidDataTypeException
685
+	 * @throws InvalidInterfaceException
686
+	 * @throws InvalidArgumentException
687
+	 */
688
+	public function determineNestedConditionQueryParameters()
689
+	{
690
+
691
+		// so this param doesn't correspond to a field eh?
692
+		if ($this->getContext()->isWriting()) {
693
+			// always tell API clients about invalid parameters when they're creating data. Otherwise,
694
+			// they are probably going to create invalid data
695
+			throw new RestException(
696
+				'invalid_field',
697
+				sprintf(
698
+					/* translators: 1: variable name */
699
+					esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
700
+					$this->getQueryParamKey()
701
+				)
702
+			);
703
+		}
704
+		// so it's not for a field, is it a logic query param key?
705
+		if ($this->isLogicQueryParam()) {
706
+			return ModelDataTranslator::prepareConditionsQueryParamsForModels(
707
+				$this->getQueryParamValue(),
708
+				$this->getContext()->getModel(),
709
+				$this->getContext()->getRequestedVersion()
710
+			);
711
+		}
712
+		if (EED_Core_Rest_Api::debugMode()) {
713
+			// only tell API clients they got it wrong if we're in debug mode
714
+			// otherwise try our best ot fulfill their request by ignoring this invalid data
715
+			throw new RestException(
716
+				'invalid_parameter',
717
+				sprintf(
718
+					/* translators: 1: variable name */
719
+					esc_html__(
720
+						'You provided an invalid parameter, with key "%1$s"',
721
+						'event_espresso'
722
+					),
723
+					$this->getQueryParamKey()
724
+				),
725
+				array(
726
+					'status' => 400,
727
+				)
728
+			);
729
+		}
730
+		return null;
731
+	}
732 732
 }
733 733
 // End of file RestQueryParamMetadata.php
734 734
 // Location: EventEspresso\core\libraries\rest_api/RestQueryParamMetadata.php
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
         ));
210 210
         // double-check is it a *_gmt field?
211 211
         if (
212
-            !$this->getField() instanceof EE_Model_Field_Base
212
+            ! $this->getField() instanceof EE_Model_Field_Base
213 213
             && ModelDataTranslator::isGmtDateFieldName($this->getQueryParamKeySansStars())
214 214
         ) {
215 215
             // yep, take off '_gmt', and find the field
@@ -330,7 +330,7 @@  discard block
 block discarded – undo
330 330
      */
331 331
     private function valueIsArrayDuringRead()
332 332
     {
333
-        return !$this->getContext()->isWriting() && is_array($this->getQueryParamValue());
333
+        return ! $this->getContext()->isWriting() && is_array($this->getQueryParamValue());
334 334
     }
335 335
 
336 336
     /**
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
      */
342 342
     private function valueIsAssociativeArray()
343 343
     {
344
-        return !EEH_Array::is_array_numerically_and_sequentially_indexed($this->getQueryParamValue());
344
+        return ! EEH_Array::is_array_numerically_and_sequentially_indexed($this->getQueryParamValue());
345 345
     }
346 346
 
347 347
     /**
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
     {
430 430
         // the value should be JSON or CSV
431 431
         $values = json_decode($sub_array_value);
432
-        if (!is_array($values)) {
432
+        if ( ! is_array($values)) {
433 433
             $values = array_filter(
434 434
                 array_map(
435 435
                     'trim',
@@ -450,7 +450,7 @@  discard block
 block discarded – undo
450 450
      */
451 451
     private function assertSimplifiedSpecifiedOperator()
452 452
     {
453
-        if (!$this->valueIsSimplifiedSpecifiedOperator() && EED_Core_Rest_Api::debugMode()) {
453
+        if ( ! $this->valueIsSimplifiedSpecifiedOperator() && EED_Core_Rest_Api::debugMode()) {
454 454
             throw new RestException(
455 455
                 'numerically_indexed_array_of_values_only',
456 456
                 sprintf(
@@ -505,7 +505,7 @@  discard block
 block discarded – undo
505 505
         $valid_operators = $this->getContext()->getModel()->valid_operators();
506 506
         $query_param_value = $this->getQueryParamValue();
507 507
         return isset($query_param_value[0])
508
-            && isset($valid_operators[ $query_param_value[0] ]);
508
+            && isset($valid_operators[$query_param_value[0]]);
509 509
     }
510 510
 
511 511
     /**
@@ -523,7 +523,7 @@  discard block
 block discarded – undo
523 523
         )
524 524
             && isset($valueArray[1])
525 525
             && is_array($valueArray[1])
526
-            && !isset($valueArray[2]);
526
+            && ! isset($valueArray[2]);
527 527
     }
528 528
 
529 529
     /**
@@ -541,8 +541,8 @@  discard block
 block discarded – undo
541 541
             && isset($query_param_value[1])
542 542
             && is_array($query_param_value[1])
543 543
             && isset($query_param_value[1][0], $query_param_value[1][1])
544
-            && !isset($query_param_value[1][2])
545
-            && !isset($query_param_value[2]);
544
+            && ! isset($query_param_value[1][2])
545
+            && ! isset($query_param_value[2]);
546 546
     }
547 547
 
548 548
     /**
@@ -556,7 +556,7 @@  discard block
 block discarded – undo
556 556
         $query_param_value = $this->getQueryParamValue();
557 557
         return array_key_exists($operator, $this->getContext()->getModel()->valid_like_style_operators())
558 558
             && isset($query_param_value[1])
559
-            && !isset($query_param_value[2]);
559
+            && ! isset($query_param_value[2]);
560 560
     }
561 561
 
562 562
     /**
@@ -569,7 +569,7 @@  discard block
 block discarded – undo
569 569
     {
570 570
         $query_param_value = $this->getQueryParamValue();
571 571
         return array_key_exists($operator, $this->getContext()->getModel()->valid_null_style_operators())
572
-            && !isset($query_param_value[1]);
572
+            && ! isset($query_param_value[1]);
573 573
     }
574 574
 
575 575
     /**
@@ -583,8 +583,8 @@  discard block
 block discarded – undo
583 583
         $query_param_value = $this->getQueryParamValue();
584 584
         $model = $this->getContext()->getModel();
585 585
         return isset($query_param_value[1])
586
-            && !isset($query_param_value[2])
587
-            && !array_key_exists(
586
+            && ! isset($query_param_value[2])
587
+            && ! array_key_exists(
588 588
                 $operator,
589 589
                 array_merge(
590 590
                     $model->valid_in_style_operators(),
Please login to merge, or discard this patch.
core/libraries/rest_api/changes/ChangesIn40834.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -12,39 +12,39 @@
 block discarded – undo
12 12
 class ChangesIn40834 extends ChangesInBase
13 13
 {
14 14
 
15
-    /**
16
-     * Adds hooks so requests to 4.8.29 don't have the checkin endpoints
17
-     */
18
-    public function setHooks()
19
-    {
20
-        // set a hook to remove the checkout/checkout endpoints if the request
21
-        // is for lower than 4.8.33
22
-        add_filter(
23
-            'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_response_headers',
24
-            array($this, 'removeResponseHeaders'),
25
-            10,
26
-            3
27
-        );
28
-    }
15
+	/**
16
+	 * Adds hooks so requests to 4.8.29 don't have the checkin endpoints
17
+	 */
18
+	public function setHooks()
19
+	{
20
+		// set a hook to remove the checkout/checkout endpoints if the request
21
+		// is for lower than 4.8.33
22
+		add_filter(
23
+			'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_response_headers',
24
+			array($this, 'removeResponseHeaders'),
25
+			10,
26
+			3
27
+		);
28
+	}
29 29
 
30 30
 
31
-    /**
32
-     * Removes the checkin and checkout endpoints from the index for requests
33
-     * to api versions lowers than 4.8.33
34
-     *
35
-     * @param array  $response_headers
36
-     * @param Base   $controller
37
-     * @param string $requested_version
38
-     * @return array like $routes_on_this_version
39
-     */
40
-    public function removeResponseHeaders($response_headers, $controller, $requested_version)
41
-    {
42
-        if (
43
-            $controller instanceof Base
44
-            && $this->appliesToVersion($requested_version)
45
-        ) {
46
-            return array();
47
-        }
48
-        return $response_headers;
49
-    }
31
+	/**
32
+	 * Removes the checkin and checkout endpoints from the index for requests
33
+	 * to api versions lowers than 4.8.33
34
+	 *
35
+	 * @param array  $response_headers
36
+	 * @param Base   $controller
37
+	 * @param string $requested_version
38
+	 * @return array like $routes_on_this_version
39
+	 */
40
+	public function removeResponseHeaders($response_headers, $controller, $requested_version)
41
+	{
42
+		if (
43
+			$controller instanceof Base
44
+			&& $this->appliesToVersion($requested_version)
45
+		) {
46
+			return array();
47
+		}
48
+		return $response_headers;
49
+	}
50 50
 }
Please login to merge, or discard this patch.
core/libraries/rest_api/ModelVersionInfo.php 2 patches
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -114,10 +114,10 @@  discard block
 block discarded – undo
114 114
         foreach ($this->resource_changes as $version => $model_classnames) {
115 115
             foreach ($model_classnames as $model_classname => $extra_fields) {
116 116
                 foreach ($extra_fields as $fieldname => $field_data) {
117
-                    $this->resource_changes[ $model_classname ][ $fieldname ]['name'] = $fieldname;
117
+                    $this->resource_changes[$model_classname][$fieldname]['name'] = $fieldname;
118 118
                     foreach ($defaults as $attribute => $default_value) {
119
-                        if (! isset($this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ])) {
120
-                            $this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ] = $default_value;
119
+                        if ( ! isset($this->resource_changes[$model_classname][$fieldname][$attribute])) {
120
+                            $this->resource_changes[$model_classname][$fieldname][$attribute] = $default_value;
121 121
                         }
122 122
                     }
123 123
                 }
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
             $model_changes = array();
140 140
             foreach ($this->modelChanges() as $version => $models_changed_in_version) {
141 141
                 if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
142
-                    $model_changes[ $version ] = $models_changed_in_version;
142
+                    $model_changes[$version] = $models_changed_in_version;
143 143
                 }
144 144
             }
145 145
             $this->cached_model_changes_between_requested_version_and_current = $model_changes;
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
             $resource_changes = array();
162 162
             foreach ($this->resourceChanges() as $version => $model_classnames) {
163 163
                 if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
164
-                    $resource_changes[ $version ] = $model_classnames;
164
+                    $resource_changes[$version] = $model_classnames;
165 165
                 }
166 166
             }
167 167
             $this->cached_resource_changes_between_requested_version_and_current = $resource_changes;
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
             foreach ($this->modelChangesBetweenRequestedVersionAndCurrent() as $version => $models_changed) {
213 213
                 foreach ($models_changed as $model_name => $new_indicator_or_fields_added) {
214 214
                     if ($new_indicator_or_fields_added === ModelVersionInfo::MODEL_ADDED) {
215
-                        unset($all_models_in_current_version[ $model_name ]);
215
+                        unset($all_models_in_current_version[$model_name]);
216 216
                     }
217 217
                 }
218 218
             }
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
     public function isModelNameInThisVersion($model_name)
238 238
     {
239 239
         $model_names = $this->modelsForRequestedVersion();
240
-        if (isset($model_names[ $model_name ])) {
240
+        if (isset($model_names[$model_name])) {
241 241
             return true;
242 242
         } else {
243 243
             return false;
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
      */
281 281
     public function fieldsOnModelInThisVersion($model)
282 282
     {
283
-        if (! isset($this->cached_fields_on_models[ $model->get_this_model_name() ])) {
283
+        if ( ! isset($this->cached_fields_on_models[$model->get_this_model_name()])) {
284 284
             // get all model changes between the requested version and current core version
285 285
             $changes = $this->modelChangesBetweenRequestedVersionAndCurrent();
286 286
             // fetch all fields currently on this model
@@ -288,12 +288,12 @@  discard block
 block discarded – undo
288 288
             // remove all fields that have been added since
289 289
             foreach ($changes as $version => $changes_in_version) {
290 290
                 if (
291
-                    isset($changes_in_version[ $model->get_this_model_name() ])
292
-                    && $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
291
+                    isset($changes_in_version[$model->get_this_model_name()])
292
+                    && $changes_in_version[$model->get_this_model_name()] !== ModelVersionInfo::MODEL_ADDED
293 293
                 ) {
294 294
                     $current_fields = array_diff_key(
295 295
                         $current_fields,
296
-                        array_flip($changes_in_version[ $model->get_this_model_name() ])
296
+                        array_flip($changes_in_version[$model->get_this_model_name()])
297 297
                     );
298 298
                 }
299 299
             }
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
         $relations = array();
449 449
         foreach ($model->relation_settings() as $relation_name => $relation_obj) {
450 450
             if ($this->isModelNameInThisVersion($relation_name)) {
451
-                $relations[ $relation_name ] = $relation_obj;
451
+                $relations[$relation_name] = $relation_obj;
452 452
             }
453 453
         }
454 454
         // filter the results, but use the old filter name
Please login to merge, or discard this patch.
Indentation   +437 added lines, -437 removed lines patch added patch discarded remove patch
@@ -24,441 +24,441 @@
 block discarded – undo
24 24
  */
25 25
 class ModelVersionInfo
26 26
 {
27
-    /**
28
-     * Constant used in the $_model_changes array to indicate that a model
29
-     * was completely new in this version
30
-     */
31
-    const MODEL_ADDED = 'model_added_in_this_version';
32
-
33
-    /**
34
-     * Top-level keys are versions (major and minor version numbers, eg "4.6")
35
-     * next-level keys are model names (eg "Event") that underwent some change in that version
36
-     * and the value is either Model_Version_Info::model_added (indicating the model is completely NEW in this version),
37
-     * or it's an array where the values are model field names,
38
-     * or API resource properties (ie, non-model fields that appear in REST API results)
39
-     * If a version is missing then we don't know anything about what changes it introduced from the previous version
40
-     *
41
-     * @var array
42
-     */
43
-    protected $model_changes = array();
44
-
45
-    /**
46
-     * top-level keys are version numbers,
47
-     * next-level keys are model CLASSNAMES (even parent classnames),
48
-     * and next-level keys are extra resource properties to attach to those models' resources,
49
-     * and next-level key-value pairs, where the keys are:
50
-     * 'raw', 'type', 'nullable', 'table_alias', 'table_column',  'always_available'
51
-     *
52
-     * @var array
53
-     */
54
-    protected $resource_changes = array();
55
-
56
-    /**
57
-     * @var string indicating what version of the API was requested
58
-     * (eg although core might be at version 4.8.11, they may have sent a request
59
-     * for 4.6)
60
-     */
61
-    protected $requested_version = null;
62
-
63
-    /**
64
-     * Keys are model names, values are their classnames.
65
-     * We cache this so we only need to calculate this once per request
66
-     *
67
-     * @var array
68
-     */
69
-    protected $cached_models_for_requested_version = null;
70
-
71
-    /**
72
-     * @var array
73
-     */
74
-    protected $cached_model_changes_between_requested_version_and_current = null;
75
-
76
-    /**
77
-     * @var array
78
-     */
79
-    protected $cached_resource_changes_between_requested_version_and_current = null;
80
-
81
-    /**
82
-     * 2d array where top-level keys are model names, 2nd-level keys are field names
83
-     * and values are the actual field objects
84
-     *
85
-     * @var array
86
-     */
87
-    protected $cached_fields_on_models = array();
88
-
89
-
90
-    /**
91
-     * Model_Version_Info constructor.
92
-     *
93
-     * @param string $requested_version
94
-     */
95
-    public function __construct($requested_version)
96
-    {
97
-        $this->requested_version = (string) $requested_version;
98
-        $this->model_changes = array(
99
-            '4.8.29' => array(
100
-                // first version where the REST API is in EE core, so no need
101
-                // to specify how its different from the previous
102
-            ),
103
-        );
104
-        // setup data for "extra" fields added onto resources which don't actually exist on models
105
-        $this->resource_changes = apply_filters(
106
-            'FHEE__Model_Version_Info___construct__extra_resource_properties_for_models',
107
-            array()
108
-        );
109
-        $defaults = array(
110
-            'raw'              => false,
111
-            'type'             => 'N/A',
112
-            'nullable'         => true,
113
-            'table_alias'      => 'N/A',
114
-            'table_column'     => 'N/A',
115
-            'always_available' => true,
116
-        );
117
-        foreach ($this->resource_changes as $version => $model_classnames) {
118
-            foreach ($model_classnames as $model_classname => $extra_fields) {
119
-                foreach ($extra_fields as $fieldname => $field_data) {
120
-                    $this->resource_changes[ $model_classname ][ $fieldname ]['name'] = $fieldname;
121
-                    foreach ($defaults as $attribute => $default_value) {
122
-                        if (! isset($this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ])) {
123
-                            $this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ] = $default_value;
124
-                        }
125
-                    }
126
-                }
127
-            }
128
-        }
129
-    }
130
-
131
-
132
-    /**
133
-     * Returns a slice of Model_Version_Info::model_changes()'s array
134
-     * indicating exactly what changes happened between the current core version,
135
-     * and the version requested
136
-     *
137
-     * @return array
138
-     */
139
-    public function modelChangesBetweenRequestedVersionAndCurrent()
140
-    {
141
-        if ($this->cached_model_changes_between_requested_version_and_current === null) {
142
-            $model_changes = array();
143
-            foreach ($this->modelChanges() as $version => $models_changed_in_version) {
144
-                if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
145
-                    $model_changes[ $version ] = $models_changed_in_version;
146
-                }
147
-            }
148
-            $this->cached_model_changes_between_requested_version_and_current = $model_changes;
149
-        }
150
-        return $this->cached_model_changes_between_requested_version_and_current;
151
-    }
152
-
153
-
154
-    /**
155
-     * Returns a slice of Model_Version_Info::model_changes()'s array
156
-     * indicating exactly what changes happened between the current core version,
157
-     * and the version requested
158
-     *
159
-     * @return array
160
-     */
161
-    public function resourceChangesBetweenRequestedVersionAndCurrent()
162
-    {
163
-        if ($this->cached_resource_changes_between_requested_version_and_current === null) {
164
-            $resource_changes = array();
165
-            foreach ($this->resourceChanges() as $version => $model_classnames) {
166
-                if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
167
-                    $resource_changes[ $version ] = $model_classnames;
168
-                }
169
-            }
170
-            $this->cached_resource_changes_between_requested_version_and_current = $resource_changes;
171
-        }
172
-        return $this->cached_resource_changes_between_requested_version_and_current;
173
-    }
174
-
175
-
176
-    /**
177
-     * If a request was sent to 'wp-json/ee/v4.7/events' this would be '4.7'
178
-     *
179
-     * @return string like '4.6'
180
-     */
181
-    public function requestedVersion()
182
-    {
183
-        return $this->requested_version;
184
-    }
185
-
186
-
187
-    /**
188
-     * Returns an array describing how the models have changed in each version of core
189
-     * that supports the API (starting at 4.6)
190
-     * Top-level keys are versions (major and minor version numbers, eg "4.6")
191
-     * next-level keys are model names (eg "Event") that underwent some change in that version
192
-     * and the value is either NULL (indicating the model is completely NEW in this version),
193
-     * or it's an array where fields are value names.
194
-     * If a version is missing then we don't know anything about what changes it introduced from the previous version
195
-     *
196
-     * @return array
197
-     */
198
-    public function modelChanges()
199
-    {
200
-        return $this->model_changes;
201
-    }
202
-
203
-
204
-    /**
205
-     * Takes into account the requested version, and the current version, and
206
-     * what changed between the two, and tries to return.
207
-     * Analogous to EE_Registry::instance()->non_abstract_db_models
208
-     *
209
-     * @return array keys are model names, values are their classname
210
-     */
211
-    public function modelsForRequestedVersion()
212
-    {
213
-        if ($this->cached_models_for_requested_version === null) {
214
-            $all_models_in_current_version = EE_Registry::instance()->non_abstract_db_models;
215
-            foreach ($this->modelChangesBetweenRequestedVersionAndCurrent() as $version => $models_changed) {
216
-                foreach ($models_changed as $model_name => $new_indicator_or_fields_added) {
217
-                    if ($new_indicator_or_fields_added === ModelVersionInfo::MODEL_ADDED) {
218
-                        unset($all_models_in_current_version[ $model_name ]);
219
-                    }
220
-                }
221
-            }
222
-            $this->cached_models_for_requested_version = apply_filters(
223
-                'FHEE__EventEspresso_core_libraries_rest_api__models_for_requested_version',
224
-                $all_models_in_current_version,
225
-                $this
226
-            );
227
-        }
228
-        return $this->cached_models_for_requested_version;
229
-    }
230
-
231
-
232
-    /**
233
-     * Determines if this is a valid model name in the requested version.
234
-     * Similar to EE_Registry::instance()->is_model_name(), but takes the requested
235
-     * version's models into account
236
-     *
237
-     * @param string $model_name eg 'Event'
238
-     * @return boolean
239
-     */
240
-    public function isModelNameInThisVersion($model_name)
241
-    {
242
-        $model_names = $this->modelsForRequestedVersion();
243
-        if (isset($model_names[ $model_name ])) {
244
-            return true;
245
-        } else {
246
-            return false;
247
-        }
248
-    }
249
-
250
-
251
-    /**
252
-     * Wrapper for EE_Registry::instance()->load_model(), but takes the requested
253
-     * version's models into account
254
-     *
255
-     * @param string $model_name
256
-     * @return EEM_Base
257
-     * @throws EE_Error
258
-     */
259
-    public function loadModel($model_name)
260
-    {
261
-        if ($this->isModelNameInThisVersion($model_name)) {
262
-            return EE_Registry::instance()->load_model($model_name);
263
-        } else {
264
-            throw new EE_Error(
265
-                sprintf(
266
-                    esc_html__(
267
-                        'Cannot load model "%1$s" because it does not exist in version %2$s of Event Espresso',
268
-                        'event_espresso'
269
-                    ),
270
-                    $model_name,
271
-                    $this->requestedVersion()
272
-                )
273
-            );
274
-        }
275
-    }
276
-
277
-
278
-    /**
279
-     * Gets all the fields that should exist on this model right now
280
-     *
281
-     * @param EEM_Base $model
282
-     * @return array|EE_Model_Field_Base[]
283
-     */
284
-    public function fieldsOnModelInThisVersion($model)
285
-    {
286
-        if (! isset($this->cached_fields_on_models[ $model->get_this_model_name() ])) {
287
-            // get all model changes between the requested version and current core version
288
-            $changes = $this->modelChangesBetweenRequestedVersionAndCurrent();
289
-            // fetch all fields currently on this model
290
-            $current_fields = $model->field_settings();
291
-            // remove all fields that have been added since
292
-            foreach ($changes as $version => $changes_in_version) {
293
-                if (
294
-                    isset($changes_in_version[ $model->get_this_model_name() ])
295
-                    && $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
296
-                ) {
297
-                    $current_fields = array_diff_key(
298
-                        $current_fields,
299
-                        array_flip($changes_in_version[ $model->get_this_model_name() ])
300
-                    );
301
-                }
302
-            }
303
-            $this->cached_fields_on_models = $current_fields;
304
-        }
305
-        return $this->cached_fields_on_models;
306
-    }
307
-
308
-
309
-    /**
310
-     * Determines if $object is of one of the classes of $classes. Similar to
311
-     * in_array(), except this checks if $object is a subclass of the classnames provided
312
-     * in $classnames
313
-     *
314
-     * @param object $object
315
-     * @param array  $classnames
316
-     * @return boolean
317
-     */
318
-    public function isSubclassOfOne($object, $classnames)
319
-    {
320
-        foreach ($classnames as $classname) {
321
-            if (is_a($object, $classname)) {
322
-                return true;
323
-            }
324
-        }
325
-        return false;
326
-    }
327
-
328
-
329
-    /**
330
-     * Returns the list of model field classes that that the API basically ignores
331
-     *
332
-     * @return array
333
-     */
334
-    public function fieldsIgnored()
335
-    {
336
-        return apply_filters(
337
-            'FHEE__Controller_Model_Read_fields_ignored',
338
-            array()
339
-        );
340
-    }
341
-
342
-
343
-    /**
344
-     * If this field one that should be ignored by the API?
345
-     *
346
-     * @param EE_Model_Field_Base
347
-     * @return boolean
348
-     */
349
-    public function fieldIsIgnored($field_obj)
350
-    {
351
-        return $this->isSubclassOfOne($field_obj, $this->fieldsIgnored());
352
-    }
353
-
354
-
355
-    /**
356
-     * Returns the list of model field classes that have a "raw" and non-raw formats.
357
-     * Normally the "raw" versions are only accessible to those who can edit them.
358
-     *
359
-     * @return array an array of EE_Model_Field_Base child classnames
360
-     */
361
-    public function fieldsThatHaveRenderedFormat()
362
-    {
363
-        return apply_filters(
364
-            'FHEE__Controller_Model_Read__fields_raw',
365
-            array('EE_Post_Content_Field', 'EE_Full_HTML_Field')
366
-        );
367
-    }
368
-
369
-
370
-    /**
371
-     * If this field one that has a raw format
372
-     *
373
-     * @param EE_Model_Field_Base
374
-     * @return boolean
375
-     */
376
-    public function fieldHasRenderedFormat($field_obj)
377
-    {
378
-        return $this->isSubclassOfOne($field_obj, $this->fieldsThatHaveRenderedFormat());
379
-    }
380
-
381
-
382
-    /**
383
-     * Returns the list of model field classes that have a "_pretty" and non-pretty versions.
384
-     * The pretty version of the field is NOT query-able or editable, but requires no extra permissions
385
-     * to view
386
-     *
387
-     * @return array an array of EE_Model_Field_Base child classnames
388
-     */
389
-    public function fieldsThatHavePrettyFormat()
390
-    {
391
-        return apply_filters(
392
-            'FHEE__Controller_Model_Read__fields_pretty',
393
-            array('EE_Enum_Integer_Field', 'EE_Enum_Text_Field', 'EE_Money_Field')
394
-        );
395
-    }
396
-
397
-
398
-    /**
399
-     * If this field one that has a pretty equivalent
400
-     *
401
-     * @param EE_Model_Field_Base
402
-     * @return boolean
403
-     */
404
-    public function fieldHasPrettyFormat($field_obj)
405
-    {
406
-        return $this->isSubclassOfOne($field_obj, $this->fieldsThatHavePrettyFormat());
407
-    }
408
-
409
-
410
-    /**
411
-     * Returns an array describing what extra API resource properties have been added through the versions
412
-     *
413
-     * @return array @see $this->_extra_resource_properties_for_models
414
-     */
415
-    public function resourceChanges()
416
-    {
417
-        return $this->resource_changes;
418
-    }
419
-
420
-
421
-    /**
422
-     * Returns an array where keys are extra resource properties in this version of the API,
423
-     * and values are key-value pairs describing the new properties. @see Model_Version::_resource_changes
424
-     *
425
-     * @param EEM_Base $model
426
-     * @return array
427
-     */
428
-    public function extraResourcePropertiesForModel($model)
429
-    {
430
-        $extra_properties = array();
431
-        foreach ($this->resourceChangesBetweenRequestedVersionAndCurrent() as $version => $model_classnames) {
432
-            foreach ($model_classnames as $model_classname => $properties_added_in_this_version) {
433
-                if (is_subclass_of($model, $model_classname)) {
434
-                    $extra_properties = array_merge($extra_properties, $properties_added_in_this_version);
435
-                }
436
-            }
437
-        }
438
-        return $extra_properties;
439
-    }
440
-
441
-
442
-    /**
443
-     * Gets all the related models for the specified model. It's good to use this
444
-     * in case this model didn't exist for this version or something
445
-     *
446
-     * @param EEM_Base $model
447
-     * @return EE_Model_Relation_Base[]
448
-     */
449
-    public function relationSettings($model)
450
-    {
451
-        $relations = array();
452
-        foreach ($model->relation_settings() as $relation_name => $relation_obj) {
453
-            if ($this->isModelNameInThisVersion($relation_name)) {
454
-                $relations[ $relation_name ] = $relation_obj;
455
-            }
456
-        }
457
-        // filter the results, but use the old filter name
458
-        return apply_filters(
459
-            'FHEE__Read__create_entity_from_wpdb_result__related_models_to_include',
460
-            $relations,
461
-            $model
462
-        );
463
-    }
27
+	/**
28
+	 * Constant used in the $_model_changes array to indicate that a model
29
+	 * was completely new in this version
30
+	 */
31
+	const MODEL_ADDED = 'model_added_in_this_version';
32
+
33
+	/**
34
+	 * Top-level keys are versions (major and minor version numbers, eg "4.6")
35
+	 * next-level keys are model names (eg "Event") that underwent some change in that version
36
+	 * and the value is either Model_Version_Info::model_added (indicating the model is completely NEW in this version),
37
+	 * or it's an array where the values are model field names,
38
+	 * or API resource properties (ie, non-model fields that appear in REST API results)
39
+	 * If a version is missing then we don't know anything about what changes it introduced from the previous version
40
+	 *
41
+	 * @var array
42
+	 */
43
+	protected $model_changes = array();
44
+
45
+	/**
46
+	 * top-level keys are version numbers,
47
+	 * next-level keys are model CLASSNAMES (even parent classnames),
48
+	 * and next-level keys are extra resource properties to attach to those models' resources,
49
+	 * and next-level key-value pairs, where the keys are:
50
+	 * 'raw', 'type', 'nullable', 'table_alias', 'table_column',  'always_available'
51
+	 *
52
+	 * @var array
53
+	 */
54
+	protected $resource_changes = array();
55
+
56
+	/**
57
+	 * @var string indicating what version of the API was requested
58
+	 * (eg although core might be at version 4.8.11, they may have sent a request
59
+	 * for 4.6)
60
+	 */
61
+	protected $requested_version = null;
62
+
63
+	/**
64
+	 * Keys are model names, values are their classnames.
65
+	 * We cache this so we only need to calculate this once per request
66
+	 *
67
+	 * @var array
68
+	 */
69
+	protected $cached_models_for_requested_version = null;
70
+
71
+	/**
72
+	 * @var array
73
+	 */
74
+	protected $cached_model_changes_between_requested_version_and_current = null;
75
+
76
+	/**
77
+	 * @var array
78
+	 */
79
+	protected $cached_resource_changes_between_requested_version_and_current = null;
80
+
81
+	/**
82
+	 * 2d array where top-level keys are model names, 2nd-level keys are field names
83
+	 * and values are the actual field objects
84
+	 *
85
+	 * @var array
86
+	 */
87
+	protected $cached_fields_on_models = array();
88
+
89
+
90
+	/**
91
+	 * Model_Version_Info constructor.
92
+	 *
93
+	 * @param string $requested_version
94
+	 */
95
+	public function __construct($requested_version)
96
+	{
97
+		$this->requested_version = (string) $requested_version;
98
+		$this->model_changes = array(
99
+			'4.8.29' => array(
100
+				// first version where the REST API is in EE core, so no need
101
+				// to specify how its different from the previous
102
+			),
103
+		);
104
+		// setup data for "extra" fields added onto resources which don't actually exist on models
105
+		$this->resource_changes = apply_filters(
106
+			'FHEE__Model_Version_Info___construct__extra_resource_properties_for_models',
107
+			array()
108
+		);
109
+		$defaults = array(
110
+			'raw'              => false,
111
+			'type'             => 'N/A',
112
+			'nullable'         => true,
113
+			'table_alias'      => 'N/A',
114
+			'table_column'     => 'N/A',
115
+			'always_available' => true,
116
+		);
117
+		foreach ($this->resource_changes as $version => $model_classnames) {
118
+			foreach ($model_classnames as $model_classname => $extra_fields) {
119
+				foreach ($extra_fields as $fieldname => $field_data) {
120
+					$this->resource_changes[ $model_classname ][ $fieldname ]['name'] = $fieldname;
121
+					foreach ($defaults as $attribute => $default_value) {
122
+						if (! isset($this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ])) {
123
+							$this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ] = $default_value;
124
+						}
125
+					}
126
+				}
127
+			}
128
+		}
129
+	}
130
+
131
+
132
+	/**
133
+	 * Returns a slice of Model_Version_Info::model_changes()'s array
134
+	 * indicating exactly what changes happened between the current core version,
135
+	 * and the version requested
136
+	 *
137
+	 * @return array
138
+	 */
139
+	public function modelChangesBetweenRequestedVersionAndCurrent()
140
+	{
141
+		if ($this->cached_model_changes_between_requested_version_and_current === null) {
142
+			$model_changes = array();
143
+			foreach ($this->modelChanges() as $version => $models_changed_in_version) {
144
+				if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
145
+					$model_changes[ $version ] = $models_changed_in_version;
146
+				}
147
+			}
148
+			$this->cached_model_changes_between_requested_version_and_current = $model_changes;
149
+		}
150
+		return $this->cached_model_changes_between_requested_version_and_current;
151
+	}
152
+
153
+
154
+	/**
155
+	 * Returns a slice of Model_Version_Info::model_changes()'s array
156
+	 * indicating exactly what changes happened between the current core version,
157
+	 * and the version requested
158
+	 *
159
+	 * @return array
160
+	 */
161
+	public function resourceChangesBetweenRequestedVersionAndCurrent()
162
+	{
163
+		if ($this->cached_resource_changes_between_requested_version_and_current === null) {
164
+			$resource_changes = array();
165
+			foreach ($this->resourceChanges() as $version => $model_classnames) {
166
+				if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
167
+					$resource_changes[ $version ] = $model_classnames;
168
+				}
169
+			}
170
+			$this->cached_resource_changes_between_requested_version_and_current = $resource_changes;
171
+		}
172
+		return $this->cached_resource_changes_between_requested_version_and_current;
173
+	}
174
+
175
+
176
+	/**
177
+	 * If a request was sent to 'wp-json/ee/v4.7/events' this would be '4.7'
178
+	 *
179
+	 * @return string like '4.6'
180
+	 */
181
+	public function requestedVersion()
182
+	{
183
+		return $this->requested_version;
184
+	}
185
+
186
+
187
+	/**
188
+	 * Returns an array describing how the models have changed in each version of core
189
+	 * that supports the API (starting at 4.6)
190
+	 * Top-level keys are versions (major and minor version numbers, eg "4.6")
191
+	 * next-level keys are model names (eg "Event") that underwent some change in that version
192
+	 * and the value is either NULL (indicating the model is completely NEW in this version),
193
+	 * or it's an array where fields are value names.
194
+	 * If a version is missing then we don't know anything about what changes it introduced from the previous version
195
+	 *
196
+	 * @return array
197
+	 */
198
+	public function modelChanges()
199
+	{
200
+		return $this->model_changes;
201
+	}
202
+
203
+
204
+	/**
205
+	 * Takes into account the requested version, and the current version, and
206
+	 * what changed between the two, and tries to return.
207
+	 * Analogous to EE_Registry::instance()->non_abstract_db_models
208
+	 *
209
+	 * @return array keys are model names, values are their classname
210
+	 */
211
+	public function modelsForRequestedVersion()
212
+	{
213
+		if ($this->cached_models_for_requested_version === null) {
214
+			$all_models_in_current_version = EE_Registry::instance()->non_abstract_db_models;
215
+			foreach ($this->modelChangesBetweenRequestedVersionAndCurrent() as $version => $models_changed) {
216
+				foreach ($models_changed as $model_name => $new_indicator_or_fields_added) {
217
+					if ($new_indicator_or_fields_added === ModelVersionInfo::MODEL_ADDED) {
218
+						unset($all_models_in_current_version[ $model_name ]);
219
+					}
220
+				}
221
+			}
222
+			$this->cached_models_for_requested_version = apply_filters(
223
+				'FHEE__EventEspresso_core_libraries_rest_api__models_for_requested_version',
224
+				$all_models_in_current_version,
225
+				$this
226
+			);
227
+		}
228
+		return $this->cached_models_for_requested_version;
229
+	}
230
+
231
+
232
+	/**
233
+	 * Determines if this is a valid model name in the requested version.
234
+	 * Similar to EE_Registry::instance()->is_model_name(), but takes the requested
235
+	 * version's models into account
236
+	 *
237
+	 * @param string $model_name eg 'Event'
238
+	 * @return boolean
239
+	 */
240
+	public function isModelNameInThisVersion($model_name)
241
+	{
242
+		$model_names = $this->modelsForRequestedVersion();
243
+		if (isset($model_names[ $model_name ])) {
244
+			return true;
245
+		} else {
246
+			return false;
247
+		}
248
+	}
249
+
250
+
251
+	/**
252
+	 * Wrapper for EE_Registry::instance()->load_model(), but takes the requested
253
+	 * version's models into account
254
+	 *
255
+	 * @param string $model_name
256
+	 * @return EEM_Base
257
+	 * @throws EE_Error
258
+	 */
259
+	public function loadModel($model_name)
260
+	{
261
+		if ($this->isModelNameInThisVersion($model_name)) {
262
+			return EE_Registry::instance()->load_model($model_name);
263
+		} else {
264
+			throw new EE_Error(
265
+				sprintf(
266
+					esc_html__(
267
+						'Cannot load model "%1$s" because it does not exist in version %2$s of Event Espresso',
268
+						'event_espresso'
269
+					),
270
+					$model_name,
271
+					$this->requestedVersion()
272
+				)
273
+			);
274
+		}
275
+	}
276
+
277
+
278
+	/**
279
+	 * Gets all the fields that should exist on this model right now
280
+	 *
281
+	 * @param EEM_Base $model
282
+	 * @return array|EE_Model_Field_Base[]
283
+	 */
284
+	public function fieldsOnModelInThisVersion($model)
285
+	{
286
+		if (! isset($this->cached_fields_on_models[ $model->get_this_model_name() ])) {
287
+			// get all model changes between the requested version and current core version
288
+			$changes = $this->modelChangesBetweenRequestedVersionAndCurrent();
289
+			// fetch all fields currently on this model
290
+			$current_fields = $model->field_settings();
291
+			// remove all fields that have been added since
292
+			foreach ($changes as $version => $changes_in_version) {
293
+				if (
294
+					isset($changes_in_version[ $model->get_this_model_name() ])
295
+					&& $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
296
+				) {
297
+					$current_fields = array_diff_key(
298
+						$current_fields,
299
+						array_flip($changes_in_version[ $model->get_this_model_name() ])
300
+					);
301
+				}
302
+			}
303
+			$this->cached_fields_on_models = $current_fields;
304
+		}
305
+		return $this->cached_fields_on_models;
306
+	}
307
+
308
+
309
+	/**
310
+	 * Determines if $object is of one of the classes of $classes. Similar to
311
+	 * in_array(), except this checks if $object is a subclass of the classnames provided
312
+	 * in $classnames
313
+	 *
314
+	 * @param object $object
315
+	 * @param array  $classnames
316
+	 * @return boolean
317
+	 */
318
+	public function isSubclassOfOne($object, $classnames)
319
+	{
320
+		foreach ($classnames as $classname) {
321
+			if (is_a($object, $classname)) {
322
+				return true;
323
+			}
324
+		}
325
+		return false;
326
+	}
327
+
328
+
329
+	/**
330
+	 * Returns the list of model field classes that that the API basically ignores
331
+	 *
332
+	 * @return array
333
+	 */
334
+	public function fieldsIgnored()
335
+	{
336
+		return apply_filters(
337
+			'FHEE__Controller_Model_Read_fields_ignored',
338
+			array()
339
+		);
340
+	}
341
+
342
+
343
+	/**
344
+	 * If this field one that should be ignored by the API?
345
+	 *
346
+	 * @param EE_Model_Field_Base
347
+	 * @return boolean
348
+	 */
349
+	public function fieldIsIgnored($field_obj)
350
+	{
351
+		return $this->isSubclassOfOne($field_obj, $this->fieldsIgnored());
352
+	}
353
+
354
+
355
+	/**
356
+	 * Returns the list of model field classes that have a "raw" and non-raw formats.
357
+	 * Normally the "raw" versions are only accessible to those who can edit them.
358
+	 *
359
+	 * @return array an array of EE_Model_Field_Base child classnames
360
+	 */
361
+	public function fieldsThatHaveRenderedFormat()
362
+	{
363
+		return apply_filters(
364
+			'FHEE__Controller_Model_Read__fields_raw',
365
+			array('EE_Post_Content_Field', 'EE_Full_HTML_Field')
366
+		);
367
+	}
368
+
369
+
370
+	/**
371
+	 * If this field one that has a raw format
372
+	 *
373
+	 * @param EE_Model_Field_Base
374
+	 * @return boolean
375
+	 */
376
+	public function fieldHasRenderedFormat($field_obj)
377
+	{
378
+		return $this->isSubclassOfOne($field_obj, $this->fieldsThatHaveRenderedFormat());
379
+	}
380
+
381
+
382
+	/**
383
+	 * Returns the list of model field classes that have a "_pretty" and non-pretty versions.
384
+	 * The pretty version of the field is NOT query-able or editable, but requires no extra permissions
385
+	 * to view
386
+	 *
387
+	 * @return array an array of EE_Model_Field_Base child classnames
388
+	 */
389
+	public function fieldsThatHavePrettyFormat()
390
+	{
391
+		return apply_filters(
392
+			'FHEE__Controller_Model_Read__fields_pretty',
393
+			array('EE_Enum_Integer_Field', 'EE_Enum_Text_Field', 'EE_Money_Field')
394
+		);
395
+	}
396
+
397
+
398
+	/**
399
+	 * If this field one that has a pretty equivalent
400
+	 *
401
+	 * @param EE_Model_Field_Base
402
+	 * @return boolean
403
+	 */
404
+	public function fieldHasPrettyFormat($field_obj)
405
+	{
406
+		return $this->isSubclassOfOne($field_obj, $this->fieldsThatHavePrettyFormat());
407
+	}
408
+
409
+
410
+	/**
411
+	 * Returns an array describing what extra API resource properties have been added through the versions
412
+	 *
413
+	 * @return array @see $this->_extra_resource_properties_for_models
414
+	 */
415
+	public function resourceChanges()
416
+	{
417
+		return $this->resource_changes;
418
+	}
419
+
420
+
421
+	/**
422
+	 * Returns an array where keys are extra resource properties in this version of the API,
423
+	 * and values are key-value pairs describing the new properties. @see Model_Version::_resource_changes
424
+	 *
425
+	 * @param EEM_Base $model
426
+	 * @return array
427
+	 */
428
+	public function extraResourcePropertiesForModel($model)
429
+	{
430
+		$extra_properties = array();
431
+		foreach ($this->resourceChangesBetweenRequestedVersionAndCurrent() as $version => $model_classnames) {
432
+			foreach ($model_classnames as $model_classname => $properties_added_in_this_version) {
433
+				if (is_subclass_of($model, $model_classname)) {
434
+					$extra_properties = array_merge($extra_properties, $properties_added_in_this_version);
435
+				}
436
+			}
437
+		}
438
+		return $extra_properties;
439
+	}
440
+
441
+
442
+	/**
443
+	 * Gets all the related models for the specified model. It's good to use this
444
+	 * in case this model didn't exist for this version or something
445
+	 *
446
+	 * @param EEM_Base $model
447
+	 * @return EE_Model_Relation_Base[]
448
+	 */
449
+	public function relationSettings($model)
450
+	{
451
+		$relations = array();
452
+		foreach ($model->relation_settings() as $relation_name => $relation_obj) {
453
+			if ($this->isModelNameInThisVersion($relation_name)) {
454
+				$relations[ $relation_name ] = $relation_obj;
455
+			}
456
+		}
457
+		// filter the results, but use the old filter name
458
+		return apply_filters(
459
+			'FHEE__Read__create_entity_from_wpdb_result__related_models_to_include',
460
+			$relations,
461
+			$model
462
+		);
463
+	}
464 464
 }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Base.lib.php 2 patches
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -196,11 +196,11 @@  discard block
 block discarded – undo
196 196
             ! empty($messenger)
197 197
             && $Message_Resource_Manager->is_message_type_active_for_messenger($messenger, $this->name)
198 198
         ) {
199
-            $settings_to_use = $active_messengers[ $messenger ]['settings'][ $messenger . '-message_types' ];
199
+            $settings_to_use = $active_messengers[$messenger]['settings'][$messenger.'-message_types'];
200 200
         }
201 201
 
202
-        $this->_existing_admin_settings = isset($settings_to_use[ $this->name ]['settings'])
203
-            ? $settings_to_use[ $this->name ]['settings']
202
+        $this->_existing_admin_settings = isset($settings_to_use[$this->name]['settings'])
203
+            ? $settings_to_use[$this->name]['settings']
204 204
             : null;
205 205
     }
206 206
 
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
     public function get_valid_shortcodes()
241 241
     {
242 242
         $valid_shortcodes = apply_filters(
243
-            'FHEE__' . get_class($this) . '__get_valid_shortcodes',
243
+            'FHEE__'.get_class($this).'__get_valid_shortcodes',
244 244
             $this->_valid_shortcodes,
245 245
             $this
246 246
         );
@@ -283,19 +283,19 @@  discard block
 block discarded – undo
283 283
     protected function _get_admin_page_content($page, $action, $extra, $actives)
284 284
     {
285 285
         // we can also further refine the context by action (if present).
286
-        if (!empty($action)) {
287
-            $page = $page . '_' . $action;
286
+        if ( ! empty($action)) {
287
+            $page = $page.'_'.$action;
288 288
         }
289 289
 
290
-        if (!isset($this->admin_registered_pages[ $page ])) {
290
+        if ( ! isset($this->admin_registered_pages[$page])) {
291 291
             // todo: a place to throw an exception?
292 292
             // We need to indicate there is no registered page so this function is not being called correctly.
293 293
             return false;
294 294
         }
295 295
         // k made it here so let's call the method
296 296
         $content = call_user_func_array(
297
-            array( $this, '_get_admin_content_' . $page ),
298
-            array( $actives, $extra )
297
+            array($this, '_get_admin_content_'.$page),
298
+            array($actives, $extra)
299 299
         );
300 300
         if ($content === false) {
301 301
             // todo this needs to be an exception once we've got exceptions in place.
Please login to merge, or discard this patch.
Indentation   +265 added lines, -265 removed lines patch added patch discarded remove patch
@@ -13,44 +13,44 @@  discard block
 block discarded – undo
13 13
  */
14 14
 abstract class EE_Messages_Base extends EE_Base
15 15
 {
16
-    /** DETAILS PROPERTIES **/
17
-    /**
18
-     * The following are used to hold details on the type for reference (i.e. on admin screens)
19
-     * and also used by the EE_message_type object to figure out where to get template data.
20
-     */
21
-    public $name;
22
-    public $description;
23
-    protected $_messages_item_type; // messenger OR message_type?
24
-
25
-
26
-    /**
27
-     * This is an array describing the ui facing labels
28
-     * that will be used whenever the messenger is referenced in the ui
29
-     *
30
-     * array(
31
-     *  'singular' => esc_html__('something'),
32
-     *  'plural' => esc_html__('somethings')
33
-     * )
34
-     *
35
-     * @var array
36
-     */
37
-    public $label;
38
-
39
-
40
-
41
-
42
-    /**
43
-     * This property when set will hold the slugs of all EE admin pages that we will need to retrieve fields for
44
-     * (and used to determine which callback method to call from the child class)
45
-     *
46
-     * structure should be
47
-     * array(
48
-     * 'page_action' => true
49
-     * )
50
-     *
16
+	/** DETAILS PROPERTIES **/
17
+	/**
18
+	 * The following are used to hold details on the type for reference (i.e. on admin screens)
19
+	 * and also used by the EE_message_type object to figure out where to get template data.
20
+	 */
21
+	public $name;
22
+	public $description;
23
+	protected $_messages_item_type; // messenger OR message_type?
24
+
25
+
26
+	/**
27
+	 * This is an array describing the ui facing labels
28
+	 * that will be used whenever the messenger is referenced in the ui
29
+	 *
30
+	 * array(
31
+	 *  'singular' => esc_html__('something'),
32
+	 *  'plural' => esc_html__('somethings')
33
+	 * )
34
+	 *
35
+	 * @var array
36
+	 */
37
+	public $label;
38
+
39
+
40
+
41
+
42
+	/**
43
+	 * This property when set will hold the slugs of all EE admin pages that we will need to retrieve fields for
44
+	 * (and used to determine which callback method to call from the child class)
45
+	 *
46
+	 * structure should be
47
+	 * array(
48
+	 * 'page_action' => true
49
+	 * )
50
+	 *
51 51
 *@var array
52
-     */
53
-    public $admin_registered_pages = array();
52
+	 */
53
+	public $admin_registered_pages = array();
54 54
 
55 55
 
56 56
 
@@ -59,265 +59,265 @@  discard block
 block discarded – undo
59 59
 
60 60
 
61 61
 
62
-    /**
63
-     * this property holds any specific fields for holding any settings related to a messenger (if any needed)
64
-     * @var array
65
-     */
66
-    protected $_admin_settings_fields = array();
62
+	/**
63
+	 * this property holds any specific fields for holding any settings related to a messenger (if any needed)
64
+	 * @var array
65
+	 */
66
+	protected $_admin_settings_fields = array();
67 67
 
68 68
 
69 69
 
70 70
 
71 71
 
72
-    /**
73
-     * this property will hold any existing settings that may have been set in the admin.
74
-     * @var array
75
-     */
76
-    protected $_existing_admin_settings = array();
72
+	/**
73
+	 * this property will hold any existing settings that may have been set in the admin.
74
+	 * @var array
75
+	 */
76
+	protected $_existing_admin_settings = array();
77 77
 
78 78
 
79 79
 
80 80
 
81 81
 
82
-    /**
83
-     * this property will hold an array of valid shortcodes for this message type and messengers.
84
-     * #For Message Types:
85
-     * This is an array of strings that correspond to defined EE_Shortcode libraries and per context.
86
-     * For example:
87
-     * array( 'admin' => array('transaction', 'event', 'attendee') )
88
-     * corresponds to 'EE_Transaction_Shortcodes.lib.php, EE_Event_Shortcodes.lib.php, EE_Attendee_Shortcodes.lib.php'
89
-     * for the admin context;
90
-     *
91
-     *
92
-     * #For Messengers:
93
-     * For example:
94
-     * array('subject' => array('transaction', 'event', 'attendee'))
95
-     * corresponds to 'EE_Transaction_Shortcodes.lib.php, EE_Event_Shortcodes.lib.php, EE_Attendee_Shortcodes.lib.php'
96
-     * for the 'subject' field;
97
-     * NOTE:  by default, with messengers, if the valid shortcodes for a field is left blank,
98
-     * that field will inherit whatever are set as valid shortcodes by message_type.
99
-     * This is so messenger can set specific valid codes for fields and leave other
100
-     * valid shortcodes up to the message type matched with the messenger.
101
-     *
102
-     * @access protected
103
-     * @var array
104
-     */
105
-    protected $_valid_shortcodes = array();
82
+	/**
83
+	 * this property will hold an array of valid shortcodes for this message type and messengers.
84
+	 * #For Message Types:
85
+	 * This is an array of strings that correspond to defined EE_Shortcode libraries and per context.
86
+	 * For example:
87
+	 * array( 'admin' => array('transaction', 'event', 'attendee') )
88
+	 * corresponds to 'EE_Transaction_Shortcodes.lib.php, EE_Event_Shortcodes.lib.php, EE_Attendee_Shortcodes.lib.php'
89
+	 * for the admin context;
90
+	 *
91
+	 *
92
+	 * #For Messengers:
93
+	 * For example:
94
+	 * array('subject' => array('transaction', 'event', 'attendee'))
95
+	 * corresponds to 'EE_Transaction_Shortcodes.lib.php, EE_Event_Shortcodes.lib.php, EE_Attendee_Shortcodes.lib.php'
96
+	 * for the 'subject' field;
97
+	 * NOTE:  by default, with messengers, if the valid shortcodes for a field is left blank,
98
+	 * that field will inherit whatever are set as valid shortcodes by message_type.
99
+	 * This is so messenger can set specific valid codes for fields and leave other
100
+	 * valid shortcodes up to the message type matched with the messenger.
101
+	 *
102
+	 * @access protected
103
+	 * @var array
104
+	 */
105
+	protected $_valid_shortcodes = array();
106 106
 
107 107
 
108 108
 
109 109
 
110 110
 
111
-    public function __construct()
112
-    {
113
-        $this->_set_admin_settings_fields();
114
-        $this->_set_valid_shortcodes();
115
-        $this->_set_admin_pages();
116
-    }
111
+	public function __construct()
112
+	{
113
+		$this->_set_admin_settings_fields();
114
+		$this->_set_valid_shortcodes();
115
+		$this->_set_admin_pages();
116
+	}
117 117
 
118 118
 
119 119
 
120 120
 
121 121
 
122
-    /**
123
-     * sets the _admin_settings_fields property which needs to be defined by child classes.
124
-     * You will want to set the _admin_settings_fields properties as a multi-dimensional array with the following format
125
-     * array(
126
-     *      {field_name - also used for setting index} => array(
127
-     *          'field_type' => {type of field: 'text', 'textarea', 'checkbox'},
128
-     *          'value_type' => {type of value: 'string', 'int', 'array', 'bool'},
129
-     *          'required' => {bool, required or not},
130
-     *          'validation' => {bool, true if we want validation, false if not},
131
-     *          'format' => {%d, or %s},
132
-     *          'label' => {label for the field, make sure it's localized},
133
-     *          'default' => {default value for the setting}
134
-     *      ),
135
-     * );
136
-     *
137
-     * @abstract
138
-     * @access protected
139
-     * @return void
140
-     */
141
-    abstract protected function _set_admin_settings_fields();
122
+	/**
123
+	 * sets the _admin_settings_fields property which needs to be defined by child classes.
124
+	 * You will want to set the _admin_settings_fields properties as a multi-dimensional array with the following format
125
+	 * array(
126
+	 *      {field_name - also used for setting index} => array(
127
+	 *          'field_type' => {type of field: 'text', 'textarea', 'checkbox'},
128
+	 *          'value_type' => {type of value: 'string', 'int', 'array', 'bool'},
129
+	 *          'required' => {bool, required or not},
130
+	 *          'validation' => {bool, true if we want validation, false if not},
131
+	 *          'format' => {%d, or %s},
132
+	 *          'label' => {label for the field, make sure it's localized},
133
+	 *          'default' => {default value for the setting}
134
+	 *      ),
135
+	 * );
136
+	 *
137
+	 * @abstract
138
+	 * @access protected
139
+	 * @return void
140
+	 */
141
+	abstract protected function _set_admin_settings_fields();
142 142
 
143 143
 
144 144
 
145 145
 
146 146
 
147
-    /**
148
-     * sets any properties on whether a message type or messenger interface shows up on a ee administration page.
149
-     * Child classes have to define this method but don't necessarily have to set the flags
150
-     * as they will be set to false by default.
151
-     *
152
-     * Child classes use this method to set the `_admin_registered_page` property.
153
-     * That property is to indicate what EE admin pages we have a corresponding callback for in the child class
154
-     * so Message Type/messenger fields/content is included on that admin page.
155
-     *
156
-     * @abstract
157
-     * @access protected
158
-     * @return void
159
-     */
160
-    abstract protected function _set_admin_pages();
147
+	/**
148
+	 * sets any properties on whether a message type or messenger interface shows up on a ee administration page.
149
+	 * Child classes have to define this method but don't necessarily have to set the flags
150
+	 * as they will be set to false by default.
151
+	 *
152
+	 * Child classes use this method to set the `_admin_registered_page` property.
153
+	 * That property is to indicate what EE admin pages we have a corresponding callback for in the child class
154
+	 * so Message Type/messenger fields/content is included on that admin page.
155
+	 *
156
+	 * @abstract
157
+	 * @access protected
158
+	 * @return void
159
+	 */
160
+	abstract protected function _set_admin_pages();
161 161
 
162 162
 
163 163
 
164 164
 
165 165
 
166
-    /**
167
-     * Child classes must declare the $_valid_shortcodes property using this method.
168
-     * See comments for $_valid_shortcodes property for details on what it is used for.
169
-     *
170
-     * @access protected
171
-     * @return void
172
-     */
173
-    abstract protected function _set_valid_shortcodes();
166
+	/**
167
+	 * Child classes must declare the $_valid_shortcodes property using this method.
168
+	 * See comments for $_valid_shortcodes property for details on what it is used for.
169
+	 *
170
+	 * @access protected
171
+	 * @return void
172
+	 */
173
+	abstract protected function _set_valid_shortcodes();
174 174
 
175 175
 
176 176
 
177
-    /**
178
-     * sets the _existing_admin_settings property can be overridden by child classes.
179
-     * We do this so we only do database calls if needed.
180
-     *
181
-     * @access protected
182
-     * @param string $messenger
183
-     */
184
-    protected function _set_existing_admin_settings($messenger = '')
185
-    {
186
-        /** @var EE_Message_Resource_Manager $Message_Resource_Manager */
187
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
188
-        $active_messengers = $Message_Resource_Manager->get_active_messengers_option();
189
-        $settings_to_use = $active_messengers;
190
-
191
-        /**
192
-         * This determines what will be used for the getting the settings.
193
-         */
194
-        if (
195
-            ! empty($messenger)
196
-            && $Message_Resource_Manager->is_message_type_active_for_messenger($messenger, $this->name)
197
-        ) {
198
-            $settings_to_use = $active_messengers[ $messenger ]['settings'][ $messenger . '-message_types' ];
199
-        }
200
-
201
-        $this->_existing_admin_settings = isset($settings_to_use[ $this->name ]['settings'])
202
-            ? $settings_to_use[ $this->name ]['settings']
203
-            : null;
204
-    }
205
-
206
-
207
-
208
-
209
-
210
-
211
-    /**
212
-     * get_existing_admin_settings
213
-     * (if needed) sets and returns the _existing_admin_settings property.
214
-     *
215
-     * @access public
216
-     * @param string $messenger
217
-     * @return array          settings
218
-     */
219
-    public function get_existing_admin_settings($messenger = '')
220
-    {
221
-        // if admin_settings property empty lets try setting it.
222
-        if (method_exists($this, '_set_existing_admin_settings') && empty($this->_existing_admin_settings)) {
223
-            $this->_set_existing_admin_settings($messenger);
224
-        }
225
-        return property_exists($this, '_existing_admin_settings')
226
-            ? $this->_existing_admin_settings
227
-            : null;
228
-    }
229
-
230
-
231
-
232
-
233
-
234
-
235
-    /**
236
-     * This returns the array of valid shortcodes for a message type or messenger as set by the child in the $_valid_shortcode property.
237
-     * @return array   an array of valid shortcodes.
238
-     */
239
-    public function get_valid_shortcodes()
240
-    {
241
-        $valid_shortcodes = apply_filters(
242
-            'FHEE__' . get_class($this) . '__get_valid_shortcodes',
243
-            $this->_valid_shortcodes,
244
-            $this
245
-        );
246
-        // The below filter applies to ALL messengers and message types so use with care!
247
-        $valid_shortcodes = apply_filters('FHEE__EE_Messages_Base__get_valid_shortcodes', $valid_shortcodes, $this);
248
-        return $valid_shortcodes;
249
-    }
250
-
251
-
252
-
253
-
254
-    /**
255
-     * getter that returns the protected admin_settings_fields property
256
-     *
257
-     * @access public
258
-     * @return array admin settings fields
259
-     */
260
-    public function get_admin_settings_fields()
261
-    {
262
-        return $this->_admin_settings_fields;
263
-    }
264
-
265
-
266
-
267
-
268
-
269
-    /**
270
-     * this public method accepts a page slug (for an EE_admin page)
271
-     * and will return the response from the child class callback function
272
-     * if that page is registered via the `_admin_registered_page` property set by the child class.
273
-     *
274
-     * @param string $page the slug of the EE admin page
275
-     * @param array $actives an array of active message type (or messenger) objects.
276
-     * @param string $action the page action (to allow for more specific handling - i.e. edit vs. add pages)
277
-     * @param array $extra This is just an extra argument that can be used
278
-     *                     to pass additional data for setting up page content.
279
-     * @access protected
280
-     * @return string $content for page.
281
-     */
282
-    protected function _get_admin_page_content($page, $action, $extra, $actives)
283
-    {
284
-        // we can also further refine the context by action (if present).
285
-        if (!empty($action)) {
286
-            $page = $page . '_' . $action;
287
-        }
288
-
289
-        if (!isset($this->admin_registered_pages[ $page ])) {
290
-            // todo: a place to throw an exception?
291
-            // We need to indicate there is no registered page so this function is not being called correctly.
292
-            return false;
293
-        }
294
-        // k made it here so let's call the method
295
-        $content = call_user_func_array(
296
-            array( $this, '_get_admin_content_' . $page ),
297
-            array( $actives, $extra )
298
-        );
299
-        if ($content === false) {
300
-            // todo this needs to be an exception once we've got exceptions in place.
301
-            return false;
302
-        }
303
-        return $content;
304
-    }
305
-
306
-
307
-    /**
308
-     * Allows a message type to specifically exclude template fields for the provided messenger.
309
-     * Filtered so this can be programmatically altered as well.
310
-     * @param string $messenger_name name of messenger
311
-     * @return array
312
-     */
313
-    public function excludedFieldsForMessenger($messenger_name)
314
-    {
315
-        return apply_filters(
316
-            'FHEE__EE_Messages_Base__excludedFieldForMessenger',
317
-            array(),
318
-            $messenger_name,
319
-            $this->name,
320
-            $this
321
-        );
322
-    }
177
+	/**
178
+	 * sets the _existing_admin_settings property can be overridden by child classes.
179
+	 * We do this so we only do database calls if needed.
180
+	 *
181
+	 * @access protected
182
+	 * @param string $messenger
183
+	 */
184
+	protected function _set_existing_admin_settings($messenger = '')
185
+	{
186
+		/** @var EE_Message_Resource_Manager $Message_Resource_Manager */
187
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
188
+		$active_messengers = $Message_Resource_Manager->get_active_messengers_option();
189
+		$settings_to_use = $active_messengers;
190
+
191
+		/**
192
+		 * This determines what will be used for the getting the settings.
193
+		 */
194
+		if (
195
+			! empty($messenger)
196
+			&& $Message_Resource_Manager->is_message_type_active_for_messenger($messenger, $this->name)
197
+		) {
198
+			$settings_to_use = $active_messengers[ $messenger ]['settings'][ $messenger . '-message_types' ];
199
+		}
200
+
201
+		$this->_existing_admin_settings = isset($settings_to_use[ $this->name ]['settings'])
202
+			? $settings_to_use[ $this->name ]['settings']
203
+			: null;
204
+	}
205
+
206
+
207
+
208
+
209
+
210
+
211
+	/**
212
+	 * get_existing_admin_settings
213
+	 * (if needed) sets and returns the _existing_admin_settings property.
214
+	 *
215
+	 * @access public
216
+	 * @param string $messenger
217
+	 * @return array          settings
218
+	 */
219
+	public function get_existing_admin_settings($messenger = '')
220
+	{
221
+		// if admin_settings property empty lets try setting it.
222
+		if (method_exists($this, '_set_existing_admin_settings') && empty($this->_existing_admin_settings)) {
223
+			$this->_set_existing_admin_settings($messenger);
224
+		}
225
+		return property_exists($this, '_existing_admin_settings')
226
+			? $this->_existing_admin_settings
227
+			: null;
228
+	}
229
+
230
+
231
+
232
+
233
+
234
+
235
+	/**
236
+	 * This returns the array of valid shortcodes for a message type or messenger as set by the child in the $_valid_shortcode property.
237
+	 * @return array   an array of valid shortcodes.
238
+	 */
239
+	public function get_valid_shortcodes()
240
+	{
241
+		$valid_shortcodes = apply_filters(
242
+			'FHEE__' . get_class($this) . '__get_valid_shortcodes',
243
+			$this->_valid_shortcodes,
244
+			$this
245
+		);
246
+		// The below filter applies to ALL messengers and message types so use with care!
247
+		$valid_shortcodes = apply_filters('FHEE__EE_Messages_Base__get_valid_shortcodes', $valid_shortcodes, $this);
248
+		return $valid_shortcodes;
249
+	}
250
+
251
+
252
+
253
+
254
+	/**
255
+	 * getter that returns the protected admin_settings_fields property
256
+	 *
257
+	 * @access public
258
+	 * @return array admin settings fields
259
+	 */
260
+	public function get_admin_settings_fields()
261
+	{
262
+		return $this->_admin_settings_fields;
263
+	}
264
+
265
+
266
+
267
+
268
+
269
+	/**
270
+	 * this public method accepts a page slug (for an EE_admin page)
271
+	 * and will return the response from the child class callback function
272
+	 * if that page is registered via the `_admin_registered_page` property set by the child class.
273
+	 *
274
+	 * @param string $page the slug of the EE admin page
275
+	 * @param array $actives an array of active message type (or messenger) objects.
276
+	 * @param string $action the page action (to allow for more specific handling - i.e. edit vs. add pages)
277
+	 * @param array $extra This is just an extra argument that can be used
278
+	 *                     to pass additional data for setting up page content.
279
+	 * @access protected
280
+	 * @return string $content for page.
281
+	 */
282
+	protected function _get_admin_page_content($page, $action, $extra, $actives)
283
+	{
284
+		// we can also further refine the context by action (if present).
285
+		if (!empty($action)) {
286
+			$page = $page . '_' . $action;
287
+		}
288
+
289
+		if (!isset($this->admin_registered_pages[ $page ])) {
290
+			// todo: a place to throw an exception?
291
+			// We need to indicate there is no registered page so this function is not being called correctly.
292
+			return false;
293
+		}
294
+		// k made it here so let's call the method
295
+		$content = call_user_func_array(
296
+			array( $this, '_get_admin_content_' . $page ),
297
+			array( $actives, $extra )
298
+		);
299
+		if ($content === false) {
300
+			// todo this needs to be an exception once we've got exceptions in place.
301
+			return false;
302
+		}
303
+		return $content;
304
+	}
305
+
306
+
307
+	/**
308
+	 * Allows a message type to specifically exclude template fields for the provided messenger.
309
+	 * Filtered so this can be programmatically altered as well.
310
+	 * @param string $messenger_name name of messenger
311
+	 * @return array
312
+	 */
313
+	public function excludedFieldsForMessenger($messenger_name)
314
+	{
315
+		return apply_filters(
316
+			'FHEE__EE_Messages_Base__excludedFieldForMessenger',
317
+			array(),
318
+			$messenger_name,
319
+			$this->name,
320
+			$this
321
+		);
322
+	}
323 323
 }
Please login to merge, or discard this patch.