Completed
Branch Gutenberg/master (b3a823)
by
unknown
73:52 queued 60:28
created
core/libraries/rest_api/ModelDataTranslator.php 2 patches
Indentation   +825 added lines, -825 removed lines patch added patch discarded remove patch
@@ -32,829 +32,829 @@
 block discarded – undo
32 32
 class ModelDataTranslator
33 33
 {
34 34
 
35
-    /**
36
-     * We used to use -1 for infinity in the rest api, but that's ambiguous for
37
-     * fields that COULD contain -1; so we use null
38
-     */
39
-    const EE_INF_IN_REST = null;
40
-
41
-
42
-    /**
43
-     * Prepares a possible array of input values from JSON for use by the models
44
-     *
45
-     * @param EE_Model_Field_Base $field_obj
46
-     * @param mixed               $original_value_maybe_array
47
-     * @param string              $requested_version
48
-     * @param string              $timezone_string treat values as being in this timezone
49
-     * @return mixed
50
-     * @throws RestException
51
-     */
52
-    public static function prepareFieldValuesFromJson(
53
-        $field_obj,
54
-        $original_value_maybe_array,
55
-        $requested_version,
56
-        $timezone_string = 'UTC'
57
-    ) {
58
-        if (is_array($original_value_maybe_array)
59
-            && ! $field_obj instanceof EE_Serialized_Text_Field
60
-        ) {
61
-            $new_value_maybe_array = array();
62
-            foreach ($original_value_maybe_array as $array_key => $array_item) {
63
-                $new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
64
-                    $field_obj,
65
-                    $array_item,
66
-                    $requested_version,
67
-                    $timezone_string
68
-                );
69
-            }
70
-        } else {
71
-            $new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
72
-                $field_obj,
73
-                $original_value_maybe_array,
74
-                $requested_version,
75
-                $timezone_string
76
-            );
77
-        }
78
-        return $new_value_maybe_array;
79
-    }
80
-
81
-
82
-    /**
83
-     * Prepares an array of field values FOR use in JSON/REST API
84
-     *
85
-     * @param EE_Model_Field_Base $field_obj
86
-     * @param mixed               $original_value_maybe_array
87
-     * @param string              $request_version (eg 4.8.36)
88
-     * @return array
89
-     */
90
-    public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
91
-    {
92
-        if (is_array($original_value_maybe_array)) {
93
-            $new_value = array();
94
-            foreach ($original_value_maybe_array as $key => $value) {
95
-                $new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
96
-                    $field_obj,
97
-                    $value,
98
-                    $request_version
99
-                );
100
-            }
101
-        } else {
102
-            $new_value = ModelDataTranslator::prepareFieldValueForJson(
103
-                $field_obj,
104
-                $original_value_maybe_array,
105
-                $request_version
106
-            );
107
-        }
108
-        return $new_value;
109
-    }
110
-
111
-
112
-    /**
113
-     * Prepares incoming data from the json or $_REQUEST parameters for the models'
114
-     * "$query_params".
115
-     *
116
-     * @param EE_Model_Field_Base $field_obj
117
-     * @param mixed               $original_value
118
-     * @param string              $requested_version
119
-     * @param string              $timezone_string treat values as being in this timezone
120
-     * @return mixed
121
-     * @throws RestException
122
-     * @throws DomainException
123
-     * @throws EE_Error
124
-     */
125
-    public static function prepareFieldValueFromJson(
126
-        $field_obj,
127
-        $original_value,
128
-        $requested_version,
129
-        $timezone_string = 'UTC' // UTC
130
-    ) {
131
-        // check if they accidentally submitted an error value. If so throw an exception
132
-        if (is_array($original_value)
133
-            && isset($original_value['error_code'], $original_value['error_message'])) {
134
-            throw new RestException(
135
-                'rest_submitted_error_value',
136
-                sprintf(
137
-                    esc_html__(
138
-                        'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
139
-                        'event_espresso'
140
-                    ),
141
-                    $field_obj->get_name()
142
-                ),
143
-                array(
144
-                    'status' => 400,
145
-                )
146
-            );
147
-        }
148
-        // double-check for serialized PHP. We never accept serialized PHP. No way Jose.
149
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
150
-        $timezone_string = $timezone_string !== '' ? $timezone_string : get_option('timezone_string', '');
151
-        $new_value = null;
152
-        // walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
153
-        // way Jose.
154
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
155
-        if ($field_obj instanceof EE_Infinite_Integer_Field
156
-            && in_array($original_value, array(null, ''), true)
157
-        ) {
158
-            $new_value = EE_INF;
159
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
160
-            $new_value = rest_parse_date(
161
-                self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
162
-            );
163
-            if ($new_value === false) {
164
-                throw new RestException(
165
-                    'invalid_format_for_timestamp',
166
-                    sprintf(
167
-                        esc_html__(
168
-                            'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
169
-                            'event_espresso'
170
-                        ),
171
-                        'RFC3339',
172
-                        'ISO8601',
173
-                        $original_value
174
-                    ),
175
-                    array(
176
-                        'status' => 400,
177
-                    )
178
-                );
179
-            }
180
-        } else {
181
-            $new_value = $original_value;
182
-        }
183
-        return $new_value;
184
-    }
185
-
186
-
187
-    /**
188
-     * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
189
-     * information via details obtained from the host site.
190
-     *
191
-     * @param string            $original_timestamp
192
-     * @param EE_Datetime_Field $datetime_field
193
-     * @param                   $timezone_string
194
-     * @return string
195
-     * @throws DomainException
196
-     */
197
-    private static function getTimestampWithTimezoneOffset(
198
-        $original_timestamp,
199
-        EE_Datetime_Field $datetime_field,
200
-        $timezone_string
201
-    ) {
202
-        // already have timezone information?
203
-        if (preg_match('/Z|(\+|\-)(\d{2}:\d{2})/', $original_timestamp)) {
204
-            // yes, we're ignoring the timezone.
205
-            return $original_timestamp;
206
-        }
207
-        // need to append timezone
208
-        list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
209
-            $datetime_field->get_timezone_offset(
210
-                new \DateTimeZone($timezone_string),
211
-                $original_timestamp
212
-            )
213
-        );
214
-        $offset_string =
215
-            str_pad(
216
-                floor($offset_secs / HOUR_IN_SECONDS),
217
-                2,
218
-                '0',
219
-                STR_PAD_LEFT
220
-            )
221
-            . ':'
222
-            . str_pad(
223
-                ($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
224
-                2,
225
-                '0',
226
-                STR_PAD_LEFT
227
-            );
228
-        return $original_timestamp . $offset_sign . $offset_string;
229
-    }
230
-
231
-
232
-    /**
233
-     * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
234
-     * think that can happen). If $data is an array, recurses into its keys and values
235
-     *
236
-     * @param mixed $data
237
-     * @throws RestException
238
-     * @return void
239
-     */
240
-    public static function throwExceptionIfContainsSerializedData($data)
241
-    {
242
-        if (is_array($data)) {
243
-            foreach ($data as $key => $value) {
244
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
245
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
246
-            }
247
-        } else {
248
-            if (is_serialized($data) || is_object($data)) {
249
-                throw new RestException(
250
-                    'serialized_data_submission_prohibited',
251
-                    esc_html__(
252
-                    // @codingStandardsIgnoreStart
253
-                        'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
254
-                        // @codingStandardsIgnoreEnd
255
-                        'event_espresso'
256
-                    )
257
-                );
258
-            }
259
-        }
260
-    }
261
-
262
-
263
-    /**
264
-     * determines what's going on with them timezone strings
265
-     *
266
-     * @param int $timezone_offset
267
-     * @return array
268
-     */
269
-    private static function parseTimezoneOffset($timezone_offset)
270
-    {
271
-        $first_char = substr((string) $timezone_offset, 0, 1);
272
-        if ($first_char === '+' || $first_char === '-') {
273
-            $offset_sign = $first_char;
274
-            $offset_secs = substr((string) $timezone_offset, 1);
275
-        } else {
276
-            $offset_sign = '+';
277
-            $offset_secs = $timezone_offset;
278
-        }
279
-        return array($offset_sign, $offset_secs);
280
-    }
281
-
282
-
283
-    /**
284
-     * Prepares a field's value for display in the API
285
-     *
286
-     * @param EE_Model_Field_Base $field_obj
287
-     * @param mixed               $original_value
288
-     * @param string              $requested_version
289
-     * @return mixed
290
-     */
291
-    public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
292
-    {
293
-        if ($original_value === EE_INF) {
294
-            $new_value = ModelDataTranslator::EE_INF_IN_REST;
295
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
296
-            if (is_string($original_value)) {
297
-                // did they submit a string of a unix timestamp?
298
-                if (is_numeric($original_value)) {
299
-                    $datetime_obj = new \DateTime();
300
-                    $datetime_obj->setTimestamp((int) $original_value);
301
-                } else {
302
-                    // first, check if its a MySQL timestamp in GMT
303
-                    $datetime_obj = \DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
304
-                }
305
-                if (! $datetime_obj instanceof \DateTime) {
306
-                    // so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
307
-                    $datetime_obj = $field_obj->prepare_for_set($original_value);
308
-                }
309
-                $original_value = $datetime_obj;
310
-            }
311
-            if ($original_value instanceof \DateTime) {
312
-                $new_value = $original_value->format('Y-m-d H:i:s');
313
-            } elseif (is_int($original_value) || is_float($original_value)) {
314
-                $new_value = date('Y-m-d H:i:s', $original_value);
315
-            } elseif ($original_value === null || $original_value === '') {
316
-                $new_value = null;
317
-            } else {
318
-                // so it's not a datetime object, unix timestamp (as string or int),
319
-                // MySQL timestamp, or even a string in the field object's format. So no idea what it is
320
-                throw new \EE_Error(
321
-                    sprintf(
322
-                        esc_html__(
323
-                        // @codingStandardsIgnoreStart
324
-                            'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
325
-                            // @codingStandardsIgnoreEnd
326
-                            'event_espresso'
327
-                        ),
328
-                        $original_value,
329
-                        $field_obj->get_name(),
330
-                        $field_obj->get_model_name(),
331
-                        $field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
332
-                    )
333
-                );
334
-            }
335
-            $new_value = mysql_to_rfc3339($new_value);
336
-        } else {
337
-            $new_value = $original_value;
338
-        }
339
-        // are we about to send an object? just don't. We have no good way to represent it in JSON.
340
-        // can't just check using is_object() because that missed PHP incomplete objects
341
-        if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
342
-            $new_value = array(
343
-                'error_code'    => 'php_object_not_return',
344
-                'error_message' => esc_html__(
345
-                    'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
346
-                    'event_espresso'
347
-                ),
348
-            );
349
-        }
350
-        return apply_filters(
351
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
352
-            $new_value,
353
-            $field_obj,
354
-            $original_value,
355
-            $requested_version
356
-        );
357
-    }
358
-
359
-
360
-    /**
361
-     * Prepares condition-query-parameters (like what's in where and having) from
362
-     * the format expected in the API to use in the models
363
-     *
364
-     * @param array    $inputted_query_params_of_this_type
365
-     * @param EEM_Base $model
366
-     * @param string   $requested_version
367
-     * @param boolean  $writing whether this data will be written to the DB, or if we're just building a query.
368
-     *                          If we're writing to the DB, we don't expect any operators, or any logic query
369
-     *                          parameters, and we also won't accept serialized data unless the current user has
370
-     *                          unfiltered_html.
371
-     * @return array
372
-     * @throws DomainException
373
-     * @throws RestException
374
-     * @throws EE_Error
375
-     */
376
-    public static function prepareConditionsQueryParamsForModels(
377
-        $inputted_query_params_of_this_type,
378
-        EEM_Base $model,
379
-        $requested_version,
380
-        $writing = false
381
-    ) {
382
-        $query_param_for_models = array();
383
-        $valid_operators = $model->valid_operators();
384
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
385
-            $is_gmt_datetime_field = false;
386
-            $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
387
-                $query_param_key
388
-            );
389
-            $field = ModelDataTranslator::deduceFieldFromQueryParam(
390
-                $query_param_sans_stars,
391
-                $model
392
-            );
393
-            // double-check is it a *_gmt field?
394
-            if (! $field instanceof EE_Model_Field_Base
395
-                && ModelDataTranslator::isGmtDateFieldName($query_param_sans_stars)
396
-            ) {
397
-                // yep, take off '_gmt', and find the field
398
-                $query_param_key = ModelDataTranslator::removeGmtFromFieldName($query_param_sans_stars);
399
-                $field = ModelDataTranslator::deduceFieldFromQueryParam(
400
-                    $query_param_key,
401
-                    $model
402
-                );
403
-                $timezone = 'UTC';
404
-                $is_gmt_datetime_field = true;
405
-            } elseif ($field instanceof EE_Datetime_Field) {
406
-                // so it's not a GMT field. Set the timezone on the model to the default
407
-                $timezone = \EEH_DTT_Helper::get_valid_timezone_string();
408
-            } else {
409
-                // just keep using what's already set for the timezone
410
-                $timezone = $model->get_timezone();
411
-            }
412
-            if ($field instanceof EE_Model_Field_Base) {
413
-                if (! $writing && is_array($query_param_value)) {
414
-                    if (! \EEH_Array::is_array_numerically_and_sequentially_indexed($query_param_value)) {
415
-                        if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
416
-                            throw new RestException(
417
-                                'numerically_indexed_array_of_values_only',
418
-                                sprintf(
419
-                                    esc_html__(
420
-                                        'The array provided for the parameter "%1$s" should be numerically indexed.',
421
-                                        'event_espresso'
422
-                                    ),
423
-                                    $query_param_key
424
-                                ),
425
-                                array(
426
-                                    'status' => 400,
427
-                                )
428
-                            );
429
-                        }
430
-                    }
431
-                    // did they specify an operator?
432
-                    if (isset($query_param_value[0])
433
-                        && isset($valid_operators[ $query_param_value[0] ])
434
-                    ) {
435
-                        $op = $query_param_value[0];
436
-                        $translated_value = array($op);
437
-                        if (array_key_exists($op, $model->valid_in_style_operators())
438
-                            && isset($query_param_value[1])
439
-                            && ! isset($query_param_value[2])
440
-                        ) {
441
-                            $translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
442
-                                $field,
443
-                                $query_param_value[1],
444
-                                $requested_version,
445
-                                $timezone
446
-                            );
447
-                        } elseif (array_key_exists($op, $model->valid_between_style_operators())
448
-                                  && isset($query_param_value[1], $query_param_value[2])
449
-                                  && ! isset($query_param_value[3])
450
-                        ) {
451
-                            $translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
452
-                                $field,
453
-                                $query_param_value[1],
454
-                                $requested_version,
455
-                                $timezone
456
-                            );
457
-                            $translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
458
-                                $field,
459
-                                $query_param_value[2],
460
-                                $requested_version,
461
-                                $timezone
462
-                            );
463
-                        } elseif (array_key_exists($op, $model->valid_like_style_operators())
464
-                                  && isset($query_param_value[1])
465
-                                  && ! isset($query_param_value[2])
466
-                        ) {
467
-                            // we want to leave this value mostly-as-is (eg don't force it to be a float
468
-                            // or a boolean or an enum value. Leave it as-is with wildcards etc)
469
-                            // but do verify it at least doesn't have any serialized data
470
-                            ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
471
-                            $translated_value[] = $query_param_value[1];
472
-                        } elseif (array_key_exists($op, $model->valid_null_style_operators())
473
-                                  && ! isset($query_param_value[1])) {
474
-                            // no arguments should have been provided, so don't look for any
475
-                        } elseif (isset($query_param_value[1])
476
-                                  && ! isset($query_param_value[2])
477
-                                  && ! array_key_exists(
478
-                                      $op,
479
-                                      array_merge(
480
-                                          $model->valid_in_style_operators(),
481
-                                          $model->valid_null_style_operators(),
482
-                                          $model->valid_like_style_operators(),
483
-                                          $model->valid_between_style_operators()
484
-                                      )
485
-                                  )
486
-                        ) {
487
-                            // it's a valid operator, but none of the exceptions. Treat it normally.
488
-                            $translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
489
-                                $field,
490
-                                $query_param_value[1],
491
-                                $requested_version,
492
-                                $timezone
493
-                            );
494
-                        } else {
495
-                            // so they provided a valid operator, but wrong number of arguments
496
-                            if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
497
-                                throw new RestException(
498
-                                    'wrong_number_of_arguments',
499
-                                    sprintf(
500
-                                        esc_html__(
501
-                                            'The operator you provided, "%1$s" had the wrong number of arguments',
502
-                                            'event_espresso'
503
-                                        ),
504
-                                        $op
505
-                                    ),
506
-                                    array(
507
-                                        'status' => 400,
508
-                                    )
509
-                                );
510
-                            }
511
-                            $translated_value = null;
512
-                        }
513
-                    } else {
514
-                        // so they didn't provide a valid operator
515
-                        if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
516
-                            throw new RestException(
517
-                                'invalid_operator',
518
-                                sprintf(
519
-                                    esc_html__(
520
-                                        'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
521
-                                        'event_espresso'
522
-                                    ),
523
-                                    $query_param_key,
524
-                                    $query_param_value
525
-                                ),
526
-                                array(
527
-                                    'status' => 400,
528
-                                )
529
-                            );
530
-                        }
531
-                        // if we aren't in debug mode, then just try our best to fulfill the user's request
532
-                        $translated_value = null;
533
-                    }
534
-                } else {
535
-                    $translated_value = ModelDataTranslator::prepareFieldValueFromJson(
536
-                        $field,
537
-                        $query_param_value,
538
-                        $requested_version,
539
-                        $timezone
540
-                    );
541
-                }
542
-                if ((isset($query_param_for_models[ $query_param_key ]) && $is_gmt_datetime_field)
543
-                    || $translated_value === null
544
-                ) {
545
-                    // they have already provided a non-gmt field, ignore the gmt one. That's what WP core
546
-                    // currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
547
-                    // OR we couldn't create a translated value from their input
548
-                    continue;
549
-                }
550
-                $query_param_for_models[ $query_param_key ] = $translated_value;
551
-            } else {
552
-                // so this param doesn't correspond to a field eh?
553
-                if ($writing) {
554
-                    // always tell API clients about invalid parameters when they're creating data. Otherwise,
555
-                    // they are probably going to create invalid data
556
-                    throw new RestException(
557
-                        'invalid_field',
558
-                        sprintf(
559
-                            esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
560
-                            $query_param_key
561
-                        )
562
-                    );
563
-                } else {
564
-                    // so it's not for a field, is it a logic query param key?
565
-                    if (in_array(
566
-                        $query_param_sans_stars,
567
-                        $model->logic_query_param_keys()
568
-                    )) {
569
-                        $query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
570
-                            $query_param_value,
571
-                            $model,
572
-                            $requested_version
573
-                        );
574
-                    } elseif (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
575
-                        // only tell API clients they got it wrong if we're in debug mode
576
-                        // otherwise try our best ot fulfill their request by ignoring this invalid data
577
-                        throw new RestException(
578
-                            'invalid_parameter',
579
-                            sprintf(
580
-                                esc_html__(
581
-                                    'You provided an invalid parameter, with key "%1$s"',
582
-                                    'event_espresso'
583
-                                ),
584
-                                $query_param_sans_stars
585
-                            ),
586
-                            array(
587
-                                'status' => 400,
588
-                            )
589
-                        );
590
-                    }
591
-                }
592
-            }
593
-        }
594
-        return $query_param_for_models;
595
-    }
596
-
597
-
598
-    /**
599
-     * Mostly checks if the last 4 characters are "_gmt", indicating its a
600
-     * gmt date field name
601
-     *
602
-     * @param string $field_name
603
-     * @return boolean
604
-     */
605
-    public static function isGmtDateFieldName($field_name)
606
-    {
607
-        return substr(
608
-            ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name),
609
-            -4,
610
-            4
611
-        ) === '_gmt';
612
-    }
613
-
614
-
615
-    /**
616
-     * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
617
-     *
618
-     * @param string $field_name
619
-     * @return string
620
-     */
621
-    public static function removeGmtFromFieldName($field_name)
622
-    {
623
-        if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
624
-            return $field_name;
625
-        }
626
-        $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
627
-            $field_name
628
-        );
629
-        $query_param_sans_gmt_and_sans_stars = substr(
630
-            $query_param_sans_stars,
631
-            0,
632
-            strrpos(
633
-                $field_name,
634
-                '_gmt'
635
-            )
636
-        );
637
-        return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
638
-    }
639
-
640
-
641
-    /**
642
-     * Takes a field name from the REST API and prepares it for the model querying
643
-     *
644
-     * @param string $field_name
645
-     * @return string
646
-     */
647
-    public static function prepareFieldNameFromJson($field_name)
648
-    {
649
-        if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
650
-            return ModelDataTranslator::removeGmtFromFieldName($field_name);
651
-        }
652
-        return $field_name;
653
-    }
654
-
655
-
656
-    /**
657
-     * Takes array of field names from REST API and prepares for models
658
-     *
659
-     * @param array $field_names
660
-     * @return array of field names (possibly include model prefixes)
661
-     */
662
-    public static function prepareFieldNamesFromJson(array $field_names)
663
-    {
664
-        $new_array = array();
665
-        foreach ($field_names as $key => $field_name) {
666
-            $new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
667
-        }
668
-        return $new_array;
669
-    }
670
-
671
-
672
-    /**
673
-     * Takes array where array keys are field names (possibly with model path prefixes)
674
-     * from the REST API and prepares them for model querying
675
-     *
676
-     * @param array $field_names_as_keys
677
-     * @return array
678
-     */
679
-    public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
680
-    {
681
-        $new_array = array();
682
-        foreach ($field_names_as_keys as $field_name => $value) {
683
-            $new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
684
-        }
685
-        return $new_array;
686
-    }
687
-
688
-
689
-    /**
690
-     * Prepares an array of model query params for use in the REST API
691
-     *
692
-     * @param array    $model_query_params
693
-     * @param EEM_Base $model
694
-     * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
695
-     *                                     REST API
696
-     * @return array which can be passed into the EE4 REST API when querying a model resource
697
-     * @throws EE_Error
698
-     */
699
-    public static function prepareQueryParamsForRestApi(
700
-        array $model_query_params,
701
-        EEM_Base $model,
702
-        $requested_version = null
703
-    ) {
704
-        if ($requested_version === null) {
705
-            $requested_version = \EED_Core_Rest_Api::latest_rest_api_version();
706
-        }
707
-        $rest_query_params = $model_query_params;
708
-        if (isset($model_query_params[0])) {
709
-            $rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
710
-                $model_query_params[0],
711
-                $model,
712
-                $requested_version
713
-            );
714
-            unset($rest_query_params[0]);
715
-        }
716
-        if (isset($model_query_params['having'])) {
717
-            $rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
718
-                $model_query_params['having'],
719
-                $model,
720
-                $requested_version
721
-            );
722
-        }
723
-        return apply_filters(
724
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
725
-            $rest_query_params,
726
-            $model_query_params,
727
-            $model,
728
-            $requested_version
729
-        );
730
-    }
731
-
732
-
733
-    /**
734
-     * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
735
-     *
736
-     * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
737
-     *                                                      passed into EEM_Base::get_all()
738
-     * @param EEM_Base $model
739
-     * @param string   $requested_version                   eg "4.8.36"
740
-     * @return array ready for use in the rest api query params
741
-     * @throws EE_Error
742
-     * @throws ObjectDetectedException if somehow a PHP object were in the query params' values,
743
-     *                                                      (which would be really unusual)
744
-     */
745
-    public static function prepareConditionsQueryParamsForRestApi(
746
-        $inputted_query_params_of_this_type,
747
-        EEM_Base $model,
748
-        $requested_version
749
-    ) {
750
-        $query_param_for_models = array();
751
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
752
-            $field = ModelDataTranslator::deduceFieldFromQueryParam(
753
-                ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
754
-                $model
755
-            );
756
-            if ($field instanceof EE_Model_Field_Base) {
757
-                // did they specify an operator?
758
-                if (is_array($query_param_value)) {
759
-                    $op = $query_param_value[0];
760
-                    $translated_value = array($op);
761
-                    if (isset($query_param_value[1])) {
762
-                        $value = $query_param_value[1];
763
-                        $translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
764
-                            $field,
765
-                            $value,
766
-                            $requested_version
767
-                        );
768
-                    }
769
-                } else {
770
-                    $translated_value = ModelDataTranslator::prepareFieldValueForJson(
771
-                        $field,
772
-                        $query_param_value,
773
-                        $requested_version
774
-                    );
775
-                }
776
-                $query_param_for_models[ $query_param_key ] = $translated_value;
777
-            } else {
778
-                // so it's not for a field, assume it's a logic query param key
779
-                $query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
780
-                    $query_param_value,
781
-                    $model,
782
-                    $requested_version
783
-                );
784
-            }
785
-        }
786
-        return $query_param_for_models;
787
-    }
788
-
789
-
790
-    /**
791
-     * @param $condition_query_param_key
792
-     * @return string
793
-     */
794
-    public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
795
-    {
796
-        $pos_of_star = strpos($condition_query_param_key, '*');
797
-        if ($pos_of_star === false) {
798
-            return $condition_query_param_key;
799
-        } else {
800
-            $condition_query_param_sans_star = substr($condition_query_param_key, 0, $pos_of_star);
801
-            return $condition_query_param_sans_star;
802
-        }
803
-    }
804
-
805
-
806
-    /**
807
-     * Takes the input parameter and finds the model field that it indicates.
808
-     *
809
-     * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
810
-     * @param EEM_Base $model
811
-     * @return EE_Model_Field_Base
812
-     * @throws EE_Error
813
-     */
814
-    public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
815
-    {
816
-        // ok, now proceed with deducing which part is the model's name, and which is the field's name
817
-        // which will help us find the database table and column
818
-        $query_param_parts = explode('.', $query_param_name);
819
-        if (empty($query_param_parts)) {
820
-            throw new EE_Error(
821
-                sprintf(
822
-                    __(
823
-                        '_extract_column_name is empty when trying to extract column and table name from %s',
824
-                        'event_espresso'
825
-                    ),
826
-                    $query_param_name
827
-                )
828
-            );
829
-        }
830
-        $number_of_parts = count($query_param_parts);
831
-        $last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
832
-        if ($number_of_parts === 1) {
833
-            $field_name = $last_query_param_part;
834
-        } else {// $number_of_parts >= 2
835
-            // the last part is the column name, and there are only 2parts. therefore...
836
-            $field_name = $last_query_param_part;
837
-            $model = \EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
838
-        }
839
-        try {
840
-            return $model->field_settings_for($field_name, false);
841
-        } catch (EE_Error $e) {
842
-            return null;
843
-        }
844
-    }
845
-
846
-
847
-    /**
848
-     * Returns true if $data can be easily represented in JSON.
849
-     * Basically, objects and resources can't be represented in JSON easily.
850
-     *
851
-     * @param mixed $data
852
-     * @return bool
853
-     */
854
-    protected static function isRepresentableInJson($data)
855
-    {
856
-        return is_scalar($data)
857
-               || is_array($data)
858
-               || is_null($data);
859
-    }
35
+	/**
36
+	 * We used to use -1 for infinity in the rest api, but that's ambiguous for
37
+	 * fields that COULD contain -1; so we use null
38
+	 */
39
+	const EE_INF_IN_REST = null;
40
+
41
+
42
+	/**
43
+	 * Prepares a possible array of input values from JSON for use by the models
44
+	 *
45
+	 * @param EE_Model_Field_Base $field_obj
46
+	 * @param mixed               $original_value_maybe_array
47
+	 * @param string              $requested_version
48
+	 * @param string              $timezone_string treat values as being in this timezone
49
+	 * @return mixed
50
+	 * @throws RestException
51
+	 */
52
+	public static function prepareFieldValuesFromJson(
53
+		$field_obj,
54
+		$original_value_maybe_array,
55
+		$requested_version,
56
+		$timezone_string = 'UTC'
57
+	) {
58
+		if (is_array($original_value_maybe_array)
59
+			&& ! $field_obj instanceof EE_Serialized_Text_Field
60
+		) {
61
+			$new_value_maybe_array = array();
62
+			foreach ($original_value_maybe_array as $array_key => $array_item) {
63
+				$new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
64
+					$field_obj,
65
+					$array_item,
66
+					$requested_version,
67
+					$timezone_string
68
+				);
69
+			}
70
+		} else {
71
+			$new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
72
+				$field_obj,
73
+				$original_value_maybe_array,
74
+				$requested_version,
75
+				$timezone_string
76
+			);
77
+		}
78
+		return $new_value_maybe_array;
79
+	}
80
+
81
+
82
+	/**
83
+	 * Prepares an array of field values FOR use in JSON/REST API
84
+	 *
85
+	 * @param EE_Model_Field_Base $field_obj
86
+	 * @param mixed               $original_value_maybe_array
87
+	 * @param string              $request_version (eg 4.8.36)
88
+	 * @return array
89
+	 */
90
+	public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
91
+	{
92
+		if (is_array($original_value_maybe_array)) {
93
+			$new_value = array();
94
+			foreach ($original_value_maybe_array as $key => $value) {
95
+				$new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
96
+					$field_obj,
97
+					$value,
98
+					$request_version
99
+				);
100
+			}
101
+		} else {
102
+			$new_value = ModelDataTranslator::prepareFieldValueForJson(
103
+				$field_obj,
104
+				$original_value_maybe_array,
105
+				$request_version
106
+			);
107
+		}
108
+		return $new_value;
109
+	}
110
+
111
+
112
+	/**
113
+	 * Prepares incoming data from the json or $_REQUEST parameters for the models'
114
+	 * "$query_params".
115
+	 *
116
+	 * @param EE_Model_Field_Base $field_obj
117
+	 * @param mixed               $original_value
118
+	 * @param string              $requested_version
119
+	 * @param string              $timezone_string treat values as being in this timezone
120
+	 * @return mixed
121
+	 * @throws RestException
122
+	 * @throws DomainException
123
+	 * @throws EE_Error
124
+	 */
125
+	public static function prepareFieldValueFromJson(
126
+		$field_obj,
127
+		$original_value,
128
+		$requested_version,
129
+		$timezone_string = 'UTC' // UTC
130
+	) {
131
+		// check if they accidentally submitted an error value. If so throw an exception
132
+		if (is_array($original_value)
133
+			&& isset($original_value['error_code'], $original_value['error_message'])) {
134
+			throw new RestException(
135
+				'rest_submitted_error_value',
136
+				sprintf(
137
+					esc_html__(
138
+						'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
139
+						'event_espresso'
140
+					),
141
+					$field_obj->get_name()
142
+				),
143
+				array(
144
+					'status' => 400,
145
+				)
146
+			);
147
+		}
148
+		// double-check for serialized PHP. We never accept serialized PHP. No way Jose.
149
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
150
+		$timezone_string = $timezone_string !== '' ? $timezone_string : get_option('timezone_string', '');
151
+		$new_value = null;
152
+		// walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
153
+		// way Jose.
154
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
155
+		if ($field_obj instanceof EE_Infinite_Integer_Field
156
+			&& in_array($original_value, array(null, ''), true)
157
+		) {
158
+			$new_value = EE_INF;
159
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
160
+			$new_value = rest_parse_date(
161
+				self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
162
+			);
163
+			if ($new_value === false) {
164
+				throw new RestException(
165
+					'invalid_format_for_timestamp',
166
+					sprintf(
167
+						esc_html__(
168
+							'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
169
+							'event_espresso'
170
+						),
171
+						'RFC3339',
172
+						'ISO8601',
173
+						$original_value
174
+					),
175
+					array(
176
+						'status' => 400,
177
+					)
178
+				);
179
+			}
180
+		} else {
181
+			$new_value = $original_value;
182
+		}
183
+		return $new_value;
184
+	}
185
+
186
+
187
+	/**
188
+	 * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
189
+	 * information via details obtained from the host site.
190
+	 *
191
+	 * @param string            $original_timestamp
192
+	 * @param EE_Datetime_Field $datetime_field
193
+	 * @param                   $timezone_string
194
+	 * @return string
195
+	 * @throws DomainException
196
+	 */
197
+	private static function getTimestampWithTimezoneOffset(
198
+		$original_timestamp,
199
+		EE_Datetime_Field $datetime_field,
200
+		$timezone_string
201
+	) {
202
+		// already have timezone information?
203
+		if (preg_match('/Z|(\+|\-)(\d{2}:\d{2})/', $original_timestamp)) {
204
+			// yes, we're ignoring the timezone.
205
+			return $original_timestamp;
206
+		}
207
+		// need to append timezone
208
+		list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
209
+			$datetime_field->get_timezone_offset(
210
+				new \DateTimeZone($timezone_string),
211
+				$original_timestamp
212
+			)
213
+		);
214
+		$offset_string =
215
+			str_pad(
216
+				floor($offset_secs / HOUR_IN_SECONDS),
217
+				2,
218
+				'0',
219
+				STR_PAD_LEFT
220
+			)
221
+			. ':'
222
+			. str_pad(
223
+				($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
224
+				2,
225
+				'0',
226
+				STR_PAD_LEFT
227
+			);
228
+		return $original_timestamp . $offset_sign . $offset_string;
229
+	}
230
+
231
+
232
+	/**
233
+	 * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
234
+	 * think that can happen). If $data is an array, recurses into its keys and values
235
+	 *
236
+	 * @param mixed $data
237
+	 * @throws RestException
238
+	 * @return void
239
+	 */
240
+	public static function throwExceptionIfContainsSerializedData($data)
241
+	{
242
+		if (is_array($data)) {
243
+			foreach ($data as $key => $value) {
244
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
245
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
246
+			}
247
+		} else {
248
+			if (is_serialized($data) || is_object($data)) {
249
+				throw new RestException(
250
+					'serialized_data_submission_prohibited',
251
+					esc_html__(
252
+					// @codingStandardsIgnoreStart
253
+						'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
254
+						// @codingStandardsIgnoreEnd
255
+						'event_espresso'
256
+					)
257
+				);
258
+			}
259
+		}
260
+	}
261
+
262
+
263
+	/**
264
+	 * determines what's going on with them timezone strings
265
+	 *
266
+	 * @param int $timezone_offset
267
+	 * @return array
268
+	 */
269
+	private static function parseTimezoneOffset($timezone_offset)
270
+	{
271
+		$first_char = substr((string) $timezone_offset, 0, 1);
272
+		if ($first_char === '+' || $first_char === '-') {
273
+			$offset_sign = $first_char;
274
+			$offset_secs = substr((string) $timezone_offset, 1);
275
+		} else {
276
+			$offset_sign = '+';
277
+			$offset_secs = $timezone_offset;
278
+		}
279
+		return array($offset_sign, $offset_secs);
280
+	}
281
+
282
+
283
+	/**
284
+	 * Prepares a field's value for display in the API
285
+	 *
286
+	 * @param EE_Model_Field_Base $field_obj
287
+	 * @param mixed               $original_value
288
+	 * @param string              $requested_version
289
+	 * @return mixed
290
+	 */
291
+	public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
292
+	{
293
+		if ($original_value === EE_INF) {
294
+			$new_value = ModelDataTranslator::EE_INF_IN_REST;
295
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
296
+			if (is_string($original_value)) {
297
+				// did they submit a string of a unix timestamp?
298
+				if (is_numeric($original_value)) {
299
+					$datetime_obj = new \DateTime();
300
+					$datetime_obj->setTimestamp((int) $original_value);
301
+				} else {
302
+					// first, check if its a MySQL timestamp in GMT
303
+					$datetime_obj = \DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
304
+				}
305
+				if (! $datetime_obj instanceof \DateTime) {
306
+					// so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
307
+					$datetime_obj = $field_obj->prepare_for_set($original_value);
308
+				}
309
+				$original_value = $datetime_obj;
310
+			}
311
+			if ($original_value instanceof \DateTime) {
312
+				$new_value = $original_value->format('Y-m-d H:i:s');
313
+			} elseif (is_int($original_value) || is_float($original_value)) {
314
+				$new_value = date('Y-m-d H:i:s', $original_value);
315
+			} elseif ($original_value === null || $original_value === '') {
316
+				$new_value = null;
317
+			} else {
318
+				// so it's not a datetime object, unix timestamp (as string or int),
319
+				// MySQL timestamp, or even a string in the field object's format. So no idea what it is
320
+				throw new \EE_Error(
321
+					sprintf(
322
+						esc_html__(
323
+						// @codingStandardsIgnoreStart
324
+							'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
325
+							// @codingStandardsIgnoreEnd
326
+							'event_espresso'
327
+						),
328
+						$original_value,
329
+						$field_obj->get_name(),
330
+						$field_obj->get_model_name(),
331
+						$field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
332
+					)
333
+				);
334
+			}
335
+			$new_value = mysql_to_rfc3339($new_value);
336
+		} else {
337
+			$new_value = $original_value;
338
+		}
339
+		// are we about to send an object? just don't. We have no good way to represent it in JSON.
340
+		// can't just check using is_object() because that missed PHP incomplete objects
341
+		if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
342
+			$new_value = array(
343
+				'error_code'    => 'php_object_not_return',
344
+				'error_message' => esc_html__(
345
+					'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
346
+					'event_espresso'
347
+				),
348
+			);
349
+		}
350
+		return apply_filters(
351
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
352
+			$new_value,
353
+			$field_obj,
354
+			$original_value,
355
+			$requested_version
356
+		);
357
+	}
358
+
359
+
360
+	/**
361
+	 * Prepares condition-query-parameters (like what's in where and having) from
362
+	 * the format expected in the API to use in the models
363
+	 *
364
+	 * @param array    $inputted_query_params_of_this_type
365
+	 * @param EEM_Base $model
366
+	 * @param string   $requested_version
367
+	 * @param boolean  $writing whether this data will be written to the DB, or if we're just building a query.
368
+	 *                          If we're writing to the DB, we don't expect any operators, or any logic query
369
+	 *                          parameters, and we also won't accept serialized data unless the current user has
370
+	 *                          unfiltered_html.
371
+	 * @return array
372
+	 * @throws DomainException
373
+	 * @throws RestException
374
+	 * @throws EE_Error
375
+	 */
376
+	public static function prepareConditionsQueryParamsForModels(
377
+		$inputted_query_params_of_this_type,
378
+		EEM_Base $model,
379
+		$requested_version,
380
+		$writing = false
381
+	) {
382
+		$query_param_for_models = array();
383
+		$valid_operators = $model->valid_operators();
384
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
385
+			$is_gmt_datetime_field = false;
386
+			$query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
387
+				$query_param_key
388
+			);
389
+			$field = ModelDataTranslator::deduceFieldFromQueryParam(
390
+				$query_param_sans_stars,
391
+				$model
392
+			);
393
+			// double-check is it a *_gmt field?
394
+			if (! $field instanceof EE_Model_Field_Base
395
+				&& ModelDataTranslator::isGmtDateFieldName($query_param_sans_stars)
396
+			) {
397
+				// yep, take off '_gmt', and find the field
398
+				$query_param_key = ModelDataTranslator::removeGmtFromFieldName($query_param_sans_stars);
399
+				$field = ModelDataTranslator::deduceFieldFromQueryParam(
400
+					$query_param_key,
401
+					$model
402
+				);
403
+				$timezone = 'UTC';
404
+				$is_gmt_datetime_field = true;
405
+			} elseif ($field instanceof EE_Datetime_Field) {
406
+				// so it's not a GMT field. Set the timezone on the model to the default
407
+				$timezone = \EEH_DTT_Helper::get_valid_timezone_string();
408
+			} else {
409
+				// just keep using what's already set for the timezone
410
+				$timezone = $model->get_timezone();
411
+			}
412
+			if ($field instanceof EE_Model_Field_Base) {
413
+				if (! $writing && is_array($query_param_value)) {
414
+					if (! \EEH_Array::is_array_numerically_and_sequentially_indexed($query_param_value)) {
415
+						if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
416
+							throw new RestException(
417
+								'numerically_indexed_array_of_values_only',
418
+								sprintf(
419
+									esc_html__(
420
+										'The array provided for the parameter "%1$s" should be numerically indexed.',
421
+										'event_espresso'
422
+									),
423
+									$query_param_key
424
+								),
425
+								array(
426
+									'status' => 400,
427
+								)
428
+							);
429
+						}
430
+					}
431
+					// did they specify an operator?
432
+					if (isset($query_param_value[0])
433
+						&& isset($valid_operators[ $query_param_value[0] ])
434
+					) {
435
+						$op = $query_param_value[0];
436
+						$translated_value = array($op);
437
+						if (array_key_exists($op, $model->valid_in_style_operators())
438
+							&& isset($query_param_value[1])
439
+							&& ! isset($query_param_value[2])
440
+						) {
441
+							$translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
442
+								$field,
443
+								$query_param_value[1],
444
+								$requested_version,
445
+								$timezone
446
+							);
447
+						} elseif (array_key_exists($op, $model->valid_between_style_operators())
448
+								  && isset($query_param_value[1], $query_param_value[2])
449
+								  && ! isset($query_param_value[3])
450
+						) {
451
+							$translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
452
+								$field,
453
+								$query_param_value[1],
454
+								$requested_version,
455
+								$timezone
456
+							);
457
+							$translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
458
+								$field,
459
+								$query_param_value[2],
460
+								$requested_version,
461
+								$timezone
462
+							);
463
+						} elseif (array_key_exists($op, $model->valid_like_style_operators())
464
+								  && isset($query_param_value[1])
465
+								  && ! isset($query_param_value[2])
466
+						) {
467
+							// we want to leave this value mostly-as-is (eg don't force it to be a float
468
+							// or a boolean or an enum value. Leave it as-is with wildcards etc)
469
+							// but do verify it at least doesn't have any serialized data
470
+							ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
471
+							$translated_value[] = $query_param_value[1];
472
+						} elseif (array_key_exists($op, $model->valid_null_style_operators())
473
+								  && ! isset($query_param_value[1])) {
474
+							// no arguments should have been provided, so don't look for any
475
+						} elseif (isset($query_param_value[1])
476
+								  && ! isset($query_param_value[2])
477
+								  && ! array_key_exists(
478
+									  $op,
479
+									  array_merge(
480
+										  $model->valid_in_style_operators(),
481
+										  $model->valid_null_style_operators(),
482
+										  $model->valid_like_style_operators(),
483
+										  $model->valid_between_style_operators()
484
+									  )
485
+								  )
486
+						) {
487
+							// it's a valid operator, but none of the exceptions. Treat it normally.
488
+							$translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
489
+								$field,
490
+								$query_param_value[1],
491
+								$requested_version,
492
+								$timezone
493
+							);
494
+						} else {
495
+							// so they provided a valid operator, but wrong number of arguments
496
+							if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
497
+								throw new RestException(
498
+									'wrong_number_of_arguments',
499
+									sprintf(
500
+										esc_html__(
501
+											'The operator you provided, "%1$s" had the wrong number of arguments',
502
+											'event_espresso'
503
+										),
504
+										$op
505
+									),
506
+									array(
507
+										'status' => 400,
508
+									)
509
+								);
510
+							}
511
+							$translated_value = null;
512
+						}
513
+					} else {
514
+						// so they didn't provide a valid operator
515
+						if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
516
+							throw new RestException(
517
+								'invalid_operator',
518
+								sprintf(
519
+									esc_html__(
520
+										'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
521
+										'event_espresso'
522
+									),
523
+									$query_param_key,
524
+									$query_param_value
525
+								),
526
+								array(
527
+									'status' => 400,
528
+								)
529
+							);
530
+						}
531
+						// if we aren't in debug mode, then just try our best to fulfill the user's request
532
+						$translated_value = null;
533
+					}
534
+				} else {
535
+					$translated_value = ModelDataTranslator::prepareFieldValueFromJson(
536
+						$field,
537
+						$query_param_value,
538
+						$requested_version,
539
+						$timezone
540
+					);
541
+				}
542
+				if ((isset($query_param_for_models[ $query_param_key ]) && $is_gmt_datetime_field)
543
+					|| $translated_value === null
544
+				) {
545
+					// they have already provided a non-gmt field, ignore the gmt one. That's what WP core
546
+					// currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
547
+					// OR we couldn't create a translated value from their input
548
+					continue;
549
+				}
550
+				$query_param_for_models[ $query_param_key ] = $translated_value;
551
+			} else {
552
+				// so this param doesn't correspond to a field eh?
553
+				if ($writing) {
554
+					// always tell API clients about invalid parameters when they're creating data. Otherwise,
555
+					// they are probably going to create invalid data
556
+					throw new RestException(
557
+						'invalid_field',
558
+						sprintf(
559
+							esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
560
+							$query_param_key
561
+						)
562
+					);
563
+				} else {
564
+					// so it's not for a field, is it a logic query param key?
565
+					if (in_array(
566
+						$query_param_sans_stars,
567
+						$model->logic_query_param_keys()
568
+					)) {
569
+						$query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
570
+							$query_param_value,
571
+							$model,
572
+							$requested_version
573
+						);
574
+					} elseif (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
575
+						// only tell API clients they got it wrong if we're in debug mode
576
+						// otherwise try our best ot fulfill their request by ignoring this invalid data
577
+						throw new RestException(
578
+							'invalid_parameter',
579
+							sprintf(
580
+								esc_html__(
581
+									'You provided an invalid parameter, with key "%1$s"',
582
+									'event_espresso'
583
+								),
584
+								$query_param_sans_stars
585
+							),
586
+							array(
587
+								'status' => 400,
588
+							)
589
+						);
590
+					}
591
+				}
592
+			}
593
+		}
594
+		return $query_param_for_models;
595
+	}
596
+
597
+
598
+	/**
599
+	 * Mostly checks if the last 4 characters are "_gmt", indicating its a
600
+	 * gmt date field name
601
+	 *
602
+	 * @param string $field_name
603
+	 * @return boolean
604
+	 */
605
+	public static function isGmtDateFieldName($field_name)
606
+	{
607
+		return substr(
608
+			ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name),
609
+			-4,
610
+			4
611
+		) === '_gmt';
612
+	}
613
+
614
+
615
+	/**
616
+	 * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
617
+	 *
618
+	 * @param string $field_name
619
+	 * @return string
620
+	 */
621
+	public static function removeGmtFromFieldName($field_name)
622
+	{
623
+		if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
624
+			return $field_name;
625
+		}
626
+		$query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
627
+			$field_name
628
+		);
629
+		$query_param_sans_gmt_and_sans_stars = substr(
630
+			$query_param_sans_stars,
631
+			0,
632
+			strrpos(
633
+				$field_name,
634
+				'_gmt'
635
+			)
636
+		);
637
+		return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
638
+	}
639
+
640
+
641
+	/**
642
+	 * Takes a field name from the REST API and prepares it for the model querying
643
+	 *
644
+	 * @param string $field_name
645
+	 * @return string
646
+	 */
647
+	public static function prepareFieldNameFromJson($field_name)
648
+	{
649
+		if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
650
+			return ModelDataTranslator::removeGmtFromFieldName($field_name);
651
+		}
652
+		return $field_name;
653
+	}
654
+
655
+
656
+	/**
657
+	 * Takes array of field names from REST API and prepares for models
658
+	 *
659
+	 * @param array $field_names
660
+	 * @return array of field names (possibly include model prefixes)
661
+	 */
662
+	public static function prepareFieldNamesFromJson(array $field_names)
663
+	{
664
+		$new_array = array();
665
+		foreach ($field_names as $key => $field_name) {
666
+			$new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
667
+		}
668
+		return $new_array;
669
+	}
670
+
671
+
672
+	/**
673
+	 * Takes array where array keys are field names (possibly with model path prefixes)
674
+	 * from the REST API and prepares them for model querying
675
+	 *
676
+	 * @param array $field_names_as_keys
677
+	 * @return array
678
+	 */
679
+	public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
680
+	{
681
+		$new_array = array();
682
+		foreach ($field_names_as_keys as $field_name => $value) {
683
+			$new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
684
+		}
685
+		return $new_array;
686
+	}
687
+
688
+
689
+	/**
690
+	 * Prepares an array of model query params for use in the REST API
691
+	 *
692
+	 * @param array    $model_query_params
693
+	 * @param EEM_Base $model
694
+	 * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
695
+	 *                                     REST API
696
+	 * @return array which can be passed into the EE4 REST API when querying a model resource
697
+	 * @throws EE_Error
698
+	 */
699
+	public static function prepareQueryParamsForRestApi(
700
+		array $model_query_params,
701
+		EEM_Base $model,
702
+		$requested_version = null
703
+	) {
704
+		if ($requested_version === null) {
705
+			$requested_version = \EED_Core_Rest_Api::latest_rest_api_version();
706
+		}
707
+		$rest_query_params = $model_query_params;
708
+		if (isset($model_query_params[0])) {
709
+			$rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
710
+				$model_query_params[0],
711
+				$model,
712
+				$requested_version
713
+			);
714
+			unset($rest_query_params[0]);
715
+		}
716
+		if (isset($model_query_params['having'])) {
717
+			$rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
718
+				$model_query_params['having'],
719
+				$model,
720
+				$requested_version
721
+			);
722
+		}
723
+		return apply_filters(
724
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
725
+			$rest_query_params,
726
+			$model_query_params,
727
+			$model,
728
+			$requested_version
729
+		);
730
+	}
731
+
732
+
733
+	/**
734
+	 * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
735
+	 *
736
+	 * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
737
+	 *                                                      passed into EEM_Base::get_all()
738
+	 * @param EEM_Base $model
739
+	 * @param string   $requested_version                   eg "4.8.36"
740
+	 * @return array ready for use in the rest api query params
741
+	 * @throws EE_Error
742
+	 * @throws ObjectDetectedException if somehow a PHP object were in the query params' values,
743
+	 *                                                      (which would be really unusual)
744
+	 */
745
+	public static function prepareConditionsQueryParamsForRestApi(
746
+		$inputted_query_params_of_this_type,
747
+		EEM_Base $model,
748
+		$requested_version
749
+	) {
750
+		$query_param_for_models = array();
751
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
752
+			$field = ModelDataTranslator::deduceFieldFromQueryParam(
753
+				ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
754
+				$model
755
+			);
756
+			if ($field instanceof EE_Model_Field_Base) {
757
+				// did they specify an operator?
758
+				if (is_array($query_param_value)) {
759
+					$op = $query_param_value[0];
760
+					$translated_value = array($op);
761
+					if (isset($query_param_value[1])) {
762
+						$value = $query_param_value[1];
763
+						$translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
764
+							$field,
765
+							$value,
766
+							$requested_version
767
+						);
768
+					}
769
+				} else {
770
+					$translated_value = ModelDataTranslator::prepareFieldValueForJson(
771
+						$field,
772
+						$query_param_value,
773
+						$requested_version
774
+					);
775
+				}
776
+				$query_param_for_models[ $query_param_key ] = $translated_value;
777
+			} else {
778
+				// so it's not for a field, assume it's a logic query param key
779
+				$query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
780
+					$query_param_value,
781
+					$model,
782
+					$requested_version
783
+				);
784
+			}
785
+		}
786
+		return $query_param_for_models;
787
+	}
788
+
789
+
790
+	/**
791
+	 * @param $condition_query_param_key
792
+	 * @return string
793
+	 */
794
+	public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
795
+	{
796
+		$pos_of_star = strpos($condition_query_param_key, '*');
797
+		if ($pos_of_star === false) {
798
+			return $condition_query_param_key;
799
+		} else {
800
+			$condition_query_param_sans_star = substr($condition_query_param_key, 0, $pos_of_star);
801
+			return $condition_query_param_sans_star;
802
+		}
803
+	}
804
+
805
+
806
+	/**
807
+	 * Takes the input parameter and finds the model field that it indicates.
808
+	 *
809
+	 * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
810
+	 * @param EEM_Base $model
811
+	 * @return EE_Model_Field_Base
812
+	 * @throws EE_Error
813
+	 */
814
+	public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
815
+	{
816
+		// ok, now proceed with deducing which part is the model's name, and which is the field's name
817
+		// which will help us find the database table and column
818
+		$query_param_parts = explode('.', $query_param_name);
819
+		if (empty($query_param_parts)) {
820
+			throw new EE_Error(
821
+				sprintf(
822
+					__(
823
+						'_extract_column_name is empty when trying to extract column and table name from %s',
824
+						'event_espresso'
825
+					),
826
+					$query_param_name
827
+				)
828
+			);
829
+		}
830
+		$number_of_parts = count($query_param_parts);
831
+		$last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
832
+		if ($number_of_parts === 1) {
833
+			$field_name = $last_query_param_part;
834
+		} else {// $number_of_parts >= 2
835
+			// the last part is the column name, and there are only 2parts. therefore...
836
+			$field_name = $last_query_param_part;
837
+			$model = \EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
838
+		}
839
+		try {
840
+			return $model->field_settings_for($field_name, false);
841
+		} catch (EE_Error $e) {
842
+			return null;
843
+		}
844
+	}
845
+
846
+
847
+	/**
848
+	 * Returns true if $data can be easily represented in JSON.
849
+	 * Basically, objects and resources can't be represented in JSON easily.
850
+	 *
851
+	 * @param mixed $data
852
+	 * @return bool
853
+	 */
854
+	protected static function isRepresentableInJson($data)
855
+	{
856
+		return is_scalar($data)
857
+			   || is_array($data)
858
+			   || is_null($data);
859
+	}
860 860
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
         ) {
61 61
             $new_value_maybe_array = array();
62 62
             foreach ($original_value_maybe_array as $array_key => $array_item) {
63
-                $new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
63
+                $new_value_maybe_array[$array_key] = ModelDataTranslator::prepareFieldValueFromJson(
64 64
                     $field_obj,
65 65
                     $array_item,
66 66
                     $requested_version,
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
         if (is_array($original_value_maybe_array)) {
93 93
             $new_value = array();
94 94
             foreach ($original_value_maybe_array as $key => $value) {
95
-                $new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
95
+                $new_value[$key] = ModelDataTranslator::prepareFieldValuesForJson(
96 96
                     $field_obj,
97 97
                     $value,
98 98
                     $request_version
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
                 '0',
226 226
                 STR_PAD_LEFT
227 227
             );
228
-        return $original_timestamp . $offset_sign . $offset_string;
228
+        return $original_timestamp.$offset_sign.$offset_string;
229 229
     }
230 230
 
231 231
 
@@ -302,7 +302,7 @@  discard block
 block discarded – undo
302 302
                     // first, check if its a MySQL timestamp in GMT
303 303
                     $datetime_obj = \DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
304 304
                 }
305
-                if (! $datetime_obj instanceof \DateTime) {
305
+                if ( ! $datetime_obj instanceof \DateTime) {
306 306
                     // so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
307 307
                     $datetime_obj = $field_obj->prepare_for_set($original_value);
308 308
                 }
@@ -328,7 +328,7 @@  discard block
 block discarded – undo
328 328
                         $original_value,
329 329
                         $field_obj->get_name(),
330 330
                         $field_obj->get_model_name(),
331
-                        $field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
331
+                        $field_obj->get_time_format().' '.$field_obj->get_time_format()
332 332
                     )
333 333
                 );
334 334
             }
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
         }
339 339
         // are we about to send an object? just don't. We have no good way to represent it in JSON.
340 340
         // can't just check using is_object() because that missed PHP incomplete objects
341
-        if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
341
+        if ( ! ModelDataTranslator::isRepresentableInJson($new_value)) {
342 342
             $new_value = array(
343 343
                 'error_code'    => 'php_object_not_return',
344 344
                 'error_message' => esc_html__(
@@ -391,7 +391,7 @@  discard block
 block discarded – undo
391 391
                 $model
392 392
             );
393 393
             // double-check is it a *_gmt field?
394
-            if (! $field instanceof EE_Model_Field_Base
394
+            if ( ! $field instanceof EE_Model_Field_Base
395 395
                 && ModelDataTranslator::isGmtDateFieldName($query_param_sans_stars)
396 396
             ) {
397 397
                 // yep, take off '_gmt', and find the field
@@ -410,8 +410,8 @@  discard block
 block discarded – undo
410 410
                 $timezone = $model->get_timezone();
411 411
             }
412 412
             if ($field instanceof EE_Model_Field_Base) {
413
-                if (! $writing && is_array($query_param_value)) {
414
-                    if (! \EEH_Array::is_array_numerically_and_sequentially_indexed($query_param_value)) {
413
+                if ( ! $writing && is_array($query_param_value)) {
414
+                    if ( ! \EEH_Array::is_array_numerically_and_sequentially_indexed($query_param_value)) {
415 415
                         if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
416 416
                             throw new RestException(
417 417
                                 'numerically_indexed_array_of_values_only',
@@ -430,7 +430,7 @@  discard block
 block discarded – undo
430 430
                     }
431 431
                     // did they specify an operator?
432 432
                     if (isset($query_param_value[0])
433
-                        && isset($valid_operators[ $query_param_value[0] ])
433
+                        && isset($valid_operators[$query_param_value[0]])
434 434
                     ) {
435 435
                         $op = $query_param_value[0];
436 436
                         $translated_value = array($op);
@@ -539,7 +539,7 @@  discard block
 block discarded – undo
539 539
                         $timezone
540 540
                     );
541 541
                 }
542
-                if ((isset($query_param_for_models[ $query_param_key ]) && $is_gmt_datetime_field)
542
+                if ((isset($query_param_for_models[$query_param_key]) && $is_gmt_datetime_field)
543 543
                     || $translated_value === null
544 544
                 ) {
545 545
                     // they have already provided a non-gmt field, ignore the gmt one. That's what WP core
@@ -547,7 +547,7 @@  discard block
 block discarded – undo
547 547
                     // OR we couldn't create a translated value from their input
548 548
                     continue;
549 549
                 }
550
-                $query_param_for_models[ $query_param_key ] = $translated_value;
550
+                $query_param_for_models[$query_param_key] = $translated_value;
551 551
             } else {
552 552
                 // so this param doesn't correspond to a field eh?
553 553
                 if ($writing) {
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
                         $query_param_sans_stars,
567 567
                         $model->logic_query_param_keys()
568 568
                     )) {
569
-                        $query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
569
+                        $query_param_for_models[$query_param_key] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
570 570
                             $query_param_value,
571 571
                             $model,
572 572
                             $requested_version
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
      */
621 621
     public static function removeGmtFromFieldName($field_name)
622 622
     {
623
-        if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
623
+        if ( ! ModelDataTranslator::isGmtDateFieldName($field_name)) {
624 624
             return $field_name;
625 625
         }
626 626
         $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
@@ -663,7 +663,7 @@  discard block
 block discarded – undo
663 663
     {
664 664
         $new_array = array();
665 665
         foreach ($field_names as $key => $field_name) {
666
-            $new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
666
+            $new_array[$key] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
667 667
         }
668 668
         return $new_array;
669 669
     }
@@ -680,7 +680,7 @@  discard block
 block discarded – undo
680 680
     {
681 681
         $new_array = array();
682 682
         foreach ($field_names_as_keys as $field_name => $value) {
683
-            $new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
683
+            $new_array[ModelDataTranslator::prepareFieldNameFromJson($field_name)] = $value;
684 684
         }
685 685
         return $new_array;
686 686
     }
@@ -773,10 +773,10 @@  discard block
 block discarded – undo
773 773
                         $requested_version
774 774
                     );
775 775
                 }
776
-                $query_param_for_models[ $query_param_key ] = $translated_value;
776
+                $query_param_for_models[$query_param_key] = $translated_value;
777 777
             } else {
778 778
                 // so it's not for a field, assume it's a logic query param key
779
-                $query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
779
+                $query_param_for_models[$query_param_key] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
780 780
                     $query_param_value,
781 781
                     $model,
782 782
                     $requested_version
@@ -828,13 +828,13 @@  discard block
 block discarded – undo
828 828
             );
829 829
         }
830 830
         $number_of_parts = count($query_param_parts);
831
-        $last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
831
+        $last_query_param_part = $query_param_parts[count($query_param_parts) - 1];
832 832
         if ($number_of_parts === 1) {
833 833
             $field_name = $last_query_param_part;
834 834
         } else {// $number_of_parts >= 2
835 835
             // the last part is the column name, and there are only 2parts. therefore...
836 836
             $field_name = $last_query_param_part;
837
-            $model = \EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
837
+            $model = \EE_Registry::instance()->load_model($query_param_parts[$number_of_parts - 2]);
838 838
         }
839 839
         try {
840 840
             return $model->field_settings_for($field_name, false);
Please login to merge, or discard this patch.
core/libraries/rest_api/ModelVersionInfo.php 2 patches
Indentation   +436 added lines, -436 removed lines patch added patch discarded remove patch
@@ -21,440 +21,440 @@
 block discarded – undo
21 21
 class ModelVersionInfo
22 22
 {
23 23
 
24
-    /**
25
-     * Constant used in the $_model_changes array to indicate that a model
26
-     * was completely new in this version
27
-     */
28
-    const MODEL_ADDED = 'model_added_in_this_version';
29
-
30
-    /**
31
-     * Top-level keys are versions (major and minor version numbers, eg "4.6")
32
-     * next-level keys are model names (eg "Event") that underwent some change in that version
33
-     * and the value is either Model_Version_Info::model_added (indicating the model is completely NEW in this version),
34
-     * or it's an array where the values are model field names,
35
-     * or API resource properties (ie, non-model fields that appear in REST API results)
36
-     * If a version is missing then we don't know anything about what changes it introduced from the previous version
37
-     *
38
-     * @var array
39
-     */
40
-    protected $model_changes = array();
41
-
42
-    /**
43
-     * top-level keys are version numbers,
44
-     * next-level keys are model CLASSNAMES (even parent classnames),
45
-     * and next-level keys are extra resource properties to attach to those models' resources,
46
-     * and next-level key-value pairs, where the keys are:
47
-     * 'raw', 'type', 'nullable', 'table_alias', 'table_column',  'always_available'
48
-     *
49
-     * @var array
50
-     */
51
-    protected $resource_changes = array();
52
-
53
-    /**
54
-     * @var string indicating what version of the API was requested
55
-     * (eg although core might be at version 4.8.11, they may have sent a request
56
-     * for 4.6)
57
-     */
58
-    protected $requested_version = null;
59
-
60
-    /**
61
-     * Keys are model names, values are their classnames.
62
-     * We cache this so we only need to calculate this once per request
63
-     *
64
-     * @var array
65
-     */
66
-    protected $cached_models_for_requested_version = null;
67
-
68
-    /**
69
-     * @var array
70
-     */
71
-    protected $cached_model_changes_between_requested_version_and_current = null;
72
-
73
-    /**
74
-     * @var array
75
-     */
76
-    protected $cached_resource_changes_between_requested_version_and_current = null;
77
-
78
-    /**
79
-     * 2d array where top-level keys are model names, 2nd-level keys are field names
80
-     * and values are the actual field objects
81
-     *
82
-     * @var array
83
-     */
84
-    protected $cached_fields_on_models = array();
85
-
86
-
87
-    /**
88
-     * Model_Version_Info constructor.
89
-     *
90
-     * @param string $requested_version
91
-     */
92
-    public function __construct($requested_version)
93
-    {
94
-        $this->requested_version = (string) $requested_version;
95
-        $this->model_changes = array(
96
-            '4.8.29' => array(
97
-                // first version where the REST API is in EE core, so no need
98
-                // to specify how its different from the previous
99
-            ),
100
-        );
101
-        // setup data for "extra" fields added onto resources which don't actually exist on models
102
-        $this->resource_changes = apply_filters(
103
-            'FHEE__Model_Version_Info___construct__extra_resource_properties_for_models',
104
-            array()
105
-        );
106
-        $defaults = array(
107
-            'raw'              => false,
108
-            'type'             => 'N/A',
109
-            'nullable'         => true,
110
-            'table_alias'      => 'N/A',
111
-            'table_column'     => 'N/A',
112
-            'always_available' => true,
113
-        );
114
-        foreach ($this->resource_changes as $version => $model_classnames) {
115
-            foreach ($model_classnames as $model_classname => $extra_fields) {
116
-                foreach ($extra_fields as $fieldname => $field_data) {
117
-                    $this->resource_changes[ $model_classname ][ $fieldname ]['name'] = $fieldname;
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;
121
-                        }
122
-                    }
123
-                }
124
-            }
125
-        }
126
-    }
127
-
128
-
129
-    /**
130
-     * Returns a slice of Model_Version_Info::model_changes()'s array
131
-     * indicating exactly what changes happened between the current core version,
132
-     * and the version requested
133
-     *
134
-     * @return array
135
-     */
136
-    public function modelChangesBetweenRequestedVersionAndCurrent()
137
-    {
138
-        if ($this->cached_model_changes_between_requested_version_and_current === null) {
139
-            $model_changes = array();
140
-            foreach ($this->modelChanges() as $version => $models_changed_in_version) {
141
-                if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
142
-                    $model_changes[ $version ] = $models_changed_in_version;
143
-                }
144
-            }
145
-            $this->cached_model_changes_between_requested_version_and_current = $model_changes;
146
-        }
147
-        return $this->cached_model_changes_between_requested_version_and_current;
148
-    }
149
-
150
-
151
-    /**
152
-     * Returns a slice of Model_Version_Info::model_changes()'s array
153
-     * indicating exactly what changes happened between the current core version,
154
-     * and the version requested
155
-     *
156
-     * @return array
157
-     */
158
-    public function resourceChangesBetweenRequestedVersionAndCurrent()
159
-    {
160
-        if ($this->cached_resource_changes_between_requested_version_and_current === null) {
161
-            $resource_changes = array();
162
-            foreach ($this->resourceChanges() as $version => $model_classnames) {
163
-                if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
164
-                    $resource_changes[ $version ] = $model_classnames;
165
-                }
166
-            }
167
-            $this->cached_resource_changes_between_requested_version_and_current = $resource_changes;
168
-        }
169
-        return $this->cached_resource_changes_between_requested_version_and_current;
170
-    }
171
-
172
-
173
-    /**
174
-     * If a request was sent to 'wp-json/ee/v4.7/events' this would be '4.7'
175
-     *
176
-     * @return string like '4.6'
177
-     */
178
-    public function requestedVersion()
179
-    {
180
-        return $this->requested_version;
181
-    }
182
-
183
-
184
-    /**
185
-     * Returns an array describing how the models have changed in each version of core
186
-     * that supports the API (starting at 4.6)
187
-     * Top-level keys are versions (major and minor version numbers, eg "4.6")
188
-     * next-level keys are model names (eg "Event") that underwent some change in that version
189
-     * and the value is either NULL (indicating the model is completely NEW in this version),
190
-     * or it's an array where fields are value names.
191
-     * If a version is missing then we don't know anything about what changes it introduced from the previous version
192
-     *
193
-     * @return array
194
-     */
195
-    public function modelChanges()
196
-    {
197
-        return $this->model_changes;
198
-    }
199
-
200
-
201
-    /**
202
-     * Takes into account the requested version, and the current version, and
203
-     * what changed between the two, and tries to return.
204
-     * Analogous to EE_Registry::instance()->non_abstract_db_models
205
-     *
206
-     * @return array keys are model names, values are their classname
207
-     */
208
-    public function modelsForRequestedVersion()
209
-    {
210
-        if ($this->cached_models_for_requested_version === null) {
211
-            $all_models_in_current_version = EE_Registry::instance()->non_abstract_db_models;
212
-            foreach ($this->modelChangesBetweenRequestedVersionAndCurrent() as $version => $models_changed) {
213
-                foreach ($models_changed as $model_name => $new_indicator_or_fields_added) {
214
-                    if ($new_indicator_or_fields_added === ModelVersionInfo::MODEL_ADDED) {
215
-                        unset($all_models_in_current_version[ $model_name ]);
216
-                    }
217
-                }
218
-            }
219
-            $this->cached_models_for_requested_version = apply_filters(
220
-                'FHEE__EventEspresso_core_libraries_rest_api__models_for_requested_version',
221
-                $all_models_in_current_version,
222
-                $this
223
-            );
224
-        }
225
-        return $this->cached_models_for_requested_version;
226
-    }
227
-
228
-
229
-    /**
230
-     * Determines if this is a valid model name in the requested version.
231
-     * Similar to EE_Registry::instance()->is_model_name(), but takes the requested
232
-     * version's models into account
233
-     *
234
-     * @param string $model_name eg 'Event'
235
-     * @return boolean
236
-     */
237
-    public function isModelNameInThisVersion($model_name)
238
-    {
239
-        $model_names = $this->modelsForRequestedVersion();
240
-        if (isset($model_names[ $model_name ])) {
241
-            return true;
242
-        } else {
243
-            return false;
244
-        }
245
-    }
246
-
247
-
248
-    /**
249
-     * Wrapper for EE_Registry::instance()->load_model(), but takes the requested
250
-     * version's models into account
251
-     *
252
-     * @param string $model_name
253
-     * @return \EEM_Base
254
-     * @throws \EE_Error
255
-     */
256
-    public function loadModel($model_name)
257
-    {
258
-        if ($this->isModelNameInThisVersion($model_name)) {
259
-            return EE_Registry::instance()->load_model($model_name);
260
-        } else {
261
-            throw new \EE_Error(
262
-                sprintf(
263
-                    __(
264
-                        'Cannot load model "%1$s" because it does not exist in version %2$s of Event Espresso',
265
-                        'event_espresso'
266
-                    ),
267
-                    $model_name,
268
-                    $this->requestedVersion()
269
-                )
270
-            );
271
-        }
272
-    }
273
-
274
-
275
-    /**
276
-     * Gets all the fields that should exist on this model right now
277
-     *
278
-     * @param \EEM_Base $model
279
-     * @return array|\EE_Model_Field_Base[]
280
-     */
281
-    public function fieldsOnModelInThisVersion($model)
282
-    {
283
-        if (! isset($this->cached_fields_on_models[ $model->get_this_model_name() ])) {
284
-            // get all model changes between the requested version and current core version
285
-            $changes = $this->modelChangesBetweenRequestedVersionAndCurrent();
286
-            // fetch all fields currently on this model
287
-            $current_fields = $model->field_settings();
288
-            // remove all fields that have been added since
289
-            foreach ($changes as $version => $changes_in_version) {
290
-                if (isset($changes_in_version[ $model->get_this_model_name() ])
291
-                    && $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
292
-                ) {
293
-                    $current_fields = array_diff_key(
294
-                        $current_fields,
295
-                        array_flip($changes_in_version[ $model->get_this_model_name() ])
296
-                    );
297
-                }
298
-            }
299
-            $this->cached_fields_on_models = $current_fields;
300
-        }
301
-        return $this->cached_fields_on_models;
302
-    }
303
-
304
-
305
-    /**
306
-     * Determines if $object is of one of the classes of $classes. Similar to
307
-     * in_array(), except this checks if $object is a subclass of the classnames provided
308
-     * in $classnames
309
-     *
310
-     * @param object $object
311
-     * @param array  $classnames
312
-     * @return boolean
313
-     */
314
-    public function isSubclassOfOne($object, $classnames)
315
-    {
316
-        foreach ($classnames as $classname) {
317
-            if (is_a($object, $classname)) {
318
-                return true;
319
-            }
320
-        }
321
-        return false;
322
-    }
323
-
324
-
325
-    /**
326
-     * Returns the list of model field classes that that the API basically ignores
327
-     *
328
-     * @return array
329
-     */
330
-    public function fieldsIgnored()
331
-    {
332
-        return apply_filters(
333
-            'FHEE__Controller_Model_Read_fields_ignored',
334
-            array('EE_Foreign_Key_Field_Base', 'EE_Any_Foreign_Model_Name_Field')
335
-        );
336
-    }
337
-
338
-
339
-    /**
340
-     * If this field one that should be ignored by the API?
341
-     *
342
-     * @param EE_Model_Field_Base
343
-     * @return boolean
344
-     */
345
-    public function fieldIsIgnored($field_obj)
346
-    {
347
-        return $this->isSubclassOfOne($field_obj, $this->fieldsIgnored());
348
-    }
349
-
350
-
351
-    /**
352
-     * Returns the list of model field classes that have a "raw" and non-raw formats.
353
-     * Normally the "raw" versions are only accessible to those who can edit them.
354
-     *
355
-     * @return array an array of EE_Model_Field_Base child classnames
356
-     */
357
-    public function fieldsThatHaveRenderedFormat()
358
-    {
359
-        return apply_filters(
360
-            'FHEE__Controller_Model_Read__fields_raw',
361
-            array('EE_Post_Content_Field', 'EE_Full_HTML_Field')
362
-        );
363
-    }
364
-
365
-
366
-    /**
367
-     * If this field one that has a raw format
368
-     *
369
-     * @param EE_Model_Field_Base
370
-     * @return boolean
371
-     */
372
-    public function fieldHasRenderedFormat($field_obj)
373
-    {
374
-        return $this->isSubclassOfOne($field_obj, $this->fieldsThatHaveRenderedFormat());
375
-    }
376
-
377
-
378
-    /**
379
-     * Returns the list of model field classes that have a "_pretty" and non-pretty versions.
380
-     * The pretty version of the field is NOT query-able or editable, but requires no extra permissions
381
-     * to view
382
-     *
383
-     * @return array an array of EE_Model_Field_Base child classnames
384
-     */
385
-    public function fieldsThatHavePrettyFormat()
386
-    {
387
-        return apply_filters(
388
-            'FHEE__Controller_Model_Read__fields_pretty',
389
-            array('EE_Enum_Integer_Field', 'EE_Enum_Text_Field', 'EE_Money_Field')
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * If this field one that has a pretty equivalent
396
-     *
397
-     * @param EE_Model_Field_Base
398
-     * @return boolean
399
-     */
400
-    public function fieldHasPrettyFormat($field_obj)
401
-    {
402
-        return $this->isSubclassOfOne($field_obj, $this->fieldsThatHavePrettyFormat());
403
-    }
404
-
405
-
406
-    /**
407
-     * Returns an array describing what extra API resource properties have been added through the versions
408
-     *
409
-     * @return array @see $this->_extra_resource_properties_for_models
410
-     */
411
-    public function resourceChanges()
412
-    {
413
-        return $this->resource_changes;
414
-    }
415
-
416
-
417
-    /**
418
-     * Returns an array where keys are extra resource properties in this version of the API,
419
-     * and values are key-value pairs describing the new properties. @see Model_Version::_resource_changes
420
-     *
421
-     * @param \EEM_Base $model
422
-     * @return array
423
-     */
424
-    public function extraResourcePropertiesForModel($model)
425
-    {
426
-        $extra_properties = array();
427
-        foreach ($this->resourceChangesBetweenRequestedVersionAndCurrent() as $version => $model_classnames) {
428
-            foreach ($model_classnames as $model_classname => $properties_added_in_this_version) {
429
-                if (is_subclass_of($model, $model_classname)) {
430
-                    $extra_properties = array_merge($extra_properties, $properties_added_in_this_version);
431
-                }
432
-            }
433
-        }
434
-        return $extra_properties;
435
-    }
436
-
437
-
438
-    /**
439
-     * Gets all the related models for the specified model. It's good to use this
440
-     * in case this model didn't exist for this version or something
441
-     *
442
-     * @param \EEM_Base $model
443
-     * @return \EE_Model_Relation_Base[]
444
-     */
445
-    public function relationSettings(\EEM_Base $model)
446
-    {
447
-        $relations = array();
448
-        foreach ($model->relation_settings() as $relation_name => $relation_obj) {
449
-            if ($this->isModelNameInThisVersion($relation_name)) {
450
-                $relations[ $relation_name ] = $relation_obj;
451
-            }
452
-        }
453
-        // filter the results, but use the old filter name
454
-        return apply_filters(
455
-            'FHEE__Read__create_entity_from_wpdb_result__related_models_to_include',
456
-            $relations,
457
-            $model
458
-        );
459
-    }
24
+	/**
25
+	 * Constant used in the $_model_changes array to indicate that a model
26
+	 * was completely new in this version
27
+	 */
28
+	const MODEL_ADDED = 'model_added_in_this_version';
29
+
30
+	/**
31
+	 * Top-level keys are versions (major and minor version numbers, eg "4.6")
32
+	 * next-level keys are model names (eg "Event") that underwent some change in that version
33
+	 * and the value is either Model_Version_Info::model_added (indicating the model is completely NEW in this version),
34
+	 * or it's an array where the values are model field names,
35
+	 * or API resource properties (ie, non-model fields that appear in REST API results)
36
+	 * If a version is missing then we don't know anything about what changes it introduced from the previous version
37
+	 *
38
+	 * @var array
39
+	 */
40
+	protected $model_changes = array();
41
+
42
+	/**
43
+	 * top-level keys are version numbers,
44
+	 * next-level keys are model CLASSNAMES (even parent classnames),
45
+	 * and next-level keys are extra resource properties to attach to those models' resources,
46
+	 * and next-level key-value pairs, where the keys are:
47
+	 * 'raw', 'type', 'nullable', 'table_alias', 'table_column',  'always_available'
48
+	 *
49
+	 * @var array
50
+	 */
51
+	protected $resource_changes = array();
52
+
53
+	/**
54
+	 * @var string indicating what version of the API was requested
55
+	 * (eg although core might be at version 4.8.11, they may have sent a request
56
+	 * for 4.6)
57
+	 */
58
+	protected $requested_version = null;
59
+
60
+	/**
61
+	 * Keys are model names, values are their classnames.
62
+	 * We cache this so we only need to calculate this once per request
63
+	 *
64
+	 * @var array
65
+	 */
66
+	protected $cached_models_for_requested_version = null;
67
+
68
+	/**
69
+	 * @var array
70
+	 */
71
+	protected $cached_model_changes_between_requested_version_and_current = null;
72
+
73
+	/**
74
+	 * @var array
75
+	 */
76
+	protected $cached_resource_changes_between_requested_version_and_current = null;
77
+
78
+	/**
79
+	 * 2d array where top-level keys are model names, 2nd-level keys are field names
80
+	 * and values are the actual field objects
81
+	 *
82
+	 * @var array
83
+	 */
84
+	protected $cached_fields_on_models = array();
85
+
86
+
87
+	/**
88
+	 * Model_Version_Info constructor.
89
+	 *
90
+	 * @param string $requested_version
91
+	 */
92
+	public function __construct($requested_version)
93
+	{
94
+		$this->requested_version = (string) $requested_version;
95
+		$this->model_changes = array(
96
+			'4.8.29' => array(
97
+				// first version where the REST API is in EE core, so no need
98
+				// to specify how its different from the previous
99
+			),
100
+		);
101
+		// setup data for "extra" fields added onto resources which don't actually exist on models
102
+		$this->resource_changes = apply_filters(
103
+			'FHEE__Model_Version_Info___construct__extra_resource_properties_for_models',
104
+			array()
105
+		);
106
+		$defaults = array(
107
+			'raw'              => false,
108
+			'type'             => 'N/A',
109
+			'nullable'         => true,
110
+			'table_alias'      => 'N/A',
111
+			'table_column'     => 'N/A',
112
+			'always_available' => true,
113
+		);
114
+		foreach ($this->resource_changes as $version => $model_classnames) {
115
+			foreach ($model_classnames as $model_classname => $extra_fields) {
116
+				foreach ($extra_fields as $fieldname => $field_data) {
117
+					$this->resource_changes[ $model_classname ][ $fieldname ]['name'] = $fieldname;
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;
121
+						}
122
+					}
123
+				}
124
+			}
125
+		}
126
+	}
127
+
128
+
129
+	/**
130
+	 * Returns a slice of Model_Version_Info::model_changes()'s array
131
+	 * indicating exactly what changes happened between the current core version,
132
+	 * and the version requested
133
+	 *
134
+	 * @return array
135
+	 */
136
+	public function modelChangesBetweenRequestedVersionAndCurrent()
137
+	{
138
+		if ($this->cached_model_changes_between_requested_version_and_current === null) {
139
+			$model_changes = array();
140
+			foreach ($this->modelChanges() as $version => $models_changed_in_version) {
141
+				if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
142
+					$model_changes[ $version ] = $models_changed_in_version;
143
+				}
144
+			}
145
+			$this->cached_model_changes_between_requested_version_and_current = $model_changes;
146
+		}
147
+		return $this->cached_model_changes_between_requested_version_and_current;
148
+	}
149
+
150
+
151
+	/**
152
+	 * Returns a slice of Model_Version_Info::model_changes()'s array
153
+	 * indicating exactly what changes happened between the current core version,
154
+	 * and the version requested
155
+	 *
156
+	 * @return array
157
+	 */
158
+	public function resourceChangesBetweenRequestedVersionAndCurrent()
159
+	{
160
+		if ($this->cached_resource_changes_between_requested_version_and_current === null) {
161
+			$resource_changes = array();
162
+			foreach ($this->resourceChanges() as $version => $model_classnames) {
163
+				if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
164
+					$resource_changes[ $version ] = $model_classnames;
165
+				}
166
+			}
167
+			$this->cached_resource_changes_between_requested_version_and_current = $resource_changes;
168
+		}
169
+		return $this->cached_resource_changes_between_requested_version_and_current;
170
+	}
171
+
172
+
173
+	/**
174
+	 * If a request was sent to 'wp-json/ee/v4.7/events' this would be '4.7'
175
+	 *
176
+	 * @return string like '4.6'
177
+	 */
178
+	public function requestedVersion()
179
+	{
180
+		return $this->requested_version;
181
+	}
182
+
183
+
184
+	/**
185
+	 * Returns an array describing how the models have changed in each version of core
186
+	 * that supports the API (starting at 4.6)
187
+	 * Top-level keys are versions (major and minor version numbers, eg "4.6")
188
+	 * next-level keys are model names (eg "Event") that underwent some change in that version
189
+	 * and the value is either NULL (indicating the model is completely NEW in this version),
190
+	 * or it's an array where fields are value names.
191
+	 * If a version is missing then we don't know anything about what changes it introduced from the previous version
192
+	 *
193
+	 * @return array
194
+	 */
195
+	public function modelChanges()
196
+	{
197
+		return $this->model_changes;
198
+	}
199
+
200
+
201
+	/**
202
+	 * Takes into account the requested version, and the current version, and
203
+	 * what changed between the two, and tries to return.
204
+	 * Analogous to EE_Registry::instance()->non_abstract_db_models
205
+	 *
206
+	 * @return array keys are model names, values are their classname
207
+	 */
208
+	public function modelsForRequestedVersion()
209
+	{
210
+		if ($this->cached_models_for_requested_version === null) {
211
+			$all_models_in_current_version = EE_Registry::instance()->non_abstract_db_models;
212
+			foreach ($this->modelChangesBetweenRequestedVersionAndCurrent() as $version => $models_changed) {
213
+				foreach ($models_changed as $model_name => $new_indicator_or_fields_added) {
214
+					if ($new_indicator_or_fields_added === ModelVersionInfo::MODEL_ADDED) {
215
+						unset($all_models_in_current_version[ $model_name ]);
216
+					}
217
+				}
218
+			}
219
+			$this->cached_models_for_requested_version = apply_filters(
220
+				'FHEE__EventEspresso_core_libraries_rest_api__models_for_requested_version',
221
+				$all_models_in_current_version,
222
+				$this
223
+			);
224
+		}
225
+		return $this->cached_models_for_requested_version;
226
+	}
227
+
228
+
229
+	/**
230
+	 * Determines if this is a valid model name in the requested version.
231
+	 * Similar to EE_Registry::instance()->is_model_name(), but takes the requested
232
+	 * version's models into account
233
+	 *
234
+	 * @param string $model_name eg 'Event'
235
+	 * @return boolean
236
+	 */
237
+	public function isModelNameInThisVersion($model_name)
238
+	{
239
+		$model_names = $this->modelsForRequestedVersion();
240
+		if (isset($model_names[ $model_name ])) {
241
+			return true;
242
+		} else {
243
+			return false;
244
+		}
245
+	}
246
+
247
+
248
+	/**
249
+	 * Wrapper for EE_Registry::instance()->load_model(), but takes the requested
250
+	 * version's models into account
251
+	 *
252
+	 * @param string $model_name
253
+	 * @return \EEM_Base
254
+	 * @throws \EE_Error
255
+	 */
256
+	public function loadModel($model_name)
257
+	{
258
+		if ($this->isModelNameInThisVersion($model_name)) {
259
+			return EE_Registry::instance()->load_model($model_name);
260
+		} else {
261
+			throw new \EE_Error(
262
+				sprintf(
263
+					__(
264
+						'Cannot load model "%1$s" because it does not exist in version %2$s of Event Espresso',
265
+						'event_espresso'
266
+					),
267
+					$model_name,
268
+					$this->requestedVersion()
269
+				)
270
+			);
271
+		}
272
+	}
273
+
274
+
275
+	/**
276
+	 * Gets all the fields that should exist on this model right now
277
+	 *
278
+	 * @param \EEM_Base $model
279
+	 * @return array|\EE_Model_Field_Base[]
280
+	 */
281
+	public function fieldsOnModelInThisVersion($model)
282
+	{
283
+		if (! isset($this->cached_fields_on_models[ $model->get_this_model_name() ])) {
284
+			// get all model changes between the requested version and current core version
285
+			$changes = $this->modelChangesBetweenRequestedVersionAndCurrent();
286
+			// fetch all fields currently on this model
287
+			$current_fields = $model->field_settings();
288
+			// remove all fields that have been added since
289
+			foreach ($changes as $version => $changes_in_version) {
290
+				if (isset($changes_in_version[ $model->get_this_model_name() ])
291
+					&& $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
292
+				) {
293
+					$current_fields = array_diff_key(
294
+						$current_fields,
295
+						array_flip($changes_in_version[ $model->get_this_model_name() ])
296
+					);
297
+				}
298
+			}
299
+			$this->cached_fields_on_models = $current_fields;
300
+		}
301
+		return $this->cached_fields_on_models;
302
+	}
303
+
304
+
305
+	/**
306
+	 * Determines if $object is of one of the classes of $classes. Similar to
307
+	 * in_array(), except this checks if $object is a subclass of the classnames provided
308
+	 * in $classnames
309
+	 *
310
+	 * @param object $object
311
+	 * @param array  $classnames
312
+	 * @return boolean
313
+	 */
314
+	public function isSubclassOfOne($object, $classnames)
315
+	{
316
+		foreach ($classnames as $classname) {
317
+			if (is_a($object, $classname)) {
318
+				return true;
319
+			}
320
+		}
321
+		return false;
322
+	}
323
+
324
+
325
+	/**
326
+	 * Returns the list of model field classes that that the API basically ignores
327
+	 *
328
+	 * @return array
329
+	 */
330
+	public function fieldsIgnored()
331
+	{
332
+		return apply_filters(
333
+			'FHEE__Controller_Model_Read_fields_ignored',
334
+			array('EE_Foreign_Key_Field_Base', 'EE_Any_Foreign_Model_Name_Field')
335
+		);
336
+	}
337
+
338
+
339
+	/**
340
+	 * If this field one that should be ignored by the API?
341
+	 *
342
+	 * @param EE_Model_Field_Base
343
+	 * @return boolean
344
+	 */
345
+	public function fieldIsIgnored($field_obj)
346
+	{
347
+		return $this->isSubclassOfOne($field_obj, $this->fieldsIgnored());
348
+	}
349
+
350
+
351
+	/**
352
+	 * Returns the list of model field classes that have a "raw" and non-raw formats.
353
+	 * Normally the "raw" versions are only accessible to those who can edit them.
354
+	 *
355
+	 * @return array an array of EE_Model_Field_Base child classnames
356
+	 */
357
+	public function fieldsThatHaveRenderedFormat()
358
+	{
359
+		return apply_filters(
360
+			'FHEE__Controller_Model_Read__fields_raw',
361
+			array('EE_Post_Content_Field', 'EE_Full_HTML_Field')
362
+		);
363
+	}
364
+
365
+
366
+	/**
367
+	 * If this field one that has a raw format
368
+	 *
369
+	 * @param EE_Model_Field_Base
370
+	 * @return boolean
371
+	 */
372
+	public function fieldHasRenderedFormat($field_obj)
373
+	{
374
+		return $this->isSubclassOfOne($field_obj, $this->fieldsThatHaveRenderedFormat());
375
+	}
376
+
377
+
378
+	/**
379
+	 * Returns the list of model field classes that have a "_pretty" and non-pretty versions.
380
+	 * The pretty version of the field is NOT query-able or editable, but requires no extra permissions
381
+	 * to view
382
+	 *
383
+	 * @return array an array of EE_Model_Field_Base child classnames
384
+	 */
385
+	public function fieldsThatHavePrettyFormat()
386
+	{
387
+		return apply_filters(
388
+			'FHEE__Controller_Model_Read__fields_pretty',
389
+			array('EE_Enum_Integer_Field', 'EE_Enum_Text_Field', 'EE_Money_Field')
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * If this field one that has a pretty equivalent
396
+	 *
397
+	 * @param EE_Model_Field_Base
398
+	 * @return boolean
399
+	 */
400
+	public function fieldHasPrettyFormat($field_obj)
401
+	{
402
+		return $this->isSubclassOfOne($field_obj, $this->fieldsThatHavePrettyFormat());
403
+	}
404
+
405
+
406
+	/**
407
+	 * Returns an array describing what extra API resource properties have been added through the versions
408
+	 *
409
+	 * @return array @see $this->_extra_resource_properties_for_models
410
+	 */
411
+	public function resourceChanges()
412
+	{
413
+		return $this->resource_changes;
414
+	}
415
+
416
+
417
+	/**
418
+	 * Returns an array where keys are extra resource properties in this version of the API,
419
+	 * and values are key-value pairs describing the new properties. @see Model_Version::_resource_changes
420
+	 *
421
+	 * @param \EEM_Base $model
422
+	 * @return array
423
+	 */
424
+	public function extraResourcePropertiesForModel($model)
425
+	{
426
+		$extra_properties = array();
427
+		foreach ($this->resourceChangesBetweenRequestedVersionAndCurrent() as $version => $model_classnames) {
428
+			foreach ($model_classnames as $model_classname => $properties_added_in_this_version) {
429
+				if (is_subclass_of($model, $model_classname)) {
430
+					$extra_properties = array_merge($extra_properties, $properties_added_in_this_version);
431
+				}
432
+			}
433
+		}
434
+		return $extra_properties;
435
+	}
436
+
437
+
438
+	/**
439
+	 * Gets all the related models for the specified model. It's good to use this
440
+	 * in case this model didn't exist for this version or something
441
+	 *
442
+	 * @param \EEM_Base $model
443
+	 * @return \EE_Model_Relation_Base[]
444
+	 */
445
+	public function relationSettings(\EEM_Base $model)
446
+	{
447
+		$relations = array();
448
+		foreach ($model->relation_settings() as $relation_name => $relation_obj) {
449
+			if ($this->isModelNameInThisVersion($relation_name)) {
450
+				$relations[ $relation_name ] = $relation_obj;
451
+			}
452
+		}
453
+		// filter the results, but use the old filter name
454
+		return apply_filters(
455
+			'FHEE__Read__create_entity_from_wpdb_result__related_models_to_include',
456
+			$relations,
457
+			$model
458
+		);
459
+	}
460 460
 }
Please login to merge, or discard this patch.
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,19 +280,19 @@  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
287 287
             $current_fields = $model->field_settings();
288 288
             // remove all fields that have been added since
289 289
             foreach ($changes as $version => $changes_in_version) {
290
-                if (isset($changes_in_version[ $model->get_this_model_name() ])
291
-                    && $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
290
+                if (isset($changes_in_version[$model->get_this_model_name()])
291
+                    && $changes_in_version[$model->get_this_model_name()] !== ModelVersionInfo::MODEL_ADDED
292 292
                 ) {
293 293
                     $current_fields = array_diff_key(
294 294
                         $current_fields,
295
-                        array_flip($changes_in_version[ $model->get_this_model_name() ])
295
+                        array_flip($changes_in_version[$model->get_this_model_name()])
296 296
                     );
297 297
                 }
298 298
             }
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
         $relations = array();
448 448
         foreach ($model->relation_settings() as $relation_name => $relation_obj) {
449 449
             if ($this->isModelNameInThisVersion($relation_name)) {
450
-                $relations[ $relation_name ] = $relation_obj;
450
+                $relations[$relation_name] = $relation_obj;
451 451
             }
452 452
         }
453 453
         // filter the results, but use the old filter name
Please login to merge, or discard this patch.
core/libraries/rest_api/Capabilities.php 2 patches
Indentation   +140 added lines, -140 removed lines patch added patch discarded remove patch
@@ -15,152 +15,152 @@
 block discarded – undo
15 15
 class Capabilities
16 16
 {
17 17
 
18
-    /**
19
-     * The current user can see at least SOME of these entities.
20
-     *
21
-     * @param EEM_Base $model
22
-     * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
23
-     * @return boolean
24
-     */
25
-    public static function currentUserHasPartialAccessTo($model, $model_context = EEM_Base::caps_read)
26
-    {
27
-        if (apply_filters(
28
-            'FHEE__Capabilities__current_user_has_partial_access_to__override_begin',
29
-            false,
30
-            $model,
31
-            $model
32
-        )) {
33
-            return true;
34
-        }
35
-        foreach ($model->caps_missing($model_context) as $capability_name => $restriction_obj) {
36
-            if ($restriction_obj instanceof \EE_Return_None_Where_Conditions) {
37
-                return false;
38
-            }
39
-        }
40
-        if (apply_filters(
41
-            'FHEE__Capabilities__current_user_has_partial_access_to__override_end',
42
-            false,
43
-            $model,
44
-            $model
45
-        )) {
46
-            return false;
47
-        }
48
-        return true;
49
-    }
18
+	/**
19
+	 * The current user can see at least SOME of these entities.
20
+	 *
21
+	 * @param EEM_Base $model
22
+	 * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
23
+	 * @return boolean
24
+	 */
25
+	public static function currentUserHasPartialAccessTo($model, $model_context = EEM_Base::caps_read)
26
+	{
27
+		if (apply_filters(
28
+			'FHEE__Capabilities__current_user_has_partial_access_to__override_begin',
29
+			false,
30
+			$model,
31
+			$model
32
+		)) {
33
+			return true;
34
+		}
35
+		foreach ($model->caps_missing($model_context) as $capability_name => $restriction_obj) {
36
+			if ($restriction_obj instanceof \EE_Return_None_Where_Conditions) {
37
+				return false;
38
+			}
39
+		}
40
+		if (apply_filters(
41
+			'FHEE__Capabilities__current_user_has_partial_access_to__override_end',
42
+			false,
43
+			$model,
44
+			$model
45
+		)) {
46
+			return false;
47
+		}
48
+		return true;
49
+	}
50 50
 
51 51
 
52
-    /**
53
-     * Gets an array of all the capabilities the current user is missing that affected
54
-     * the query
55
-     *
56
-     * @param EEM_Base $model
57
-     * @param string   $request_type one of the constants on WP_JSON_Server
58
-     * @return array
59
-     */
60
-    public static function getMissingPermissions($model, $request_type = EEM_Base::caps_read)
61
-    {
62
-        return $model->caps_missing($request_type);
63
-    }
52
+	/**
53
+	 * Gets an array of all the capabilities the current user is missing that affected
54
+	 * the query
55
+	 *
56
+	 * @param EEM_Base $model
57
+	 * @param string   $request_type one of the constants on WP_JSON_Server
58
+	 * @return array
59
+	 */
60
+	public static function getMissingPermissions($model, $request_type = EEM_Base::caps_read)
61
+	{
62
+		return $model->caps_missing($request_type);
63
+	}
64 64
 
65 65
 
66
-    /**
67
-     * Gets a string of all the capabilities the current user is missing that affected
68
-     * the query
69
-     *
70
-     * @param EEM_Base $model
71
-     * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
72
-     * @return string
73
-     */
74
-    public static function getMissingPermissionsString($model, $model_context = EEM_Base::caps_read)
75
-    {
76
-        return implode(',', array_keys(self::getMissingPermissions($model, $model_context)));
77
-    }
66
+	/**
67
+	 * Gets a string of all the capabilities the current user is missing that affected
68
+	 * the query
69
+	 *
70
+	 * @param EEM_Base $model
71
+	 * @param string   $model_context one of the return values from EEM_Base::valid_cap_contexts()
72
+	 * @return string
73
+	 */
74
+	public static function getMissingPermissionsString($model, $model_context = EEM_Base::caps_read)
75
+	{
76
+		return implode(',', array_keys(self::getMissingPermissions($model, $model_context)));
77
+	}
78 78
 
79 79
 
80
-    /**
81
-     * Takes a entity that's ready to be returned and removes fields which the user shouldn't be able to access.
82
-     *
83
-     * @param array            $entity
84
-     * @param EEM_Base         $model
85
-     * @param string           $request_type         one of the return values from EEM_Base::valid_cap_contexts()
86
-     * @param ModelVersionInfo $model_version_info
87
-     * @param string           $primary_key_string   result of EEM_Base::get_index_primary_key_string(), so that we can
88
-     *                                               use this with models that have no primary key
89
-     * @return array ready for converting into json
90
-     */
91
-    public static function filterOutInaccessibleEntityFields(
92
-        $entity,
93
-        $model,
94
-        $request_type,
95
-        $model_version_info,
96
-        $primary_key_string = null
97
-    ) {
98
-        // if they didn't provide the primary key string, we'll just hope we can figure it out
99
-        // from the entity (although it's preferred client code does it, because the entity might be missing
100
-        // necessary fields for creating the primary key string, or they could be named differently)
101
-        if ($primary_key_string === null) {
102
-            $primary_key_string = $model->get_index_primary_key_string(
103
-                $model->deduce_fields_n_values_from_cols_n_values($entity)
104
-            );
105
-        }
106
-        // we only care to do this for frontend reads and when the user can't edit the item
107
-        if ($request_type !== EEM_Base::caps_read
108
-            || $model->exists(
109
-                $model->alter_query_params_to_restrict_by_ID(
110
-                    $primary_key_string,
111
-                    array(
112
-                        'default_where_conditions' => 'none',
113
-                        'caps'                     => EEM_Base::caps_edit,
114
-                    )
115
-                )
116
-            )
117
-        ) {
118
-            return $entity;
119
-        }
120
-        foreach ($model->field_settings() as $field_name => $field_obj) {
121
-            if ($model_version_info->fieldHasRenderedFormat($field_obj)
122
-                && isset($entity[ $field_name ])
123
-                && is_array($entity[ $field_name ])
124
-                && isset($entity[ $field_name ]['raw'])
125
-            ) {
126
-                unset($entity[ $field_name ]['raw']);
127
-            }
128
-        }
129
-        // theoretically we may want to filter out specific fields for specific models
130
-        return apply_filters(
131
-            'FHEE__Capabilities__filter_out_inaccessible_entity_fields',
132
-            $entity,
133
-            $model,
134
-            $request_type
135
-        );
136
-    }
80
+	/**
81
+	 * Takes a entity that's ready to be returned and removes fields which the user shouldn't be able to access.
82
+	 *
83
+	 * @param array            $entity
84
+	 * @param EEM_Base         $model
85
+	 * @param string           $request_type         one of the return values from EEM_Base::valid_cap_contexts()
86
+	 * @param ModelVersionInfo $model_version_info
87
+	 * @param string           $primary_key_string   result of EEM_Base::get_index_primary_key_string(), so that we can
88
+	 *                                               use this with models that have no primary key
89
+	 * @return array ready for converting into json
90
+	 */
91
+	public static function filterOutInaccessibleEntityFields(
92
+		$entity,
93
+		$model,
94
+		$request_type,
95
+		$model_version_info,
96
+		$primary_key_string = null
97
+	) {
98
+		// if they didn't provide the primary key string, we'll just hope we can figure it out
99
+		// from the entity (although it's preferred client code does it, because the entity might be missing
100
+		// necessary fields for creating the primary key string, or they could be named differently)
101
+		if ($primary_key_string === null) {
102
+			$primary_key_string = $model->get_index_primary_key_string(
103
+				$model->deduce_fields_n_values_from_cols_n_values($entity)
104
+			);
105
+		}
106
+		// we only care to do this for frontend reads and when the user can't edit the item
107
+		if ($request_type !== EEM_Base::caps_read
108
+			|| $model->exists(
109
+				$model->alter_query_params_to_restrict_by_ID(
110
+					$primary_key_string,
111
+					array(
112
+						'default_where_conditions' => 'none',
113
+						'caps'                     => EEM_Base::caps_edit,
114
+					)
115
+				)
116
+			)
117
+		) {
118
+			return $entity;
119
+		}
120
+		foreach ($model->field_settings() as $field_name => $field_obj) {
121
+			if ($model_version_info->fieldHasRenderedFormat($field_obj)
122
+				&& isset($entity[ $field_name ])
123
+				&& is_array($entity[ $field_name ])
124
+				&& isset($entity[ $field_name ]['raw'])
125
+			) {
126
+				unset($entity[ $field_name ]['raw']);
127
+			}
128
+		}
129
+		// theoretically we may want to filter out specific fields for specific models
130
+		return apply_filters(
131
+			'FHEE__Capabilities__filter_out_inaccessible_entity_fields',
132
+			$entity,
133
+			$model,
134
+			$request_type
135
+		);
136
+	}
137 137
 
138 138
 
139
-    /**
140
-     * Verifies the current user has at least partial access to do this action on this model.
141
-     * If not, throws an exception (so we can define the code that sets up this error object
142
-     * once)
143
-     *
144
-     * @param EEM_Base $model
145
-     * @param string   $model_action_context
146
-     * @param string   $action_name
147
-     * @return void
148
-     * @throws RestException
149
-     */
150
-    public static function verifyAtLeastPartialAccessTo($model, $model_action_context, $action_name = 'list')
151
-    {
152
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
153
-            $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
154
-            throw new RestException(
155
-                sprintf('rest_cannot_%s_%s', strtolower($action_name), $model_name_plural),
156
-                sprintf(
157
-                    __('Sorry, you are not allowed to %1$s %2$s. Missing permissions: %3$s', 'event_espresso'),
158
-                    $action_name,
159
-                    $model_name_plural,
160
-                    Capabilities::getMissingPermissionsString($model, $model_action_context)
161
-                ),
162
-                array('status' => 403)
163
-            );
164
-        }
165
-    }
139
+	/**
140
+	 * Verifies the current user has at least partial access to do this action on this model.
141
+	 * If not, throws an exception (so we can define the code that sets up this error object
142
+	 * once)
143
+	 *
144
+	 * @param EEM_Base $model
145
+	 * @param string   $model_action_context
146
+	 * @param string   $action_name
147
+	 * @return void
148
+	 * @throws RestException
149
+	 */
150
+	public static function verifyAtLeastPartialAccessTo($model, $model_action_context, $action_name = 'list')
151
+	{
152
+		if (! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
153
+			$model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
154
+			throw new RestException(
155
+				sprintf('rest_cannot_%s_%s', strtolower($action_name), $model_name_plural),
156
+				sprintf(
157
+					__('Sorry, you are not allowed to %1$s %2$s. Missing permissions: %3$s', 'event_espresso'),
158
+					$action_name,
159
+					$model_name_plural,
160
+					Capabilities::getMissingPermissionsString($model, $model_action_context)
161
+				),
162
+				array('status' => 403)
163
+			);
164
+		}
165
+	}
166 166
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -119,11 +119,11 @@  discard block
 block discarded – undo
119 119
         }
120 120
         foreach ($model->field_settings() as $field_name => $field_obj) {
121 121
             if ($model_version_info->fieldHasRenderedFormat($field_obj)
122
-                && isset($entity[ $field_name ])
123
-                && is_array($entity[ $field_name ])
124
-                && isset($entity[ $field_name ]['raw'])
122
+                && isset($entity[$field_name])
123
+                && is_array($entity[$field_name])
124
+                && isset($entity[$field_name]['raw'])
125 125
             ) {
126
-                unset($entity[ $field_name ]['raw']);
126
+                unset($entity[$field_name]['raw']);
127 127
             }
128 128
         }
129 129
         // theoretically we may want to filter out specific fields for specific models
@@ -149,7 +149,7 @@  discard block
 block discarded – undo
149 149
      */
150 150
     public static function verifyAtLeastPartialAccessTo($model, $model_action_context, $action_name = 'list')
151 151
     {
152
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
152
+        if ( ! Capabilities::currentUserHasPartialAccessTo($model, $model_action_context)) {
153 153
             $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
154 154
             throw new RestException(
155 155
                 sprintf('rest_cannot_%s_%s', strtolower($action_name), $model_name_plural),
Please login to merge, or discard this patch.
core/libraries/rest_api/calculations/Registration.php 2 patches
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -19,62 +19,62 @@
 block discarded – undo
19 19
 class Registration extends Calculations_Base
20 20
 {
21 21
 
22
-    /**
23
-     * Calculates the checkin status for each datetime this registration has access to
24
-     *
25
-     * @param array            $wpdb_row
26
-     * @param \WP_REST_Request $request
27
-     * @param Base             $controller
28
-     * @return array
29
-     * @throws \EE_Error
30
-     */
31
-    public static function datetimeCheckinStati($wpdb_row, $request, $controller)
32
-    {
33
-        if (is_array($wpdb_row) && isset($wpdb_row['Registration.REG_ID'])) {
34
-            $reg = EEM_Registration::instance()->get_one_by_ID($wpdb_row['Registration.REG_ID']);
35
-        } else {
36
-            $reg = null;
37
-        }
38
-        if (! $reg instanceof EE_Registration
39
-        ) {
40
-            throw new \EE_Error(
41
-                sprintf(
42
-                    __(
43
-                    // @codingStandardsIgnoreStart
44
-                        'Cannot calculate datetime_checkin_stati because the registration with ID %1$s (from database row %2$s) was not found',
45
-                        // @codingStandardsIgnoreEnd
46
-                        'event_espresso'
47
-                    ),
48
-                    $wpdb_row['Registration.REG_ID'],
49
-                    print_r($wpdb_row, true)
50
-                )
51
-            );
52
-        }
53
-        $datetime_ids = EEM_Datetime::instance()->get_col(
54
-            array(
55
-                array(
56
-                    'Ticket.TKT_ID' => $reg->ticket_ID(),
57
-                ),
58
-                'default_where_conditions' => \EEM_Base::default_where_conditions_minimum_all,
59
-            )
60
-        );
61
-        $checkin_stati = array();
62
-        foreach ($datetime_ids as $datetime_id) {
63
-            $status = $reg->check_in_status_for_datetime($datetime_id);
64
-            switch ($status) {
65
-                case EE_Checkin::status_checked_out:
66
-                    $status_pretty = 'OUT';
67
-                    break;
68
-                case EE_Checkin::status_checked_in:
69
-                    $status_pretty = 'IN';
70
-                    break;
71
-                case EE_Checkin::status_checked_never:
72
-                default:
73
-                    $status_pretty = 'NEVER';
74
-                    break;
75
-            }
76
-            $checkin_stati[ $datetime_id ] = $status_pretty;
77
-        }
78
-        return $checkin_stati;
79
-    }
22
+	/**
23
+	 * Calculates the checkin status for each datetime this registration has access to
24
+	 *
25
+	 * @param array            $wpdb_row
26
+	 * @param \WP_REST_Request $request
27
+	 * @param Base             $controller
28
+	 * @return array
29
+	 * @throws \EE_Error
30
+	 */
31
+	public static function datetimeCheckinStati($wpdb_row, $request, $controller)
32
+	{
33
+		if (is_array($wpdb_row) && isset($wpdb_row['Registration.REG_ID'])) {
34
+			$reg = EEM_Registration::instance()->get_one_by_ID($wpdb_row['Registration.REG_ID']);
35
+		} else {
36
+			$reg = null;
37
+		}
38
+		if (! $reg instanceof EE_Registration
39
+		) {
40
+			throw new \EE_Error(
41
+				sprintf(
42
+					__(
43
+					// @codingStandardsIgnoreStart
44
+						'Cannot calculate datetime_checkin_stati because the registration with ID %1$s (from database row %2$s) was not found',
45
+						// @codingStandardsIgnoreEnd
46
+						'event_espresso'
47
+					),
48
+					$wpdb_row['Registration.REG_ID'],
49
+					print_r($wpdb_row, true)
50
+				)
51
+			);
52
+		}
53
+		$datetime_ids = EEM_Datetime::instance()->get_col(
54
+			array(
55
+				array(
56
+					'Ticket.TKT_ID' => $reg->ticket_ID(),
57
+				),
58
+				'default_where_conditions' => \EEM_Base::default_where_conditions_minimum_all,
59
+			)
60
+		);
61
+		$checkin_stati = array();
62
+		foreach ($datetime_ids as $datetime_id) {
63
+			$status = $reg->check_in_status_for_datetime($datetime_id);
64
+			switch ($status) {
65
+				case EE_Checkin::status_checked_out:
66
+					$status_pretty = 'OUT';
67
+					break;
68
+				case EE_Checkin::status_checked_in:
69
+					$status_pretty = 'IN';
70
+					break;
71
+				case EE_Checkin::status_checked_never:
72
+				default:
73
+					$status_pretty = 'NEVER';
74
+					break;
75
+			}
76
+			$checkin_stati[ $datetime_id ] = $status_pretty;
77
+		}
78
+		return $checkin_stati;
79
+	}
80 80
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -35,7 +35,7 @@  discard block
 block discarded – undo
35 35
         } else {
36 36
             $reg = null;
37 37
         }
38
-        if (! $reg instanceof EE_Registration
38
+        if ( ! $reg instanceof EE_Registration
39 39
         ) {
40 40
             throw new \EE_Error(
41 41
                 sprintf(
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
                     $status_pretty = 'NEVER';
74 74
                     break;
75 75
             }
76
-            $checkin_stati[ $datetime_id ] = $status_pretty;
76
+            $checkin_stati[$datetime_id] = $status_pretty;
77 77
         }
78 78
         return $checkin_stati;
79 79
     }
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/DatetimeOffsetFix.php 2 patches
Indentation   +467 added lines, -467 removed lines patch added patch discarded remove patch
@@ -24,471 +24,471 @@
 block discarded – undo
24 24
 class DatetimeOffsetFix extends JobHandler
25 25
 {
26 26
 
27
-    /**
28
-     * Key for the option used to track which models have been processed when doing the batches.
29
-     */
30
-    const MODELS_TO_PROCESS_OPTION_KEY = 'ee_models_processed_for_datetime_offset_fix';
31
-
32
-
33
-    const COUNT_OF_MODELS_PROCESSED = 'ee_count_of_ee_models_processed_for_datetime_offset_fixed';
34
-
35
-    /**
36
-     * Key for the option used to track what the current offset is that will be applied when this tool is executed.
37
-     */
38
-    const OFFSET_TO_APPLY_OPTION_KEY = 'ee_datetime_offset_fix_offset_to_apply';
39
-
40
-
41
-    const OPTION_KEY_OFFSET_RANGE_START_DATE = 'ee_datetime_offset_start_date_range';
42
-
43
-
44
-    const OPTION_KEY_OFFSET_RANGE_END_DATE = 'ee_datetime_offset_end_date_range';
45
-
46
-
47
-    /**
48
-     * String labelling the datetime offset fix type for change-log entries.
49
-     */
50
-    const DATETIME_OFFSET_FIX_CHANGELOG_TYPE = 'datetime_offset_fix';
51
-
52
-
53
-    /**
54
-     * String labelling a datetime offset fix error for change-log entries.
55
-     */
56
-    const DATETIME_OFFSET_FIX_CHANGELOG_ERROR_TYPE = 'datetime_offset_fix_error';
57
-
58
-    /**
59
-     * @var EEM_Base[]
60
-     */
61
-    protected $models_with_datetime_fields = array();
62
-
63
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
64
-
65
-    /**
66
-     * Performs any necessary setup for starting the job. This is also a good
67
-     * place to setup the $job_arguments which will be used for subsequent HTTP requests
68
-     * when continue_job will be called
69
-     *
70
-     * @param JobParameters $job_parameters
71
-     * @return JobStepResponse
72
-     * @throws EE_Error
73
-     * @throws InvalidArgumentException
74
-     * @throws InvalidDataTypeException
75
-     * @throws InvalidInterfaceException
76
-     */
77
-    public function create_job(JobParameters $job_parameters)
78
-    {
79
-        $models_with_datetime_fields = $this->getModelsWithDatetimeFields();
80
-        // we'll be doing each model as a batch.
81
-        $job_parameters->set_job_size(count($models_with_datetime_fields));
82
-        return new JobStepResponse(
83
-            $job_parameters,
84
-            esc_html__('Starting Datetime Offset Fix', 'event_espresso')
85
-        );
86
-    }
87
-
88
-    /**
89
-     * Performs another step of the job
90
-     *
91
-     * @param JobParameters $job_parameters
92
-     * @param int           $batch_size
93
-     * @return JobStepResponse
94
-     * @throws EE_Error
95
-     * @throws InvalidArgumentException
96
-     * @throws InvalidDataTypeException
97
-     * @throws InvalidInterfaceException
98
-     */
99
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
100
-    {
101
-        $models_to_process = $this->getModelsWithDatetimeFields();
102
-        // let's pop off the a model and do the query to apply the offset.
103
-        $model_to_process = array_pop($models_to_process);
104
-        // update our record
105
-        $this->setModelsToProcess($models_to_process);
106
-        $this->processModel($model_to_process);
107
-        $this->updateCountOfModelsProcessed();
108
-        $job_parameters->set_units_processed($this->getCountOfModelsProcessed());
109
-        if (count($models_to_process) > 0) {
110
-            $job_parameters->set_status(JobParameters::status_continue);
111
-        } else {
112
-            $job_parameters->set_status(JobParameters::status_complete);
113
-        }
114
-        return new JobStepResponse(
115
-            $job_parameters,
116
-            sprintf(
117
-                esc_html__('Updated the offset for all datetime fields on the %s model.', 'event_espresso'),
118
-                $model_to_process
119
-            )
120
-        );
121
-    }
122
-
123
-    /**
124
-     * Performs any clean-up logic when we know the job is completed
125
-     *
126
-     * @param JobParameters $job_parameters
127
-     * @return JobStepResponse
128
-     * @throws BatchRequestException
129
-     */
130
-    public function cleanup_job(JobParameters $job_parameters)
131
-    {
132
-        // delete important saved options.
133
-        delete_option(self::MODELS_TO_PROCESS_OPTION_KEY);
134
-        delete_option(self::COUNT_OF_MODELS_PROCESSED);
135
-        delete_option(self::OPTION_KEY_OFFSET_RANGE_START_DATE);
136
-        delete_option(self::OPTION_KEY_OFFSET_RANGE_END_DATE);
137
-        return new JobStepResponse($job_parameters, esc_html__(
138
-            'Offset has been applied to all affected fields.',
139
-            'event_espresso'
140
-        ));
141
-    }
142
-
143
-
144
-    /**
145
-     * Contains the logic for processing a model and applying the datetime offset to affected fields on that model.
146
-     *
147
-     * @param string $model_class_name
148
-     * @throws EE_Error
149
-     */
150
-    protected function processModel($model_class_name)
151
-    {
152
-        global $wpdb;
153
-        /** @var EEM_Base $model */
154
-        $model = $model_class_name::instance();
155
-        $original_offset = self::getOffset();
156
-        $start_date_range = self::getStartDateRange();
157
-        $end_date_range = self::getEndDateRange();
158
-        $sql_date_function = $original_offset > 0 ? 'DATE_ADD' : 'DATE_SUB';
159
-        $offset = abs($original_offset) * 60;
160
-        $date_ranges = array();
161
-        // since some affected models might have two tables, we have to get our tables and set up a query for each table.
162
-        foreach ($model->get_tables() as $table) {
163
-            $query = 'UPDATE ' . $table->get_table_name();
164
-            $fields_affected = array();
165
-            $inner_query = array();
166
-            foreach ($model->_get_fields_for_table($table->get_table_alias()) as $model_field) {
167
-                if ($model_field instanceof EE_Datetime_Field) {
168
-                    $inner_query[ $model_field->get_table_column() ] = $model_field->get_table_column() . ' = '
169
-                                                                       . $sql_date_function . '('
170
-                                                                       . $model_field->get_table_column()
171
-                                                                       . ", INTERVAL {$offset} MINUTE)";
172
-                    $fields_affected[] = $model_field;
173
-                }
174
-            }
175
-            if (! $fields_affected) {
176
-                continue;
177
-            }
178
-            // do we do one query per column/field or one query for all fields on the model? It all depends on whether
179
-            // there is a date range applied or not.
180
-            if ($start_date_range instanceof DbSafeDateTime || $end_date_range instanceof DbSafeDateTime) {
181
-                $result = $this->doQueryForEachField($query, $inner_query, $start_date_range, $end_date_range);
182
-            } else {
183
-                $result = $this->doQueryForAllFields($query, $inner_query);
184
-            }
185
-
186
-            // record appropriate logs for the query
187
-            switch (true) {
188
-                case $result === false:
189
-                    // record error.
190
-                    $error_message = $wpdb->last_error;
191
-                    // handle the edgecases where last_error might be empty.
192
-                    if (! $error_message) {
193
-                        $error_message = esc_html__('Unknown mysql error occured.', 'event_espresso');
194
-                    }
195
-                    $this->recordChangeLog($model, $original_offset, $table, $fields_affected, $error_message);
196
-                    break;
197
-                case is_array($result) && ! empty($result):
198
-                    foreach ($result as $field_name => $error_message) {
199
-                        $this->recordChangeLog($model, $original_offset, $table, array($field_name), $error_message);
200
-                    }
201
-                    break;
202
-                default:
203
-                    $this->recordChangeLog($model, $original_offset, $table, $fields_affected);
204
-            }
205
-        }
206
-    }
207
-
208
-
209
-    /**
210
-     * Does the query on each $inner_query individually.
211
-     *
212
-     * @param string              $query
213
-     * @param array               $inner_query
214
-     * @param DbSafeDateTime|null $start_date_range
215
-     * @param DbSafeDateTime|null $end_date_range
216
-     * @return array  An array of any errors encountered and the fields they were for.
217
-     */
218
-    private function doQueryForEachField($query, array $inner_query, $start_date_range, $end_date_range)
219
-    {
220
-        global $wpdb;
221
-        $errors = array();
222
-        foreach ($inner_query as $field_name => $field_query) {
223
-            $query_to_run = $query;
224
-            $where_conditions = array();
225
-            $query_to_run .= ' SET ' . $field_query;
226
-            if ($start_date_range instanceof DbSafeDateTime) {
227
-                $start_date = $start_date_range->format(EE_Datetime_Field::mysql_timestamp_format);
228
-                $where_conditions[] = "{$field_name} > '{$start_date}'";
229
-            }
230
-            if ($end_date_range instanceof DbSafeDateTime) {
231
-                $end_date = $end_date_range->format(EE_Datetime_Field::mysql_timestamp_format);
232
-                $where_conditions[] = "{$field_name} < '{$end_date}'";
233
-            }
234
-            if ($where_conditions) {
235
-                $query_to_run .= ' WHERE ' . implode(' AND ', $where_conditions);
236
-            }
237
-            $result = $wpdb->query($query_to_run);
238
-            if ($result === false) {
239
-                // record error.
240
-                $error_message = $wpdb->last_error;
241
-                // handle the edgecases where last_error might be empty.
242
-                if (! $error_message) {
243
-                    $error_message = esc_html__('Unknown mysql error occured.', 'event_espresso');
244
-                }
245
-                $errors[ $field_name ] = $error_message;
246
-            }
247
-        }
248
-        return $errors;
249
-    }
250
-
251
-
252
-    /**
253
-     * Performs the query for all fields within the inner_query
254
-     *
255
-     * @param string $query
256
-     * @param array  $inner_query
257
-     * @return false|int
258
-     */
259
-    private function doQueryForAllFields($query, array $inner_query)
260
-    {
261
-        global $wpdb;
262
-        $query .= ' SET ' . implode(',', $inner_query);
263
-        return $wpdb->query($query);
264
-    }
265
-
266
-
267
-    /**
268
-     * Records a changelog entry using the given information.
269
-     *
270
-     * @param EEM_Base              $model
271
-     * @param float                 $offset
272
-     * @param EE_Table_Base         $table
273
-     * @param EE_Model_Field_Base[] $model_fields_affected
274
-     * @param string                $error_message If present then there was an error so let's record that instead.
275
-     * @throws EE_Error
276
-     */
277
-    private function recordChangeLog(
278
-        EEM_Base $model,
279
-        $offset,
280
-        EE_Table_Base $table,
281
-        $model_fields_affected,
282
-        $error_message = ''
283
-    ) {
284
-        // setup $fields list.
285
-        $fields = array();
286
-        /** @var EE_Datetime_Field $model_field */
287
-        foreach ($model_fields_affected as $model_field) {
288
-            if (! $model_field instanceof EE_Datetime_Field) {
289
-                continue;
290
-            }
291
-            $fields[] = $model_field->get_name();
292
-        }
293
-        // setup the message for the changelog entry.
294
-        $message = $error_message
295
-            ? sprintf(
296
-                esc_html__(
297
-                    'The %1$s table for the %2$s model did not have the offset of %3$f applied to its fields (%4$s), because of the following error:%5$s',
298
-                    'event_espresso'
299
-                ),
300
-                $table->get_table_name(),
301
-                $model->get_this_model_name(),
302
-                $offset,
303
-                implode(',', $fields),
304
-                $error_message
305
-            )
306
-            : sprintf(
307
-                esc_html__(
308
-                    'The %1$s table for the %2$s model has had the offset of %3$f applied to its following fields: %4$s',
309
-                    'event_espresso'
310
-                ),
311
-                $table->get_table_name(),
312
-                $model->get_this_model_name(),
313
-                $offset,
314
-                implode(',', $fields)
315
-            );
316
-        // write to the log
317
-        $changelog = EE_Change_Log::new_instance(array(
318
-            'LOG_type'    => $error_message
319
-                ? self::DATETIME_OFFSET_FIX_CHANGELOG_ERROR_TYPE
320
-                : self::DATETIME_OFFSET_FIX_CHANGELOG_TYPE,
321
-            'LOG_message' => $message,
322
-        ));
323
-        $changelog->save();
324
-    }
325
-
326
-
327
-    /**
328
-     * Returns an array of models that have datetime fields.
329
-     * This array is added to a short lived transient cache to keep having to build this list to a minimum.
330
-     *
331
-     * @return array an array of model class names.
332
-     * @throws EE_Error
333
-     * @throws InvalidDataTypeException
334
-     * @throws InvalidInterfaceException
335
-     * @throws InvalidArgumentException
336
-     */
337
-    private function getModelsWithDatetimeFields()
338
-    {
339
-        $this->getModelsToProcess();
340
-        if (! empty($this->models_with_datetime_fields)) {
341
-            return $this->models_with_datetime_fields;
342
-        }
343
-
344
-        $all_non_abstract_models = EE_Registry::instance()->non_abstract_db_models;
345
-        foreach ($all_non_abstract_models as $non_abstract_model) {
346
-            // get model instance
347
-            /** @var EEM_Base $non_abstract_model */
348
-            $non_abstract_model = $non_abstract_model::instance();
349
-            if ($non_abstract_model->get_a_field_of_type('EE_Datetime_Field') instanceof EE_Datetime_Field) {
350
-                $this->models_with_datetime_fields[] = get_class($non_abstract_model);
351
-            }
352
-        }
353
-        $this->setModelsToProcess($this->models_with_datetime_fields);
354
-        return $this->models_with_datetime_fields;
355
-    }
356
-
357
-
358
-    /**
359
-     * This simply records the models that have been processed with our tracking option.
360
-     *
361
-     * @param array $models_to_set array of model class names.
362
-     */
363
-    private function setModelsToProcess($models_to_set)
364
-    {
365
-        update_option(self::MODELS_TO_PROCESS_OPTION_KEY, $models_to_set);
366
-    }
367
-
368
-
369
-    /**
370
-     * Used to keep track of how many models have been processed for the batch
371
-     *
372
-     * @param $count
373
-     */
374
-    private function updateCountOfModelsProcessed($count = 1)
375
-    {
376
-        $count = $this->getCountOfModelsProcessed() + (int) $count;
377
-        update_option(self::COUNT_OF_MODELS_PROCESSED, $count);
378
-    }
379
-
380
-
381
-    /**
382
-     * Retrieve the tracked number of models processed between requests.
383
-     *
384
-     * @return int
385
-     */
386
-    private function getCountOfModelsProcessed()
387
-    {
388
-        return (int) get_option(self::COUNT_OF_MODELS_PROCESSED, 0);
389
-    }
390
-
391
-
392
-    /**
393
-     * Returns the models that are left to process.
394
-     *
395
-     * @return array  an array of model class names.
396
-     */
397
-    private function getModelsToProcess()
398
-    {
399
-        if (empty($this->models_with_datetime_fields)) {
400
-            $this->models_with_datetime_fields = get_option(self::MODELS_TO_PROCESS_OPTION_KEY, array());
401
-        }
402
-        return $this->models_with_datetime_fields;
403
-    }
404
-
405
-
406
-    /**
407
-     * Used to record the offset that will be applied to dates and times for EE_Datetime_Field columns.
408
-     *
409
-     * @param float $offset
410
-     */
411
-    public static function updateOffset($offset)
412
-    {
413
-        update_option(self::OFFSET_TO_APPLY_OPTION_KEY, $offset);
414
-    }
415
-
416
-
417
-    /**
418
-     * Used to retrieve the saved offset that will be applied to dates and times for EE_Datetime_Field columns.
419
-     *
420
-     * @return float
421
-     */
422
-    public static function getOffset()
423
-    {
424
-        return (float) get_option(self::OFFSET_TO_APPLY_OPTION_KEY, 0);
425
-    }
426
-
427
-
428
-    /**
429
-     * Used to set the saved offset range start date.
430
-     *
431
-     * @param DbSafeDateTime|null $start_date
432
-     */
433
-    public static function updateStartDateRange(DbSafeDateTime $start_date = null)
434
-    {
435
-        $date_to_save = $start_date instanceof DbSafeDateTime
436
-            ? $start_date->format('U')
437
-            : '';
438
-        update_option(self::OPTION_KEY_OFFSET_RANGE_START_DATE, $date_to_save);
439
-    }
440
-
441
-
442
-    /**
443
-     * Used to get the saved offset range start date.
444
-     *
445
-     * @return DbSafeDateTime|null
446
-     */
447
-    public static function getStartDateRange()
448
-    {
449
-        $start_date = get_option(self::OPTION_KEY_OFFSET_RANGE_START_DATE, null);
450
-        try {
451
-            $datetime = DateTime::createFromFormat('U', $start_date, new DateTimeZone('UTC'));
452
-            $start_date = $datetime instanceof DateTime
453
-                ? DbSafeDateTime::createFromDateTime($datetime)
454
-                : null;
455
-        } catch (Exception $e) {
456
-            $start_date = null;
457
-        }
458
-        return $start_date;
459
-    }
460
-
461
-
462
-    /**
463
-     * Used to set the saved offset range end date.
464
-     *
465
-     * @param DbSafeDateTime|null $end_date
466
-     */
467
-    public static function updateEndDateRange(DbSafeDateTime $end_date = null)
468
-    {
469
-        $date_to_save = $end_date instanceof DbSafeDateTime
470
-            ? $end_date->format('U')
471
-            : '';
472
-        update_option(self::OPTION_KEY_OFFSET_RANGE_END_DATE, $date_to_save);
473
-    }
474
-
475
-
476
-    /**
477
-     * Used to get the saved offset range end date.
478
-     *
479
-     * @return DbSafeDateTime|null
480
-     */
481
-    public static function getEndDateRange()
482
-    {
483
-        $end_date = get_option(self::OPTION_KEY_OFFSET_RANGE_END_DATE, null);
484
-        try {
485
-            $datetime = DateTime::createFromFormat('U', $end_date, new DateTimeZone('UTC'));
486
-            $end_date = $datetime instanceof Datetime
487
-                ? DbSafeDateTime::createFromDateTime($datetime)
488
-                : null;
489
-        } catch (Exception $e) {
490
-            $end_date = null;
491
-        }
492
-        return $end_date;
493
-    }
27
+	/**
28
+	 * Key for the option used to track which models have been processed when doing the batches.
29
+	 */
30
+	const MODELS_TO_PROCESS_OPTION_KEY = 'ee_models_processed_for_datetime_offset_fix';
31
+
32
+
33
+	const COUNT_OF_MODELS_PROCESSED = 'ee_count_of_ee_models_processed_for_datetime_offset_fixed';
34
+
35
+	/**
36
+	 * Key for the option used to track what the current offset is that will be applied when this tool is executed.
37
+	 */
38
+	const OFFSET_TO_APPLY_OPTION_KEY = 'ee_datetime_offset_fix_offset_to_apply';
39
+
40
+
41
+	const OPTION_KEY_OFFSET_RANGE_START_DATE = 'ee_datetime_offset_start_date_range';
42
+
43
+
44
+	const OPTION_KEY_OFFSET_RANGE_END_DATE = 'ee_datetime_offset_end_date_range';
45
+
46
+
47
+	/**
48
+	 * String labelling the datetime offset fix type for change-log entries.
49
+	 */
50
+	const DATETIME_OFFSET_FIX_CHANGELOG_TYPE = 'datetime_offset_fix';
51
+
52
+
53
+	/**
54
+	 * String labelling a datetime offset fix error for change-log entries.
55
+	 */
56
+	const DATETIME_OFFSET_FIX_CHANGELOG_ERROR_TYPE = 'datetime_offset_fix_error';
57
+
58
+	/**
59
+	 * @var EEM_Base[]
60
+	 */
61
+	protected $models_with_datetime_fields = array();
62
+
63
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
64
+
65
+	/**
66
+	 * Performs any necessary setup for starting the job. This is also a good
67
+	 * place to setup the $job_arguments which will be used for subsequent HTTP requests
68
+	 * when continue_job will be called
69
+	 *
70
+	 * @param JobParameters $job_parameters
71
+	 * @return JobStepResponse
72
+	 * @throws EE_Error
73
+	 * @throws InvalidArgumentException
74
+	 * @throws InvalidDataTypeException
75
+	 * @throws InvalidInterfaceException
76
+	 */
77
+	public function create_job(JobParameters $job_parameters)
78
+	{
79
+		$models_with_datetime_fields = $this->getModelsWithDatetimeFields();
80
+		// we'll be doing each model as a batch.
81
+		$job_parameters->set_job_size(count($models_with_datetime_fields));
82
+		return new JobStepResponse(
83
+			$job_parameters,
84
+			esc_html__('Starting Datetime Offset Fix', 'event_espresso')
85
+		);
86
+	}
87
+
88
+	/**
89
+	 * Performs another step of the job
90
+	 *
91
+	 * @param JobParameters $job_parameters
92
+	 * @param int           $batch_size
93
+	 * @return JobStepResponse
94
+	 * @throws EE_Error
95
+	 * @throws InvalidArgumentException
96
+	 * @throws InvalidDataTypeException
97
+	 * @throws InvalidInterfaceException
98
+	 */
99
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
100
+	{
101
+		$models_to_process = $this->getModelsWithDatetimeFields();
102
+		// let's pop off the a model and do the query to apply the offset.
103
+		$model_to_process = array_pop($models_to_process);
104
+		// update our record
105
+		$this->setModelsToProcess($models_to_process);
106
+		$this->processModel($model_to_process);
107
+		$this->updateCountOfModelsProcessed();
108
+		$job_parameters->set_units_processed($this->getCountOfModelsProcessed());
109
+		if (count($models_to_process) > 0) {
110
+			$job_parameters->set_status(JobParameters::status_continue);
111
+		} else {
112
+			$job_parameters->set_status(JobParameters::status_complete);
113
+		}
114
+		return new JobStepResponse(
115
+			$job_parameters,
116
+			sprintf(
117
+				esc_html__('Updated the offset for all datetime fields on the %s model.', 'event_espresso'),
118
+				$model_to_process
119
+			)
120
+		);
121
+	}
122
+
123
+	/**
124
+	 * Performs any clean-up logic when we know the job is completed
125
+	 *
126
+	 * @param JobParameters $job_parameters
127
+	 * @return JobStepResponse
128
+	 * @throws BatchRequestException
129
+	 */
130
+	public function cleanup_job(JobParameters $job_parameters)
131
+	{
132
+		// delete important saved options.
133
+		delete_option(self::MODELS_TO_PROCESS_OPTION_KEY);
134
+		delete_option(self::COUNT_OF_MODELS_PROCESSED);
135
+		delete_option(self::OPTION_KEY_OFFSET_RANGE_START_DATE);
136
+		delete_option(self::OPTION_KEY_OFFSET_RANGE_END_DATE);
137
+		return new JobStepResponse($job_parameters, esc_html__(
138
+			'Offset has been applied to all affected fields.',
139
+			'event_espresso'
140
+		));
141
+	}
142
+
143
+
144
+	/**
145
+	 * Contains the logic for processing a model and applying the datetime offset to affected fields on that model.
146
+	 *
147
+	 * @param string $model_class_name
148
+	 * @throws EE_Error
149
+	 */
150
+	protected function processModel($model_class_name)
151
+	{
152
+		global $wpdb;
153
+		/** @var EEM_Base $model */
154
+		$model = $model_class_name::instance();
155
+		$original_offset = self::getOffset();
156
+		$start_date_range = self::getStartDateRange();
157
+		$end_date_range = self::getEndDateRange();
158
+		$sql_date_function = $original_offset > 0 ? 'DATE_ADD' : 'DATE_SUB';
159
+		$offset = abs($original_offset) * 60;
160
+		$date_ranges = array();
161
+		// since some affected models might have two tables, we have to get our tables and set up a query for each table.
162
+		foreach ($model->get_tables() as $table) {
163
+			$query = 'UPDATE ' . $table->get_table_name();
164
+			$fields_affected = array();
165
+			$inner_query = array();
166
+			foreach ($model->_get_fields_for_table($table->get_table_alias()) as $model_field) {
167
+				if ($model_field instanceof EE_Datetime_Field) {
168
+					$inner_query[ $model_field->get_table_column() ] = $model_field->get_table_column() . ' = '
169
+																	   . $sql_date_function . '('
170
+																	   . $model_field->get_table_column()
171
+																	   . ", INTERVAL {$offset} MINUTE)";
172
+					$fields_affected[] = $model_field;
173
+				}
174
+			}
175
+			if (! $fields_affected) {
176
+				continue;
177
+			}
178
+			// do we do one query per column/field or one query for all fields on the model? It all depends on whether
179
+			// there is a date range applied or not.
180
+			if ($start_date_range instanceof DbSafeDateTime || $end_date_range instanceof DbSafeDateTime) {
181
+				$result = $this->doQueryForEachField($query, $inner_query, $start_date_range, $end_date_range);
182
+			} else {
183
+				$result = $this->doQueryForAllFields($query, $inner_query);
184
+			}
185
+
186
+			// record appropriate logs for the query
187
+			switch (true) {
188
+				case $result === false:
189
+					// record error.
190
+					$error_message = $wpdb->last_error;
191
+					// handle the edgecases where last_error might be empty.
192
+					if (! $error_message) {
193
+						$error_message = esc_html__('Unknown mysql error occured.', 'event_espresso');
194
+					}
195
+					$this->recordChangeLog($model, $original_offset, $table, $fields_affected, $error_message);
196
+					break;
197
+				case is_array($result) && ! empty($result):
198
+					foreach ($result as $field_name => $error_message) {
199
+						$this->recordChangeLog($model, $original_offset, $table, array($field_name), $error_message);
200
+					}
201
+					break;
202
+				default:
203
+					$this->recordChangeLog($model, $original_offset, $table, $fields_affected);
204
+			}
205
+		}
206
+	}
207
+
208
+
209
+	/**
210
+	 * Does the query on each $inner_query individually.
211
+	 *
212
+	 * @param string              $query
213
+	 * @param array               $inner_query
214
+	 * @param DbSafeDateTime|null $start_date_range
215
+	 * @param DbSafeDateTime|null $end_date_range
216
+	 * @return array  An array of any errors encountered and the fields they were for.
217
+	 */
218
+	private function doQueryForEachField($query, array $inner_query, $start_date_range, $end_date_range)
219
+	{
220
+		global $wpdb;
221
+		$errors = array();
222
+		foreach ($inner_query as $field_name => $field_query) {
223
+			$query_to_run = $query;
224
+			$where_conditions = array();
225
+			$query_to_run .= ' SET ' . $field_query;
226
+			if ($start_date_range instanceof DbSafeDateTime) {
227
+				$start_date = $start_date_range->format(EE_Datetime_Field::mysql_timestamp_format);
228
+				$where_conditions[] = "{$field_name} > '{$start_date}'";
229
+			}
230
+			if ($end_date_range instanceof DbSafeDateTime) {
231
+				$end_date = $end_date_range->format(EE_Datetime_Field::mysql_timestamp_format);
232
+				$where_conditions[] = "{$field_name} < '{$end_date}'";
233
+			}
234
+			if ($where_conditions) {
235
+				$query_to_run .= ' WHERE ' . implode(' AND ', $where_conditions);
236
+			}
237
+			$result = $wpdb->query($query_to_run);
238
+			if ($result === false) {
239
+				// record error.
240
+				$error_message = $wpdb->last_error;
241
+				// handle the edgecases where last_error might be empty.
242
+				if (! $error_message) {
243
+					$error_message = esc_html__('Unknown mysql error occured.', 'event_espresso');
244
+				}
245
+				$errors[ $field_name ] = $error_message;
246
+			}
247
+		}
248
+		return $errors;
249
+	}
250
+
251
+
252
+	/**
253
+	 * Performs the query for all fields within the inner_query
254
+	 *
255
+	 * @param string $query
256
+	 * @param array  $inner_query
257
+	 * @return false|int
258
+	 */
259
+	private function doQueryForAllFields($query, array $inner_query)
260
+	{
261
+		global $wpdb;
262
+		$query .= ' SET ' . implode(',', $inner_query);
263
+		return $wpdb->query($query);
264
+	}
265
+
266
+
267
+	/**
268
+	 * Records a changelog entry using the given information.
269
+	 *
270
+	 * @param EEM_Base              $model
271
+	 * @param float                 $offset
272
+	 * @param EE_Table_Base         $table
273
+	 * @param EE_Model_Field_Base[] $model_fields_affected
274
+	 * @param string                $error_message If present then there was an error so let's record that instead.
275
+	 * @throws EE_Error
276
+	 */
277
+	private function recordChangeLog(
278
+		EEM_Base $model,
279
+		$offset,
280
+		EE_Table_Base $table,
281
+		$model_fields_affected,
282
+		$error_message = ''
283
+	) {
284
+		// setup $fields list.
285
+		$fields = array();
286
+		/** @var EE_Datetime_Field $model_field */
287
+		foreach ($model_fields_affected as $model_field) {
288
+			if (! $model_field instanceof EE_Datetime_Field) {
289
+				continue;
290
+			}
291
+			$fields[] = $model_field->get_name();
292
+		}
293
+		// setup the message for the changelog entry.
294
+		$message = $error_message
295
+			? sprintf(
296
+				esc_html__(
297
+					'The %1$s table for the %2$s model did not have the offset of %3$f applied to its fields (%4$s), because of the following error:%5$s',
298
+					'event_espresso'
299
+				),
300
+				$table->get_table_name(),
301
+				$model->get_this_model_name(),
302
+				$offset,
303
+				implode(',', $fields),
304
+				$error_message
305
+			)
306
+			: sprintf(
307
+				esc_html__(
308
+					'The %1$s table for the %2$s model has had the offset of %3$f applied to its following fields: %4$s',
309
+					'event_espresso'
310
+				),
311
+				$table->get_table_name(),
312
+				$model->get_this_model_name(),
313
+				$offset,
314
+				implode(',', $fields)
315
+			);
316
+		// write to the log
317
+		$changelog = EE_Change_Log::new_instance(array(
318
+			'LOG_type'    => $error_message
319
+				? self::DATETIME_OFFSET_FIX_CHANGELOG_ERROR_TYPE
320
+				: self::DATETIME_OFFSET_FIX_CHANGELOG_TYPE,
321
+			'LOG_message' => $message,
322
+		));
323
+		$changelog->save();
324
+	}
325
+
326
+
327
+	/**
328
+	 * Returns an array of models that have datetime fields.
329
+	 * This array is added to a short lived transient cache to keep having to build this list to a minimum.
330
+	 *
331
+	 * @return array an array of model class names.
332
+	 * @throws EE_Error
333
+	 * @throws InvalidDataTypeException
334
+	 * @throws InvalidInterfaceException
335
+	 * @throws InvalidArgumentException
336
+	 */
337
+	private function getModelsWithDatetimeFields()
338
+	{
339
+		$this->getModelsToProcess();
340
+		if (! empty($this->models_with_datetime_fields)) {
341
+			return $this->models_with_datetime_fields;
342
+		}
343
+
344
+		$all_non_abstract_models = EE_Registry::instance()->non_abstract_db_models;
345
+		foreach ($all_non_abstract_models as $non_abstract_model) {
346
+			// get model instance
347
+			/** @var EEM_Base $non_abstract_model */
348
+			$non_abstract_model = $non_abstract_model::instance();
349
+			if ($non_abstract_model->get_a_field_of_type('EE_Datetime_Field') instanceof EE_Datetime_Field) {
350
+				$this->models_with_datetime_fields[] = get_class($non_abstract_model);
351
+			}
352
+		}
353
+		$this->setModelsToProcess($this->models_with_datetime_fields);
354
+		return $this->models_with_datetime_fields;
355
+	}
356
+
357
+
358
+	/**
359
+	 * This simply records the models that have been processed with our tracking option.
360
+	 *
361
+	 * @param array $models_to_set array of model class names.
362
+	 */
363
+	private function setModelsToProcess($models_to_set)
364
+	{
365
+		update_option(self::MODELS_TO_PROCESS_OPTION_KEY, $models_to_set);
366
+	}
367
+
368
+
369
+	/**
370
+	 * Used to keep track of how many models have been processed for the batch
371
+	 *
372
+	 * @param $count
373
+	 */
374
+	private function updateCountOfModelsProcessed($count = 1)
375
+	{
376
+		$count = $this->getCountOfModelsProcessed() + (int) $count;
377
+		update_option(self::COUNT_OF_MODELS_PROCESSED, $count);
378
+	}
379
+
380
+
381
+	/**
382
+	 * Retrieve the tracked number of models processed between requests.
383
+	 *
384
+	 * @return int
385
+	 */
386
+	private function getCountOfModelsProcessed()
387
+	{
388
+		return (int) get_option(self::COUNT_OF_MODELS_PROCESSED, 0);
389
+	}
390
+
391
+
392
+	/**
393
+	 * Returns the models that are left to process.
394
+	 *
395
+	 * @return array  an array of model class names.
396
+	 */
397
+	private function getModelsToProcess()
398
+	{
399
+		if (empty($this->models_with_datetime_fields)) {
400
+			$this->models_with_datetime_fields = get_option(self::MODELS_TO_PROCESS_OPTION_KEY, array());
401
+		}
402
+		return $this->models_with_datetime_fields;
403
+	}
404
+
405
+
406
+	/**
407
+	 * Used to record the offset that will be applied to dates and times for EE_Datetime_Field columns.
408
+	 *
409
+	 * @param float $offset
410
+	 */
411
+	public static function updateOffset($offset)
412
+	{
413
+		update_option(self::OFFSET_TO_APPLY_OPTION_KEY, $offset);
414
+	}
415
+
416
+
417
+	/**
418
+	 * Used to retrieve the saved offset that will be applied to dates and times for EE_Datetime_Field columns.
419
+	 *
420
+	 * @return float
421
+	 */
422
+	public static function getOffset()
423
+	{
424
+		return (float) get_option(self::OFFSET_TO_APPLY_OPTION_KEY, 0);
425
+	}
426
+
427
+
428
+	/**
429
+	 * Used to set the saved offset range start date.
430
+	 *
431
+	 * @param DbSafeDateTime|null $start_date
432
+	 */
433
+	public static function updateStartDateRange(DbSafeDateTime $start_date = null)
434
+	{
435
+		$date_to_save = $start_date instanceof DbSafeDateTime
436
+			? $start_date->format('U')
437
+			: '';
438
+		update_option(self::OPTION_KEY_OFFSET_RANGE_START_DATE, $date_to_save);
439
+	}
440
+
441
+
442
+	/**
443
+	 * Used to get the saved offset range start date.
444
+	 *
445
+	 * @return DbSafeDateTime|null
446
+	 */
447
+	public static function getStartDateRange()
448
+	{
449
+		$start_date = get_option(self::OPTION_KEY_OFFSET_RANGE_START_DATE, null);
450
+		try {
451
+			$datetime = DateTime::createFromFormat('U', $start_date, new DateTimeZone('UTC'));
452
+			$start_date = $datetime instanceof DateTime
453
+				? DbSafeDateTime::createFromDateTime($datetime)
454
+				: null;
455
+		} catch (Exception $e) {
456
+			$start_date = null;
457
+		}
458
+		return $start_date;
459
+	}
460
+
461
+
462
+	/**
463
+	 * Used to set the saved offset range end date.
464
+	 *
465
+	 * @param DbSafeDateTime|null $end_date
466
+	 */
467
+	public static function updateEndDateRange(DbSafeDateTime $end_date = null)
468
+	{
469
+		$date_to_save = $end_date instanceof DbSafeDateTime
470
+			? $end_date->format('U')
471
+			: '';
472
+		update_option(self::OPTION_KEY_OFFSET_RANGE_END_DATE, $date_to_save);
473
+	}
474
+
475
+
476
+	/**
477
+	 * Used to get the saved offset range end date.
478
+	 *
479
+	 * @return DbSafeDateTime|null
480
+	 */
481
+	public static function getEndDateRange()
482
+	{
483
+		$end_date = get_option(self::OPTION_KEY_OFFSET_RANGE_END_DATE, null);
484
+		try {
485
+			$datetime = DateTime::createFromFormat('U', $end_date, new DateTimeZone('UTC'));
486
+			$end_date = $datetime instanceof Datetime
487
+				? DbSafeDateTime::createFromDateTime($datetime)
488
+				: null;
489
+		} catch (Exception $e) {
490
+			$end_date = null;
491
+		}
492
+		return $end_date;
493
+	}
494 494
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -160,19 +160,19 @@  discard block
 block discarded – undo
160 160
         $date_ranges = array();
161 161
         // since some affected models might have two tables, we have to get our tables and set up a query for each table.
162 162
         foreach ($model->get_tables() as $table) {
163
-            $query = 'UPDATE ' . $table->get_table_name();
163
+            $query = 'UPDATE '.$table->get_table_name();
164 164
             $fields_affected = array();
165 165
             $inner_query = array();
166 166
             foreach ($model->_get_fields_for_table($table->get_table_alias()) as $model_field) {
167 167
                 if ($model_field instanceof EE_Datetime_Field) {
168
-                    $inner_query[ $model_field->get_table_column() ] = $model_field->get_table_column() . ' = '
169
-                                                                       . $sql_date_function . '('
168
+                    $inner_query[$model_field->get_table_column()] = $model_field->get_table_column().' = '
169
+                                                                       . $sql_date_function.'('
170 170
                                                                        . $model_field->get_table_column()
171 171
                                                                        . ", INTERVAL {$offset} MINUTE)";
172 172
                     $fields_affected[] = $model_field;
173 173
                 }
174 174
             }
175
-            if (! $fields_affected) {
175
+            if ( ! $fields_affected) {
176 176
                 continue;
177 177
             }
178 178
             // do we do one query per column/field or one query for all fields on the model? It all depends on whether
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
                     // record error.
190 190
                     $error_message = $wpdb->last_error;
191 191
                     // handle the edgecases where last_error might be empty.
192
-                    if (! $error_message) {
192
+                    if ( ! $error_message) {
193 193
                         $error_message = esc_html__('Unknown mysql error occured.', 'event_espresso');
194 194
                     }
195 195
                     $this->recordChangeLog($model, $original_offset, $table, $fields_affected, $error_message);
@@ -222,7 +222,7 @@  discard block
 block discarded – undo
222 222
         foreach ($inner_query as $field_name => $field_query) {
223 223
             $query_to_run = $query;
224 224
             $where_conditions = array();
225
-            $query_to_run .= ' SET ' . $field_query;
225
+            $query_to_run .= ' SET '.$field_query;
226 226
             if ($start_date_range instanceof DbSafeDateTime) {
227 227
                 $start_date = $start_date_range->format(EE_Datetime_Field::mysql_timestamp_format);
228 228
                 $where_conditions[] = "{$field_name} > '{$start_date}'";
@@ -232,17 +232,17 @@  discard block
 block discarded – undo
232 232
                 $where_conditions[] = "{$field_name} < '{$end_date}'";
233 233
             }
234 234
             if ($where_conditions) {
235
-                $query_to_run .= ' WHERE ' . implode(' AND ', $where_conditions);
235
+                $query_to_run .= ' WHERE '.implode(' AND ', $where_conditions);
236 236
             }
237 237
             $result = $wpdb->query($query_to_run);
238 238
             if ($result === false) {
239 239
                 // record error.
240 240
                 $error_message = $wpdb->last_error;
241 241
                 // handle the edgecases where last_error might be empty.
242
-                if (! $error_message) {
242
+                if ( ! $error_message) {
243 243
                     $error_message = esc_html__('Unknown mysql error occured.', 'event_espresso');
244 244
                 }
245
-                $errors[ $field_name ] = $error_message;
245
+                $errors[$field_name] = $error_message;
246 246
             }
247 247
         }
248 248
         return $errors;
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
259 259
     private function doQueryForAllFields($query, array $inner_query)
260 260
     {
261 261
         global $wpdb;
262
-        $query .= ' SET ' . implode(',', $inner_query);
262
+        $query .= ' SET '.implode(',', $inner_query);
263 263
         return $wpdb->query($query);
264 264
     }
265 265
 
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
         $fields = array();
286 286
         /** @var EE_Datetime_Field $model_field */
287 287
         foreach ($model_fields_affected as $model_field) {
288
-            if (! $model_field instanceof EE_Datetime_Field) {
288
+            if ( ! $model_field instanceof EE_Datetime_Field) {
289 289
                 continue;
290 290
             }
291 291
             $fields[] = $model_field->get_name();
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
     private function getModelsWithDatetimeFields()
338 338
     {
339 339
         $this->getModelsToProcess();
340
-        if (! empty($this->models_with_datetime_fields)) {
340
+        if ( ! empty($this->models_with_datetime_fields)) {
341 341
             return $this->models_with_datetime_fields;
342 342
         }
343 343
 
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/RegistrationsReport.php 2 patches
Indentation   +504 added lines, -504 removed lines patch added patch discarded remove patch
@@ -19,523 +19,523 @@
 block discarded – undo
19 19
  */
20 20
 class RegistrationsReport extends JobHandlerFile
21 21
 {
22
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
23
-    // phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
24
-    /**
25
-     * Performs any necessary setup for starting the job. This is also a good
26
-     * place to setup the $job_arguments which will be used for subsequent HTTP requests
27
-     * when continue_job will be called
28
-     *
29
-     * @param JobParameters $job_parameters
30
-     * @throws BatchRequestException
31
-     * @return JobStepResponse
32
-     */
33
-    public function create_job(JobParameters $job_parameters)
34
-    {
35
-        $event_id = intval($job_parameters->request_datum('EVT_ID', '0'));
36
-        if (! \EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
37
-            throw new BatchRequestException(__('You do not have permission to view registrations', 'event_espresso'));
38
-        }
39
-        $filepath = $this->create_file_from_job_with_name(
40
-            $job_parameters->job_id(),
41
-            $this->get_filename($event_id)
42
-        );
43
-        $job_parameters->add_extra_data('filepath', $filepath);
44
-        if ($job_parameters->request_datum('use_filters', false)) {
45
-            $query_params = maybe_unserialize(stripslashes($job_parameters->request_datum('filters', array())));
46
-        } else {
47
-            $query_params = apply_filters('FHEE__EE_Export__report_registration_for_event', array(
48
-                array(
49
-                    'OR'                 => array(
50
-                        // don't include registrations from failed or abandoned transactions...
51
-                        'Transaction.STS_ID' => array(
52
-                            'NOT IN',
53
-                            array(
54
-                                \EEM_Transaction::failed_status_code,
55
-                                \EEM_Transaction::abandoned_status_code,
56
-                            ),
57
-                        ),
58
-                        // unless the registration is approved, in which case include it regardless of transaction status
59
-                        'STS_ID'             => \EEM_Registration::status_id_approved,
60
-                    ),
61
-                    'Ticket.TKT_deleted' => array('IN', array(true, false)),
62
-                ),
63
-                'order_by'   => array('Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'),
64
-                'force_join' => array('Transaction', 'Ticket', 'Attendee'),
65
-                'caps'       => \EEM_Base::caps_read_admin,
66
-            ), $event_id);
67
-            if ($event_id) {
68
-                $query_params[0]['EVT_ID'] = $event_id;
69
-            } else {
70
-                $query_params['force_join'][] = 'Event';
71
-            }
72
-        }
73
-        if (! isset($query_params['force_join'])) {
74
-            $query_params['force_join'] = array('Event', 'Transaction', 'Ticket', 'Attendee');
75
-        }
76
-        $job_parameters->add_extra_data('query_params', $query_params);
77
-        $question_labels = $this->_get_question_labels($query_params);
78
-        $job_parameters->add_extra_data('question_labels', $question_labels);
79
-        $job_parameters->set_job_size(
80
-            \EEM_Registration::instance()->count(
81
-                array_diff_key(
82
-                    $query_params,
83
-                    array_flip(
84
-                        array('limit')
85
-                    )
86
-                )
87
-            )
88
-        );
89
-        // we should also set the header columns
90
-        $csv_data_for_row = $this->get_csv_data_for(
91
-            $event_id,
92
-            0,
93
-            1,
94
-            $job_parameters->extra_datum('question_labels'),
95
-            $job_parameters->extra_datum('query_params')
96
-        );
97
-        \EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true);
98
-        // if we actually processed a row there, record it
99
-        if ($job_parameters->job_size()) {
100
-            $job_parameters->mark_processed(1);
101
-        }
102
-        return new JobStepResponse(
103
-            $job_parameters,
104
-            __('Registrations report started successfully...', 'event_espresso')
105
-        );
106
-    }
22
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
23
+	// phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
24
+	/**
25
+	 * Performs any necessary setup for starting the job. This is also a good
26
+	 * place to setup the $job_arguments which will be used for subsequent HTTP requests
27
+	 * when continue_job will be called
28
+	 *
29
+	 * @param JobParameters $job_parameters
30
+	 * @throws BatchRequestException
31
+	 * @return JobStepResponse
32
+	 */
33
+	public function create_job(JobParameters $job_parameters)
34
+	{
35
+		$event_id = intval($job_parameters->request_datum('EVT_ID', '0'));
36
+		if (! \EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
37
+			throw new BatchRequestException(__('You do not have permission to view registrations', 'event_espresso'));
38
+		}
39
+		$filepath = $this->create_file_from_job_with_name(
40
+			$job_parameters->job_id(),
41
+			$this->get_filename($event_id)
42
+		);
43
+		$job_parameters->add_extra_data('filepath', $filepath);
44
+		if ($job_parameters->request_datum('use_filters', false)) {
45
+			$query_params = maybe_unserialize(stripslashes($job_parameters->request_datum('filters', array())));
46
+		} else {
47
+			$query_params = apply_filters('FHEE__EE_Export__report_registration_for_event', array(
48
+				array(
49
+					'OR'                 => array(
50
+						// don't include registrations from failed or abandoned transactions...
51
+						'Transaction.STS_ID' => array(
52
+							'NOT IN',
53
+							array(
54
+								\EEM_Transaction::failed_status_code,
55
+								\EEM_Transaction::abandoned_status_code,
56
+							),
57
+						),
58
+						// unless the registration is approved, in which case include it regardless of transaction status
59
+						'STS_ID'             => \EEM_Registration::status_id_approved,
60
+					),
61
+					'Ticket.TKT_deleted' => array('IN', array(true, false)),
62
+				),
63
+				'order_by'   => array('Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'),
64
+				'force_join' => array('Transaction', 'Ticket', 'Attendee'),
65
+				'caps'       => \EEM_Base::caps_read_admin,
66
+			), $event_id);
67
+			if ($event_id) {
68
+				$query_params[0]['EVT_ID'] = $event_id;
69
+			} else {
70
+				$query_params['force_join'][] = 'Event';
71
+			}
72
+		}
73
+		if (! isset($query_params['force_join'])) {
74
+			$query_params['force_join'] = array('Event', 'Transaction', 'Ticket', 'Attendee');
75
+		}
76
+		$job_parameters->add_extra_data('query_params', $query_params);
77
+		$question_labels = $this->_get_question_labels($query_params);
78
+		$job_parameters->add_extra_data('question_labels', $question_labels);
79
+		$job_parameters->set_job_size(
80
+			\EEM_Registration::instance()->count(
81
+				array_diff_key(
82
+					$query_params,
83
+					array_flip(
84
+						array('limit')
85
+					)
86
+				)
87
+			)
88
+		);
89
+		// we should also set the header columns
90
+		$csv_data_for_row = $this->get_csv_data_for(
91
+			$event_id,
92
+			0,
93
+			1,
94
+			$job_parameters->extra_datum('question_labels'),
95
+			$job_parameters->extra_datum('query_params')
96
+		);
97
+		\EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true);
98
+		// if we actually processed a row there, record it
99
+		if ($job_parameters->job_size()) {
100
+			$job_parameters->mark_processed(1);
101
+		}
102
+		return new JobStepResponse(
103
+			$job_parameters,
104
+			__('Registrations report started successfully...', 'event_espresso')
105
+		);
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * Gets the filename
111
-     *
112
-     * @return string
113
-     */
114
-    protected function get_filename()
115
-    {
116
-        return sprintf("event-espresso-registrations-%s.csv", str_replace(':', '-', current_time('mysql')));
117
-    }
109
+	/**
110
+	 * Gets the filename
111
+	 *
112
+	 * @return string
113
+	 */
114
+	protected function get_filename()
115
+	{
116
+		return sprintf("event-espresso-registrations-%s.csv", str_replace(':', '-', current_time('mysql')));
117
+	}
118 118
 
119 119
 
120
-    /**
121
-     * Gets the questions which are to be used for this report, so they
122
-     * can be remembered for later
123
-     *
124
-     * @param array $registration_query_params
125
-     * @return array question admin labels to be used for this report
126
-     */
127
-    protected function _get_question_labels($registration_query_params)
128
-    {
129
-        $where = isset($registration_query_params[0]) ? $registration_query_params[0] : null;
130
-        $question_query_params = array();
131
-        if ($where !== null) {
132
-            $question_query_params = array(
133
-                $this->_change_registration_where_params_to_question_where_params($registration_query_params[0]),
134
-            );
135
-        }
136
-        $question_query_params[0]['QST_system'] = array(
137
-            'NOT_IN',
138
-            array_keys(\EEM_Attendee::instance()->system_question_to_attendee_field_mapping()),
139
-        );
140
-        if (apply_filters(
141
-            'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport___get_question_labels__only_include_answered_questions',
142
-            false,
143
-            $registration_query_params
144
-        )) {
145
-            $question_query_params[0]['Answer.ANS_ID'] = array('IS_NOT_NULL');
146
-        }
147
-        $question_query_params['group_by'] = array('QST_ID');
148
-        return array_unique(\EEM_Question::instance()->get_col($question_query_params, 'QST_admin_label'));
149
-    }
120
+	/**
121
+	 * Gets the questions which are to be used for this report, so they
122
+	 * can be remembered for later
123
+	 *
124
+	 * @param array $registration_query_params
125
+	 * @return array question admin labels to be used for this report
126
+	 */
127
+	protected function _get_question_labels($registration_query_params)
128
+	{
129
+		$where = isset($registration_query_params[0]) ? $registration_query_params[0] : null;
130
+		$question_query_params = array();
131
+		if ($where !== null) {
132
+			$question_query_params = array(
133
+				$this->_change_registration_where_params_to_question_where_params($registration_query_params[0]),
134
+			);
135
+		}
136
+		$question_query_params[0]['QST_system'] = array(
137
+			'NOT_IN',
138
+			array_keys(\EEM_Attendee::instance()->system_question_to_attendee_field_mapping()),
139
+		);
140
+		if (apply_filters(
141
+			'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport___get_question_labels__only_include_answered_questions',
142
+			false,
143
+			$registration_query_params
144
+		)) {
145
+			$question_query_params[0]['Answer.ANS_ID'] = array('IS_NOT_NULL');
146
+		}
147
+		$question_query_params['group_by'] = array('QST_ID');
148
+		return array_unique(\EEM_Question::instance()->get_col($question_query_params, 'QST_admin_label'));
149
+	}
150 150
 
151 151
 
152
-    /**
153
-     * Takes where params meant for registrations and changes them to work for questions
154
-     *
155
-     * @param array $reg_where_params
156
-     * @return array
157
-     */
158
-    protected function _change_registration_where_params_to_question_where_params($reg_where_params)
159
-    {
160
-        $question_where_params = array();
161
-        foreach ($reg_where_params as $key => $val) {
162
-            if (\EEM_Registration::instance()->is_logic_query_param_key($key)) {
163
-                $question_where_params[ $key ] = $this->_change_registration_where_params_to_question_where_params($val);
164
-            } else {
165
-                // it's a normal where condition
166
-                $question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
167
-            }
168
-        }
169
-        return $question_where_params;
170
-    }
152
+	/**
153
+	 * Takes where params meant for registrations and changes them to work for questions
154
+	 *
155
+	 * @param array $reg_where_params
156
+	 * @return array
157
+	 */
158
+	protected function _change_registration_where_params_to_question_where_params($reg_where_params)
159
+	{
160
+		$question_where_params = array();
161
+		foreach ($reg_where_params as $key => $val) {
162
+			if (\EEM_Registration::instance()->is_logic_query_param_key($key)) {
163
+				$question_where_params[ $key ] = $this->_change_registration_where_params_to_question_where_params($val);
164
+			} else {
165
+				// it's a normal where condition
166
+				$question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
167
+			}
168
+		}
169
+		return $question_where_params;
170
+	}
171 171
 
172 172
 
173
-    /**
174
-     * Performs another step of the job
175
-     *
176
-     * @param JobParameters $job_parameters
177
-     * @param int           $batch_size
178
-     * @return JobStepResponse
179
-     * @throws \EE_Error
180
-     */
181
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
182
-    {
183
-        if ($job_parameters->units_processed() < $job_parameters->job_size()) {
184
-            $csv_data = $this->get_csv_data_for(
185
-                $job_parameters->request_datum('EVT_ID', '0'),
186
-                $job_parameters->units_processed(),
187
-                $batch_size,
188
-                $job_parameters->extra_datum('question_labels'),
189
-                $job_parameters->extra_datum('query_params')
190
-            );
191
-            \EEH_Export::write_data_array_to_csv($job_parameters->extra_datum('filepath'), $csv_data, false);
192
-            $units_processed = count($csv_data);
193
-        } else {
194
-            $units_processed = 0;
195
-        }
196
-        $job_parameters->mark_processed($units_processed);
197
-        $extra_response_data = array(
198
-            'file_url' => '',
199
-        );
200
-        if ($units_processed < $batch_size) {
201
-            $job_parameters->set_status(JobParameters::status_complete);
202
-            $extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
203
-        }
173
+	/**
174
+	 * Performs another step of the job
175
+	 *
176
+	 * @param JobParameters $job_parameters
177
+	 * @param int           $batch_size
178
+	 * @return JobStepResponse
179
+	 * @throws \EE_Error
180
+	 */
181
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
182
+	{
183
+		if ($job_parameters->units_processed() < $job_parameters->job_size()) {
184
+			$csv_data = $this->get_csv_data_for(
185
+				$job_parameters->request_datum('EVT_ID', '0'),
186
+				$job_parameters->units_processed(),
187
+				$batch_size,
188
+				$job_parameters->extra_datum('question_labels'),
189
+				$job_parameters->extra_datum('query_params')
190
+			);
191
+			\EEH_Export::write_data_array_to_csv($job_parameters->extra_datum('filepath'), $csv_data, false);
192
+			$units_processed = count($csv_data);
193
+		} else {
194
+			$units_processed = 0;
195
+		}
196
+		$job_parameters->mark_processed($units_processed);
197
+		$extra_response_data = array(
198
+			'file_url' => '',
199
+		);
200
+		if ($units_processed < $batch_size) {
201
+			$job_parameters->set_status(JobParameters::status_complete);
202
+			$extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
203
+		}
204 204
 
205
-        return new JobStepResponse(
206
-            $job_parameters,
207
-            sprintf(__('Wrote %1$s rows to report CSV file...', 'event_espresso'), count($csv_data)),
208
-            $extra_response_data
209
-        );
210
-    }
205
+		return new JobStepResponse(
206
+			$job_parameters,
207
+			sprintf(__('Wrote %1$s rows to report CSV file...', 'event_espresso'), count($csv_data)),
208
+			$extra_response_data
209
+		);
210
+	}
211 211
 
212 212
 
213
-    /**
214
-     * Gets the csv data for a batch of registrations
215
-     *
216
-     * @param int|null $event_id
217
-     * @param int      $offset
218
-     * @param int      $limit
219
-     * @param array    $question_labels the IDs for all the questions which were answered by someone in this selection
220
-     * @param array    $query_params    for using where querying the model
221
-     * @return array top-level keys are numeric, next-level keys are column headers
222
-     */
223
-    public function get_csv_data_for($event_id, $offset, $limit, $question_labels, $query_params)
224
-    {
225
-        $reg_fields_to_include = array(
226
-            'TXN_ID',
227
-            'ATT_ID',
228
-            'REG_ID',
229
-            'REG_date',
230
-            'REG_code',
231
-            'REG_count',
232
-            'REG_final_price',
233
-        );
234
-        $att_fields_to_include = array(
235
-            'ATT_fname',
236
-            'ATT_lname',
237
-            'ATT_email',
238
-            'ATT_address',
239
-            'ATT_address2',
240
-            'ATT_city',
241
-            'STA_ID',
242
-            'CNT_ISO',
243
-            'ATT_zip',
244
-            'ATT_phone',
245
-        );
246
-        $registrations_csv_ready_array = array();
247
-        $reg_model = \EE_Registry::instance()->load_model('Registration');
248
-        $query_params['limit'] = array($offset, $limit);
249
-        $registration_rows = $reg_model->get_all_wpdb_results($query_params);
250
-        $registration_ids = array();
251
-        foreach ($registration_rows as $reg_row) {
252
-            $registration_ids[] = intval($reg_row['Registration.REG_ID']);
253
-        }
254
-        foreach ($registration_rows as $reg_row) {
255
-            if (is_array($reg_row)) {
256
-                $reg_csv_array = array();
257
-                if (! $event_id) {
258
-                    // get the event's name and Id
259
-                    $reg_csv_array[ __('Event', 'event_espresso') ] = sprintf(
260
-                        __('%1$s (%2$s)', 'event_espresso'),
261
-                        \EEH_Export::prepare_value_from_db_for_display(
262
-                            \EEM_Event::instance(),
263
-                            'EVT_name',
264
-                            $reg_row['Event_CPT.post_title']
265
-                        ),
266
-                        $reg_row['Event_CPT.ID']
267
-                    );
268
-                }
269
-                $is_primary_reg = $reg_row['Registration.REG_count'] == '1' ? true : false;
270
-                /*@var $reg_row EE_Registration */
271
-                foreach ($reg_fields_to_include as $field_name) {
272
-                    $field = $reg_model->field_settings_for($field_name);
273
-                    if ($field_name == 'REG_final_price') {
274
-                        $value = \EEH_Export::prepare_value_from_db_for_display(
275
-                            $reg_model,
276
-                            $field_name,
277
-                            $reg_row['Registration.REG_final_price'],
278
-                            'localized_float'
279
-                        );
280
-                    } elseif ($field_name == 'REG_count') {
281
-                        $value = sprintf(
282
-                            __('%1$s of %2$s', 'event_espresso'),
283
-                            \EEH_Export::prepare_value_from_db_for_display(
284
-                                $reg_model,
285
-                                'REG_count',
286
-                                $reg_row['Registration.REG_count']
287
-                            ),
288
-                            \EEH_Export::prepare_value_from_db_for_display(
289
-                                $reg_model,
290
-                                'REG_group_size',
291
-                                $reg_row['Registration.REG_group_size']
292
-                            )
293
-                        );
294
-                    } elseif ($field_name == 'REG_date') {
295
-                        $value = \EEH_Export::prepare_value_from_db_for_display(
296
-                            $reg_model,
297
-                            $field_name,
298
-                            $reg_row['Registration.REG_date'],
299
-                            'no_html'
300
-                        );
301
-                    } else {
302
-                        $value = \EEH_Export::prepare_value_from_db_for_display(
303
-                            $reg_model,
304
-                            $field_name,
305
-                            $reg_row[ $field->get_qualified_column() ]
306
-                        );
307
-                    }
308
-                    $reg_csv_array[ \EEH_Export::get_column_name_for_field($field) ] = $value;
309
-                    if ($field_name == 'REG_final_price') {
310
-                        // add a column named Currency after the final price
311
-                        $reg_csv_array[ __("Currency", "event_espresso") ] = \EE_Config::instance()->currency->code;
312
-                    }
313
-                }
314
-                // get pretty status
315
-                $stati = \EEM_Status::instance()->localized_status(
316
-                    array(
317
-                        $reg_row['Registration.STS_ID']     => __('unknown', 'event_espresso'),
318
-                        $reg_row['TransactionTable.STS_ID'] => __('unknown', 'event_espresso'),
319
-                    ),
320
-                    false,
321
-                    'sentence'
322
-                );
323
-                $reg_csv_array[ __("Registration Status", 'event_espresso') ] = $stati[ $reg_row['Registration.STS_ID'] ];
324
-                // get pretty transaction status
325
-                $reg_csv_array[ __("Transaction Status", 'event_espresso') ] = $stati[ $reg_row['TransactionTable.STS_ID'] ];
326
-                $reg_csv_array[ __('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
327
-                    ? \EEH_Export::prepare_value_from_db_for_display(
328
-                        \EEM_Transaction::instance(),
329
-                        'TXN_total',
330
-                        $reg_row['TransactionTable.TXN_total'],
331
-                        'localized_float'
332
-                    ) : '0.00';
333
-                $reg_csv_array[ __('Amount Paid', 'event_espresso') ] = $is_primary_reg
334
-                    ? \EEH_Export::prepare_value_from_db_for_display(
335
-                        \EEM_Transaction::instance(),
336
-                        'TXN_paid',
337
-                        $reg_row['TransactionTable.TXN_paid'],
338
-                        'localized_float'
339
-                    ) : '0.00';
340
-                $payment_methods = array();
341
-                $gateway_txn_ids_etc = array();
342
-                $payment_times = array();
343
-                if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) {
344
-                    $payments_info = \EEM_Payment::instance()->get_all_wpdb_results(
345
-                        array(
346
-                            array(
347
-                                'TXN_ID' => $reg_row['TransactionTable.TXN_ID'],
348
-                                'STS_ID' => \EEM_Payment::status_id_approved,
349
-                            ),
350
-                            'force_join' => array('Payment_Method'),
351
-                        ),
352
-                        ARRAY_A,
353
-                        'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time'
354
-                    );
355
-                    foreach ($payments_info as $payment_method_and_gateway_txn_id) {
356
-                        $payment_methods[] = isset($payment_method_and_gateway_txn_id['name'])
357
-                            ? $payment_method_and_gateway_txn_id['name'] : __('Unknown', 'event_espresso');
358
-                        $gateway_txn_ids_etc[] = isset($payment_method_and_gateway_txn_id['gateway_txn_id'])
359
-                            ? $payment_method_and_gateway_txn_id['gateway_txn_id'] : '';
360
-                        $payment_times[] = isset($payment_method_and_gateway_txn_id['payment_time'])
361
-                            ? $payment_method_and_gateway_txn_id['payment_time'] : '';
362
-                    }
363
-                }
364
-                $reg_csv_array[ __('Payment Date(s)', 'event_espresso') ] = implode(',', $payment_times);
365
-                $reg_csv_array[ __('Payment Method(s)', 'event_espresso') ] = implode(",", $payment_methods);
366
-                $reg_csv_array[ __('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
367
-                    ',',
368
-                    $gateway_txn_ids_etc
369
-                );
370
-                // get whether or not the user has checked in
371
-                $reg_csv_array[ __("Check-Ins", "event_espresso") ] = $reg_model->count_related(
372
-                    $reg_row['Registration.REG_ID'],
373
-                    'Checkin'
374
-                );
375
-                // get ticket of registration and its price
376
-                $ticket_model = \EE_Registry::instance()->load_model('Ticket');
377
-                if ($reg_row['Ticket.TKT_ID']) {
378
-                    $ticket_name = \EEH_Export::prepare_value_from_db_for_display(
379
-                        $ticket_model,
380
-                        'TKT_name',
381
-                        $reg_row['Ticket.TKT_name']
382
-                    );
383
-                    $datetimes_strings = array();
384
-                    foreach (\EEM_Datetime::instance()->get_all_wpdb_results(
385
-                        array(
386
-                            array('Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']),
387
-                            'order_by'                 => array('DTT_EVT_start' => 'ASC'),
388
-                            'default_where_conditions' => 'none',
389
-                        )
390
-                    ) as $datetime) {
391
-                        $datetimes_strings[] = \EEH_Export::prepare_value_from_db_for_display(
392
-                            \EEM_Datetime::instance(),
393
-                            'DTT_EVT_start',
394
-                            $datetime['Datetime.DTT_EVT_start']
395
-                        );
396
-                    }
397
-                } else {
398
-                    $ticket_name = __('Unknown', 'event_espresso');
399
-                    $datetimes_strings = array(__('Unknown', 'event_espresso'));
400
-                }
401
-                $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
402
-                $reg_csv_array[ __("Datetimes of Ticket", "event_espresso") ] = implode(", ", $datetimes_strings);
403
-                // get datetime(s) of registration
404
-                // add attendee columns
405
-                foreach ($att_fields_to_include as $att_field_name) {
406
-                    $field_obj = \EEM_Attendee::instance()->field_settings_for($att_field_name);
407
-                    if ($reg_row['Attendee_CPT.ID']) {
408
-                        if ($att_field_name == 'STA_ID') {
409
-                            $value = \EEM_State::instance()->get_var(
410
-                                array(array('STA_ID' => $reg_row['Attendee_Meta.STA_ID'])),
411
-                                'STA_name'
412
-                            );
413
-                        } elseif ($att_field_name == 'CNT_ISO') {
414
-                            $value = \EEM_Country::instance()->get_var(
415
-                                array(array('CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO'])),
416
-                                'CNT_name'
417
-                            );
418
-                        } else {
419
-                            $value = \EEH_Export::prepare_value_from_db_for_display(
420
-                                \EEM_Attendee::instance(),
421
-                                $att_field_name,
422
-                                $reg_row[ $field_obj->get_qualified_column() ]
423
-                            );
424
-                        }
425
-                    } else {
426
-                        $value = '';
427
-                    }
428
-                    $reg_csv_array[ \EEH_Export::get_column_name_for_field($field_obj) ] = $value;
429
-                }
430
-                // make sure each registration has the same questions in the same order
431
-                foreach ($question_labels as $question_label) {
432
-                    if (! isset($reg_csv_array[ $question_label ])) {
433
-                        $reg_csv_array[ $question_label ] = null;
434
-                    }
435
-                }
436
-                $answers = \EEM_Answer::instance()->get_all_wpdb_results(array(
437
-                    array('REG_ID' => $reg_row['Registration.REG_ID']),
438
-                    'force_join' => array('Question'),
439
-                ));
440
-                // now fill out the questions THEY answered
441
-                foreach ($answers as $answer_row) {
442
-                    if ($answer_row['Question.QST_ID']) {
443
-                        $question_label = \EEH_Export::prepare_value_from_db_for_display(
444
-                            \EEM_Question::instance(),
445
-                            'QST_admin_label',
446
-                            $answer_row['Question.QST_admin_label']
447
-                        );
448
-                    } else {
449
-                        $question_label = sprintf(__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']);
450
-                    }
451
-                    if (isset($answer_row['Question.QST_type'])
452
-                        && $answer_row['Question.QST_type'] == \EEM_Question::QST_type_state
453
-                    ) {
454
-                        $reg_csv_array[ $question_label ] = \EEM_State::instance()->get_state_name_by_ID(
455
-                            $answer_row['Answer.ANS_value']
456
-                        );
457
-                    } else {
458
-                        // this isn't for html, so don't show html entities
459
-                        $reg_csv_array[ $question_label ] = html_entity_decode(
460
-                            \EEH_Export::prepare_value_from_db_for_display(
461
-                                \EEM_Answer::instance(),
462
-                                'ANS_value',
463
-                                $answer_row['Answer.ANS_value']
464
-                            )
465
-                        );
466
-                    }
467
-                }
468
-                /**
469
-                 * Filter to change the contents of each row of the registrations report CSV file.
470
-                 * This can be used to add or remote columns from the CSV file, or change their values.                 *
471
-                 * Note: it has this name because originally that's where this filter resided,
472
-                 * and we've left its name as-is for backward compatibility.
473
-                 * Note when using: all rows in the CSV should have the same columns.
474
-                 *
475
-                 * @param array $reg_csv_array keys are column-header names, and values are that columns' value
476
-                 *                             in this row
477
-                 * @param array $reg_row       is the row from the database's wp_esp_registration table
478
-                 */
479
-                $registrations_csv_ready_array[] = apply_filters(
480
-                    'FHEE__EE_Export__report_registrations__reg_csv_array',
481
-                    $reg_csv_array,
482
-                    $reg_row
483
-                );
484
-            }
485
-        }
486
-        // if we couldn't export anything, we want to at least show the column headers
487
-        if (empty($registrations_csv_ready_array)) {
488
-            $reg_csv_array = array();
489
-            $model_and_fields_to_include = array(
490
-                'Registration' => $reg_fields_to_include,
491
-                'Attendee'     => $att_fields_to_include,
492
-            );
493
-            foreach ($model_and_fields_to_include as $model_name => $field_list) {
494
-                $model = \EE_Registry::instance()->load_model($model_name);
495
-                foreach ($field_list as $field_name) {
496
-                    $field = $model->field_settings_for($field_name);
497
-                    $reg_csv_array[ \EEH_Export::get_column_name_for_field($field) ] = null;
498
-                }
499
-            }
500
-            $registrations_csv_ready_array[] = $reg_csv_array;
501
-        }
502
-        return $registrations_csv_ready_array;
503
-    }
213
+	/**
214
+	 * Gets the csv data for a batch of registrations
215
+	 *
216
+	 * @param int|null $event_id
217
+	 * @param int      $offset
218
+	 * @param int      $limit
219
+	 * @param array    $question_labels the IDs for all the questions which were answered by someone in this selection
220
+	 * @param array    $query_params    for using where querying the model
221
+	 * @return array top-level keys are numeric, next-level keys are column headers
222
+	 */
223
+	public function get_csv_data_for($event_id, $offset, $limit, $question_labels, $query_params)
224
+	{
225
+		$reg_fields_to_include = array(
226
+			'TXN_ID',
227
+			'ATT_ID',
228
+			'REG_ID',
229
+			'REG_date',
230
+			'REG_code',
231
+			'REG_count',
232
+			'REG_final_price',
233
+		);
234
+		$att_fields_to_include = array(
235
+			'ATT_fname',
236
+			'ATT_lname',
237
+			'ATT_email',
238
+			'ATT_address',
239
+			'ATT_address2',
240
+			'ATT_city',
241
+			'STA_ID',
242
+			'CNT_ISO',
243
+			'ATT_zip',
244
+			'ATT_phone',
245
+		);
246
+		$registrations_csv_ready_array = array();
247
+		$reg_model = \EE_Registry::instance()->load_model('Registration');
248
+		$query_params['limit'] = array($offset, $limit);
249
+		$registration_rows = $reg_model->get_all_wpdb_results($query_params);
250
+		$registration_ids = array();
251
+		foreach ($registration_rows as $reg_row) {
252
+			$registration_ids[] = intval($reg_row['Registration.REG_ID']);
253
+		}
254
+		foreach ($registration_rows as $reg_row) {
255
+			if (is_array($reg_row)) {
256
+				$reg_csv_array = array();
257
+				if (! $event_id) {
258
+					// get the event's name and Id
259
+					$reg_csv_array[ __('Event', 'event_espresso') ] = sprintf(
260
+						__('%1$s (%2$s)', 'event_espresso'),
261
+						\EEH_Export::prepare_value_from_db_for_display(
262
+							\EEM_Event::instance(),
263
+							'EVT_name',
264
+							$reg_row['Event_CPT.post_title']
265
+						),
266
+						$reg_row['Event_CPT.ID']
267
+					);
268
+				}
269
+				$is_primary_reg = $reg_row['Registration.REG_count'] == '1' ? true : false;
270
+				/*@var $reg_row EE_Registration */
271
+				foreach ($reg_fields_to_include as $field_name) {
272
+					$field = $reg_model->field_settings_for($field_name);
273
+					if ($field_name == 'REG_final_price') {
274
+						$value = \EEH_Export::prepare_value_from_db_for_display(
275
+							$reg_model,
276
+							$field_name,
277
+							$reg_row['Registration.REG_final_price'],
278
+							'localized_float'
279
+						);
280
+					} elseif ($field_name == 'REG_count') {
281
+						$value = sprintf(
282
+							__('%1$s of %2$s', 'event_espresso'),
283
+							\EEH_Export::prepare_value_from_db_for_display(
284
+								$reg_model,
285
+								'REG_count',
286
+								$reg_row['Registration.REG_count']
287
+							),
288
+							\EEH_Export::prepare_value_from_db_for_display(
289
+								$reg_model,
290
+								'REG_group_size',
291
+								$reg_row['Registration.REG_group_size']
292
+							)
293
+						);
294
+					} elseif ($field_name == 'REG_date') {
295
+						$value = \EEH_Export::prepare_value_from_db_for_display(
296
+							$reg_model,
297
+							$field_name,
298
+							$reg_row['Registration.REG_date'],
299
+							'no_html'
300
+						);
301
+					} else {
302
+						$value = \EEH_Export::prepare_value_from_db_for_display(
303
+							$reg_model,
304
+							$field_name,
305
+							$reg_row[ $field->get_qualified_column() ]
306
+						);
307
+					}
308
+					$reg_csv_array[ \EEH_Export::get_column_name_for_field($field) ] = $value;
309
+					if ($field_name == 'REG_final_price') {
310
+						// add a column named Currency after the final price
311
+						$reg_csv_array[ __("Currency", "event_espresso") ] = \EE_Config::instance()->currency->code;
312
+					}
313
+				}
314
+				// get pretty status
315
+				$stati = \EEM_Status::instance()->localized_status(
316
+					array(
317
+						$reg_row['Registration.STS_ID']     => __('unknown', 'event_espresso'),
318
+						$reg_row['TransactionTable.STS_ID'] => __('unknown', 'event_espresso'),
319
+					),
320
+					false,
321
+					'sentence'
322
+				);
323
+				$reg_csv_array[ __("Registration Status", 'event_espresso') ] = $stati[ $reg_row['Registration.STS_ID'] ];
324
+				// get pretty transaction status
325
+				$reg_csv_array[ __("Transaction Status", 'event_espresso') ] = $stati[ $reg_row['TransactionTable.STS_ID'] ];
326
+				$reg_csv_array[ __('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
327
+					? \EEH_Export::prepare_value_from_db_for_display(
328
+						\EEM_Transaction::instance(),
329
+						'TXN_total',
330
+						$reg_row['TransactionTable.TXN_total'],
331
+						'localized_float'
332
+					) : '0.00';
333
+				$reg_csv_array[ __('Amount Paid', 'event_espresso') ] = $is_primary_reg
334
+					? \EEH_Export::prepare_value_from_db_for_display(
335
+						\EEM_Transaction::instance(),
336
+						'TXN_paid',
337
+						$reg_row['TransactionTable.TXN_paid'],
338
+						'localized_float'
339
+					) : '0.00';
340
+				$payment_methods = array();
341
+				$gateway_txn_ids_etc = array();
342
+				$payment_times = array();
343
+				if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) {
344
+					$payments_info = \EEM_Payment::instance()->get_all_wpdb_results(
345
+						array(
346
+							array(
347
+								'TXN_ID' => $reg_row['TransactionTable.TXN_ID'],
348
+								'STS_ID' => \EEM_Payment::status_id_approved,
349
+							),
350
+							'force_join' => array('Payment_Method'),
351
+						),
352
+						ARRAY_A,
353
+						'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time'
354
+					);
355
+					foreach ($payments_info as $payment_method_and_gateway_txn_id) {
356
+						$payment_methods[] = isset($payment_method_and_gateway_txn_id['name'])
357
+							? $payment_method_and_gateway_txn_id['name'] : __('Unknown', 'event_espresso');
358
+						$gateway_txn_ids_etc[] = isset($payment_method_and_gateway_txn_id['gateway_txn_id'])
359
+							? $payment_method_and_gateway_txn_id['gateway_txn_id'] : '';
360
+						$payment_times[] = isset($payment_method_and_gateway_txn_id['payment_time'])
361
+							? $payment_method_and_gateway_txn_id['payment_time'] : '';
362
+					}
363
+				}
364
+				$reg_csv_array[ __('Payment Date(s)', 'event_espresso') ] = implode(',', $payment_times);
365
+				$reg_csv_array[ __('Payment Method(s)', 'event_espresso') ] = implode(",", $payment_methods);
366
+				$reg_csv_array[ __('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
367
+					',',
368
+					$gateway_txn_ids_etc
369
+				);
370
+				// get whether or not the user has checked in
371
+				$reg_csv_array[ __("Check-Ins", "event_espresso") ] = $reg_model->count_related(
372
+					$reg_row['Registration.REG_ID'],
373
+					'Checkin'
374
+				);
375
+				// get ticket of registration and its price
376
+				$ticket_model = \EE_Registry::instance()->load_model('Ticket');
377
+				if ($reg_row['Ticket.TKT_ID']) {
378
+					$ticket_name = \EEH_Export::prepare_value_from_db_for_display(
379
+						$ticket_model,
380
+						'TKT_name',
381
+						$reg_row['Ticket.TKT_name']
382
+					);
383
+					$datetimes_strings = array();
384
+					foreach (\EEM_Datetime::instance()->get_all_wpdb_results(
385
+						array(
386
+							array('Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']),
387
+							'order_by'                 => array('DTT_EVT_start' => 'ASC'),
388
+							'default_where_conditions' => 'none',
389
+						)
390
+					) as $datetime) {
391
+						$datetimes_strings[] = \EEH_Export::prepare_value_from_db_for_display(
392
+							\EEM_Datetime::instance(),
393
+							'DTT_EVT_start',
394
+							$datetime['Datetime.DTT_EVT_start']
395
+						);
396
+					}
397
+				} else {
398
+					$ticket_name = __('Unknown', 'event_espresso');
399
+					$datetimes_strings = array(__('Unknown', 'event_espresso'));
400
+				}
401
+				$reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
402
+				$reg_csv_array[ __("Datetimes of Ticket", "event_espresso") ] = implode(", ", $datetimes_strings);
403
+				// get datetime(s) of registration
404
+				// add attendee columns
405
+				foreach ($att_fields_to_include as $att_field_name) {
406
+					$field_obj = \EEM_Attendee::instance()->field_settings_for($att_field_name);
407
+					if ($reg_row['Attendee_CPT.ID']) {
408
+						if ($att_field_name == 'STA_ID') {
409
+							$value = \EEM_State::instance()->get_var(
410
+								array(array('STA_ID' => $reg_row['Attendee_Meta.STA_ID'])),
411
+								'STA_name'
412
+							);
413
+						} elseif ($att_field_name == 'CNT_ISO') {
414
+							$value = \EEM_Country::instance()->get_var(
415
+								array(array('CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO'])),
416
+								'CNT_name'
417
+							);
418
+						} else {
419
+							$value = \EEH_Export::prepare_value_from_db_for_display(
420
+								\EEM_Attendee::instance(),
421
+								$att_field_name,
422
+								$reg_row[ $field_obj->get_qualified_column() ]
423
+							);
424
+						}
425
+					} else {
426
+						$value = '';
427
+					}
428
+					$reg_csv_array[ \EEH_Export::get_column_name_for_field($field_obj) ] = $value;
429
+				}
430
+				// make sure each registration has the same questions in the same order
431
+				foreach ($question_labels as $question_label) {
432
+					if (! isset($reg_csv_array[ $question_label ])) {
433
+						$reg_csv_array[ $question_label ] = null;
434
+					}
435
+				}
436
+				$answers = \EEM_Answer::instance()->get_all_wpdb_results(array(
437
+					array('REG_ID' => $reg_row['Registration.REG_ID']),
438
+					'force_join' => array('Question'),
439
+				));
440
+				// now fill out the questions THEY answered
441
+				foreach ($answers as $answer_row) {
442
+					if ($answer_row['Question.QST_ID']) {
443
+						$question_label = \EEH_Export::prepare_value_from_db_for_display(
444
+							\EEM_Question::instance(),
445
+							'QST_admin_label',
446
+							$answer_row['Question.QST_admin_label']
447
+						);
448
+					} else {
449
+						$question_label = sprintf(__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']);
450
+					}
451
+					if (isset($answer_row['Question.QST_type'])
452
+						&& $answer_row['Question.QST_type'] == \EEM_Question::QST_type_state
453
+					) {
454
+						$reg_csv_array[ $question_label ] = \EEM_State::instance()->get_state_name_by_ID(
455
+							$answer_row['Answer.ANS_value']
456
+						);
457
+					} else {
458
+						// this isn't for html, so don't show html entities
459
+						$reg_csv_array[ $question_label ] = html_entity_decode(
460
+							\EEH_Export::prepare_value_from_db_for_display(
461
+								\EEM_Answer::instance(),
462
+								'ANS_value',
463
+								$answer_row['Answer.ANS_value']
464
+							)
465
+						);
466
+					}
467
+				}
468
+				/**
469
+				 * Filter to change the contents of each row of the registrations report CSV file.
470
+				 * This can be used to add or remote columns from the CSV file, or change their values.                 *
471
+				 * Note: it has this name because originally that's where this filter resided,
472
+				 * and we've left its name as-is for backward compatibility.
473
+				 * Note when using: all rows in the CSV should have the same columns.
474
+				 *
475
+				 * @param array $reg_csv_array keys are column-header names, and values are that columns' value
476
+				 *                             in this row
477
+				 * @param array $reg_row       is the row from the database's wp_esp_registration table
478
+				 */
479
+				$registrations_csv_ready_array[] = apply_filters(
480
+					'FHEE__EE_Export__report_registrations__reg_csv_array',
481
+					$reg_csv_array,
482
+					$reg_row
483
+				);
484
+			}
485
+		}
486
+		// if we couldn't export anything, we want to at least show the column headers
487
+		if (empty($registrations_csv_ready_array)) {
488
+			$reg_csv_array = array();
489
+			$model_and_fields_to_include = array(
490
+				'Registration' => $reg_fields_to_include,
491
+				'Attendee'     => $att_fields_to_include,
492
+			);
493
+			foreach ($model_and_fields_to_include as $model_name => $field_list) {
494
+				$model = \EE_Registry::instance()->load_model($model_name);
495
+				foreach ($field_list as $field_name) {
496
+					$field = $model->field_settings_for($field_name);
497
+					$reg_csv_array[ \EEH_Export::get_column_name_for_field($field) ] = null;
498
+				}
499
+			}
500
+			$registrations_csv_ready_array[] = $reg_csv_array;
501
+		}
502
+		return $registrations_csv_ready_array;
503
+	}
504 504
 
505 505
 
506
-    /**
507
-     * Counts total unit to process
508
-     *
509
-     * @deprecated since 4.9.19
510
-     * @param int|array $event_id
511
-     * @return int
512
-     */
513
-    public function count_units_to_process($event_id)
514
-    {
515
-        // use the legacy filter
516
-        if ($event_id) {
517
-            $query_params[0]['EVT_ID'] = $event_id;
518
-        } else {
519
-            $query_params['force_join'][] = 'Event';
520
-        }
521
-        return \EEM_Registration::instance()->count($query_params);
522
-    }
506
+	/**
507
+	 * Counts total unit to process
508
+	 *
509
+	 * @deprecated since 4.9.19
510
+	 * @param int|array $event_id
511
+	 * @return int
512
+	 */
513
+	public function count_units_to_process($event_id)
514
+	{
515
+		// use the legacy filter
516
+		if ($event_id) {
517
+			$query_params[0]['EVT_ID'] = $event_id;
518
+		} else {
519
+			$query_params['force_join'][] = 'Event';
520
+		}
521
+		return \EEM_Registration::instance()->count($query_params);
522
+	}
523 523
 
524 524
 
525
-    /**
526
-     * Performs any clean-up logic when we know the job is completed.
527
-     * In this case, we delete the temporary file
528
-     *
529
-     * @param JobParameters $job_parameters
530
-     * @return boolean
531
-     */
532
-    public function cleanup_job(JobParameters $job_parameters)
533
-    {
534
-        $this->_file_helper->delete(
535
-            \EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
536
-            true,
537
-            'd'
538
-        );
539
-        return new JobStepResponse($job_parameters, __('Cleaned up temporary file', 'event_espresso'));
540
-    }
525
+	/**
526
+	 * Performs any clean-up logic when we know the job is completed.
527
+	 * In this case, we delete the temporary file
528
+	 *
529
+	 * @param JobParameters $job_parameters
530
+	 * @return boolean
531
+	 */
532
+	public function cleanup_job(JobParameters $job_parameters)
533
+	{
534
+		$this->_file_helper->delete(
535
+			\EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
536
+			true,
537
+			'd'
538
+		);
539
+		return new JobStepResponse($job_parameters, __('Cleaned up temporary file', 'event_espresso'));
540
+	}
541 541
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
     public function create_job(JobParameters $job_parameters)
34 34
     {
35 35
         $event_id = intval($job_parameters->request_datum('EVT_ID', '0'));
36
-        if (! \EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
36
+        if ( ! \EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
37 37
             throw new BatchRequestException(__('You do not have permission to view registrations', 'event_espresso'));
38 38
         }
39 39
         $filepath = $this->create_file_from_job_with_name(
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
                 $query_params['force_join'][] = 'Event';
71 71
             }
72 72
         }
73
-        if (! isset($query_params['force_join'])) {
73
+        if ( ! isset($query_params['force_join'])) {
74 74
             $query_params['force_join'] = array('Event', 'Transaction', 'Ticket', 'Attendee');
75 75
         }
76 76
         $job_parameters->add_extra_data('query_params', $query_params);
@@ -160,10 +160,10 @@  discard block
 block discarded – undo
160 160
         $question_where_params = array();
161 161
         foreach ($reg_where_params as $key => $val) {
162 162
             if (\EEM_Registration::instance()->is_logic_query_param_key($key)) {
163
-                $question_where_params[ $key ] = $this->_change_registration_where_params_to_question_where_params($val);
163
+                $question_where_params[$key] = $this->_change_registration_where_params_to_question_where_params($val);
164 164
             } else {
165 165
                 // it's a normal where condition
166
-                $question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
166
+                $question_where_params['Question_Group.Event.Registration.'.$key] = $val;
167 167
             }
168 168
         }
169 169
         return $question_where_params;
@@ -254,9 +254,9 @@  discard block
 block discarded – undo
254 254
         foreach ($registration_rows as $reg_row) {
255 255
             if (is_array($reg_row)) {
256 256
                 $reg_csv_array = array();
257
-                if (! $event_id) {
257
+                if ( ! $event_id) {
258 258
                     // get the event's name and Id
259
-                    $reg_csv_array[ __('Event', 'event_espresso') ] = sprintf(
259
+                    $reg_csv_array[__('Event', 'event_espresso')] = sprintf(
260 260
                         __('%1$s (%2$s)', 'event_espresso'),
261 261
                         \EEH_Export::prepare_value_from_db_for_display(
262 262
                             \EEM_Event::instance(),
@@ -302,13 +302,13 @@  discard block
 block discarded – undo
302 302
                         $value = \EEH_Export::prepare_value_from_db_for_display(
303 303
                             $reg_model,
304 304
                             $field_name,
305
-                            $reg_row[ $field->get_qualified_column() ]
305
+                            $reg_row[$field->get_qualified_column()]
306 306
                         );
307 307
                     }
308
-                    $reg_csv_array[ \EEH_Export::get_column_name_for_field($field) ] = $value;
308
+                    $reg_csv_array[\EEH_Export::get_column_name_for_field($field)] = $value;
309 309
                     if ($field_name == 'REG_final_price') {
310 310
                         // add a column named Currency after the final price
311
-                        $reg_csv_array[ __("Currency", "event_espresso") ] = \EE_Config::instance()->currency->code;
311
+                        $reg_csv_array[__("Currency", "event_espresso")] = \EE_Config::instance()->currency->code;
312 312
                     }
313 313
                 }
314 314
                 // get pretty status
@@ -320,17 +320,17 @@  discard block
 block discarded – undo
320 320
                     false,
321 321
                     'sentence'
322 322
                 );
323
-                $reg_csv_array[ __("Registration Status", 'event_espresso') ] = $stati[ $reg_row['Registration.STS_ID'] ];
323
+                $reg_csv_array[__("Registration Status", 'event_espresso')] = $stati[$reg_row['Registration.STS_ID']];
324 324
                 // get pretty transaction status
325
-                $reg_csv_array[ __("Transaction Status", 'event_espresso') ] = $stati[ $reg_row['TransactionTable.STS_ID'] ];
326
-                $reg_csv_array[ __('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
325
+                $reg_csv_array[__("Transaction Status", 'event_espresso')] = $stati[$reg_row['TransactionTable.STS_ID']];
326
+                $reg_csv_array[__('Transaction Amount Due', 'event_espresso')] = $is_primary_reg
327 327
                     ? \EEH_Export::prepare_value_from_db_for_display(
328 328
                         \EEM_Transaction::instance(),
329 329
                         'TXN_total',
330 330
                         $reg_row['TransactionTable.TXN_total'],
331 331
                         'localized_float'
332 332
                     ) : '0.00';
333
-                $reg_csv_array[ __('Amount Paid', 'event_espresso') ] = $is_primary_reg
333
+                $reg_csv_array[__('Amount Paid', 'event_espresso')] = $is_primary_reg
334 334
                     ? \EEH_Export::prepare_value_from_db_for_display(
335 335
                         \EEM_Transaction::instance(),
336 336
                         'TXN_paid',
@@ -361,14 +361,14 @@  discard block
 block discarded – undo
361 361
                             ? $payment_method_and_gateway_txn_id['payment_time'] : '';
362 362
                     }
363 363
                 }
364
-                $reg_csv_array[ __('Payment Date(s)', 'event_espresso') ] = implode(',', $payment_times);
365
-                $reg_csv_array[ __('Payment Method(s)', 'event_espresso') ] = implode(",", $payment_methods);
366
-                $reg_csv_array[ __('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
364
+                $reg_csv_array[__('Payment Date(s)', 'event_espresso')] = implode(',', $payment_times);
365
+                $reg_csv_array[__('Payment Method(s)', 'event_espresso')] = implode(",", $payment_methods);
366
+                $reg_csv_array[__('Gateway Transaction ID(s)', 'event_espresso')] = implode(
367 367
                     ',',
368 368
                     $gateway_txn_ids_etc
369 369
                 );
370 370
                 // get whether or not the user has checked in
371
-                $reg_csv_array[ __("Check-Ins", "event_espresso") ] = $reg_model->count_related(
371
+                $reg_csv_array[__("Check-Ins", "event_espresso")] = $reg_model->count_related(
372 372
                     $reg_row['Registration.REG_ID'],
373 373
                     'Checkin'
374 374
                 );
@@ -398,8 +398,8 @@  discard block
 block discarded – undo
398 398
                     $ticket_name = __('Unknown', 'event_espresso');
399 399
                     $datetimes_strings = array(__('Unknown', 'event_espresso'));
400 400
                 }
401
-                $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
402
-                $reg_csv_array[ __("Datetimes of Ticket", "event_espresso") ] = implode(", ", $datetimes_strings);
401
+                $reg_csv_array[$ticket_model->field_settings_for('TKT_name')->get_nicename()] = $ticket_name;
402
+                $reg_csv_array[__("Datetimes of Ticket", "event_espresso")] = implode(", ", $datetimes_strings);
403 403
                 // get datetime(s) of registration
404 404
                 // add attendee columns
405 405
                 foreach ($att_fields_to_include as $att_field_name) {
@@ -419,18 +419,18 @@  discard block
 block discarded – undo
419 419
                             $value = \EEH_Export::prepare_value_from_db_for_display(
420 420
                                 \EEM_Attendee::instance(),
421 421
                                 $att_field_name,
422
-                                $reg_row[ $field_obj->get_qualified_column() ]
422
+                                $reg_row[$field_obj->get_qualified_column()]
423 423
                             );
424 424
                         }
425 425
                     } else {
426 426
                         $value = '';
427 427
                     }
428
-                    $reg_csv_array[ \EEH_Export::get_column_name_for_field($field_obj) ] = $value;
428
+                    $reg_csv_array[\EEH_Export::get_column_name_for_field($field_obj)] = $value;
429 429
                 }
430 430
                 // make sure each registration has the same questions in the same order
431 431
                 foreach ($question_labels as $question_label) {
432
-                    if (! isset($reg_csv_array[ $question_label ])) {
433
-                        $reg_csv_array[ $question_label ] = null;
432
+                    if ( ! isset($reg_csv_array[$question_label])) {
433
+                        $reg_csv_array[$question_label] = null;
434 434
                     }
435 435
                 }
436 436
                 $answers = \EEM_Answer::instance()->get_all_wpdb_results(array(
@@ -451,12 +451,12 @@  discard block
 block discarded – undo
451 451
                     if (isset($answer_row['Question.QST_type'])
452 452
                         && $answer_row['Question.QST_type'] == \EEM_Question::QST_type_state
453 453
                     ) {
454
-                        $reg_csv_array[ $question_label ] = \EEM_State::instance()->get_state_name_by_ID(
454
+                        $reg_csv_array[$question_label] = \EEM_State::instance()->get_state_name_by_ID(
455 455
                             $answer_row['Answer.ANS_value']
456 456
                         );
457 457
                     } else {
458 458
                         // this isn't for html, so don't show html entities
459
-                        $reg_csv_array[ $question_label ] = html_entity_decode(
459
+                        $reg_csv_array[$question_label] = html_entity_decode(
460 460
                             \EEH_Export::prepare_value_from_db_for_display(
461 461
                                 \EEM_Answer::instance(),
462 462
                                 'ANS_value',
@@ -494,7 +494,7 @@  discard block
 block discarded – undo
494 494
                 $model = \EE_Registry::instance()->load_model($model_name);
495 495
                 foreach ($field_list as $field_name) {
496 496
                     $field = $model->field_settings_for($field_name);
497
-                    $reg_csv_array[ \EEH_Export::get_column_name_for_field($field) ] = null;
497
+                    $reg_csv_array[\EEH_Export::get_column_name_for_field($field)] = null;
498 498
                 }
499 499
             }
500 500
             $registrations_csv_ready_array[] = $reg_csv_array;
Please login to merge, or discard this patch.
core/libraries/batch/Helpers/JobParameters.php 2 patches
Indentation   +392 added lines, -392 removed lines patch added patch discarded remove patch
@@ -14,396 +14,396 @@
 block discarded – undo
14 14
  */
15 15
 class JobParameters
16 16
 {
17
-    // phpcs:disable Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
18
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
19
-    // phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore
20
-    /**
21
-     * status indicating the job should continue
22
-     */
23
-    const status_continue = 'continue';
24
-
25
-    /**
26
-     * status indicated the job has been completed successfully and should be cleaned up next
27
-     */
28
-    const status_complete = 'complete';
29
-
30
-    /**
31
-     * status indicating there was an error and the job should be cleaned up
32
-     */
33
-    const status_error = 'error';
34
-
35
-    /**
36
-     * status indicating the job has been cleaned up, and so this is probably the last
37
-     * time you'll see this job
38
-     */
39
-    const status_cleaned_up = 'cleaned_up';
40
-
41
-    const wp_option_prefix = 'ee_job_parameters_';
42
-
43
-
44
-    /**
45
-     * String uniquely identifying the job
46
-     *
47
-     * @var string
48
-     */
49
-    protected $_job_id;
50
-
51
-    /**
52
-     * @var string
53
-     */
54
-    protected $_classname;
55
-
56
-    /**
57
-     * @var array
58
-     */
59
-    protected $_request_data;
60
-
61
-    /**
62
-     * Array of any extra data we want to remember about this request, that
63
-     * wasn't necessarily past in with the request data
64
-     *
65
-     * @var array
66
-     */
67
-    protected $_extra_data;
68
-
69
-    /**
70
-     * Estimate of how many units HAVE been processed
71
-     *
72
-     * @var int
73
-     */
74
-    protected $_units_processed = 0;
75
-
76
-    /**
77
-     * @var string
78
-     */
79
-    protected $_status;
80
-
81
-    /**
82
-     * The size of the total job in whatever units you want.
83
-     * If you can't provide an estimate leave as 0.
84
-     * Once _units_processed equals _job_size, we should be done
85
-     *
86
-     * @var int
87
-     */
88
-    protected $_job_size = 0;
89
-
90
-
91
-    /**
92
-     * @param string $job_id
93
-     * @param string $classname
94
-     * @param array  $request_data
95
-     * @param array  $extra_data
96
-     */
97
-    public function __construct($job_id, $classname, $request_data, $extra_data = array())
98
-    {
99
-        $this->set_job_id($job_id);
100
-        $this->set_classname($classname);
101
-        $this->set_request_data($request_data);
102
-        $this->set_extra_data($extra_data);
103
-        $this->set_status(JobParameters::status_continue);
104
-    }
105
-
106
-
107
-    /**
108
-     * Returns the array of strings of valid stati
109
-     *
110
-     * @return array
111
-     */
112
-    public static function valid_stati()
113
-    {
114
-        return array(
115
-            JobParameters::status_complete,
116
-            JobParameters::status_continue,
117
-            JobParameters::status_error,
118
-            JobParameters::status_cleaned_up,
119
-        );
120
-    }
121
-
122
-
123
-    /**
124
-     * Saves this option to the database (wordpress options table)
125
-     *
126
-     * @param boolean $first
127
-     * @return boolean success
128
-     */
129
-    public function save($first = false)
130
-    {
131
-        $object_vars = get_object_vars($this);
132
-        if ($first) {
133
-            return add_option($this->option_name(), $object_vars, null, 'no');
134
-        } else {
135
-            return update_option($this->option_name(), $object_vars);
136
-        }
137
-    }
138
-
139
-
140
-    /**
141
-     * Deletes the job from teh database, although this object is still usable
142
-     * for the rest of the request
143
-     *
144
-     * @return boolean
145
-     */
146
-    public function delete()
147
-    {
148
-        return delete_option($this->option_name());
149
-    }
150
-
151
-
152
-    /**
153
-     * Loads the specified job from the database
154
-     *
155
-     * @param string $job_id
156
-     * @return JobParameters
157
-     * @throws BatchRequestException
158
-     */
159
-    public static function load($job_id)
160
-    {
161
-        $job_parameter_vars = get_option(JobParameters::wp_option_prefix . $job_id);
162
-        if (! is_array($job_parameter_vars) ||
163
-            ! isset($job_parameter_vars['_classname']) ||
164
-            ! isset($job_parameter_vars['_request_data'])
165
-        ) {
166
-            throw new BatchRequestException(
167
-                sprintf(
168
-                    __(
169
-                        'Could not retrieve job %1$s from the Wordpress options table, and so the job could not continue. The wordpress option was %2$s',
170
-                        'event_espresso'
171
-                    ),
172
-                    $job_id,
173
-                    get_option(JobParameters::wp_option_prefix . $job_id)
174
-                )
175
-            );
176
-        }
177
-        $job_parameters = new JobParameters(
178
-            $job_id,
179
-            $job_parameter_vars['_classname'],
180
-            $job_parameter_vars['_request_data']
181
-        );
182
-        foreach ($job_parameter_vars as $key => $value) {
183
-            $job_parameters->{$key} = $value;
184
-        }
185
-        return $job_parameters;
186
-    }
187
-
188
-
189
-    /**
190
-     * Gets the job's unique string
191
-     *
192
-     * @return string
193
-     */
194
-    public function job_id()
195
-    {
196
-        return $this->_job_id;
197
-    }
198
-
199
-
200
-    /**
201
-     * Gets the classname that should run this job
202
-     *
203
-     * @return string
204
-     */
205
-    public function classname()
206
-    {
207
-        return $this->_classname;
208
-    }
209
-
210
-
211
-    /**
212
-     * Gets the original array of $_REQUEST data for this job
213
-     *
214
-     * @return array
215
-     */
216
-    public function request_data()
217
-    {
218
-        return $this->_request_data;
219
-    }
220
-
221
-
222
-    /**
223
-     * Gets a single item from the request data
224
-     *
225
-     * @param string       $key
226
-     * @param string|array $default
227
-     * @return string|array
228
-     */
229
-    public function request_datum($key, $default = '')
230
-    {
231
-        if (isset($this->_request_data[ $key ])) {
232
-            return $this->_request_data[ $key ];
233
-        } else {
234
-            return $default;
235
-        }
236
-    }
237
-
238
-
239
-    /**
240
-     * Gets a single item from the extra data
241
-     *
242
-     * @param string       $key
243
-     * @param string|array $default
244
-     * @return string|array
245
-     */
246
-    public function extra_datum($key, $default = '')
247
-    {
248
-        if (isset($this->_extra_data[ $key ])) {
249
-            return $this->_extra_data[ $key ];
250
-        } else {
251
-            return $default;
252
-        }
253
-    }
254
-
255
-
256
-    /**
257
-     * Adds an extra piece of extra data that we're going to want later during the job
258
-     *
259
-     * @param string                $key
260
-     * @param string|int|array|null $value almost any extra data you want to store
261
-     */
262
-    public function add_extra_data($key, $value)
263
-    {
264
-        $this->_extra_data[ $key ] = $value;
265
-    }
266
-
267
-
268
-    /**
269
-     * Array of any extra data we want to store
270
-     *
271
-     * @return array
272
-     */
273
-    public function extra_data()
274
-    {
275
-        return $this->_extra_data;
276
-    }
277
-
278
-
279
-    /**
280
-     * Returns the job size, in whatever units you want
281
-     *
282
-     * @return int
283
-     */
284
-    public function job_size()
285
-    {
286
-        return $this->_job_size;
287
-    }
288
-
289
-
290
-    /**
291
-     * Sets the job size. You decide what units to use
292
-     *
293
-     * @param int $size
294
-     */
295
-    public function set_job_size($size)
296
-    {
297
-        $this->_job_size = $size;
298
-    }
299
-
300
-
301
-    /**
302
-     * The number of "units" processed, in the same units as the "job size"
303
-     *
304
-     * @return int
305
-     */
306
-    public function units_processed()
307
-    {
308
-        return $this->_units_processed;
309
-    }
310
-
311
-
312
-    /**
313
-     * Marks more units as processed
314
-     *
315
-     * @param int $newly_processed
316
-     * @return int updated units processed
317
-     */
318
-    public function mark_processed($newly_processed)
319
-    {
320
-        $this->_units_processed += $newly_processed;
321
-        return $this->_units_processed;
322
-    }
323
-
324
-
325
-    /**
326
-     * Sets the total count of units processed. You might prefer to use mark_processed
327
-     *
328
-     * @param int $total_units_processed
329
-     */
330
-    public function set_units_processed($total_units_processed)
331
-    {
332
-        $this->_units_processed = $total_units_processed;
333
-    }
334
-
335
-
336
-    /**
337
-     * Sets the job's ID
338
-     *
339
-     * @param string $job_id
340
-     */
341
-    public function set_job_id($job_id)
342
-    {
343
-        $this->_job_id = $job_id;
344
-    }
345
-
346
-
347
-    /**
348
-     * sets the classname
349
-     *
350
-     * @param string $classname
351
-     */
352
-    public function set_classname($classname)
353
-    {
354
-        $this->_classname = $classname;
355
-    }
356
-
357
-
358
-    /**
359
-     * Sets the request data
360
-     *
361
-     * @param array $request_data
362
-     */
363
-    public function set_request_data($request_data)
364
-    {
365
-        $this->_request_data = $request_data;
366
-    }
367
-
368
-
369
-    /**
370
-     * Sets the array of extra data we want to store on this request
371
-     *
372
-     * @param array $extra_data
373
-     */
374
-    public function set_extra_data($extra_data)
375
-    {
376
-        $this->_extra_data = $extra_data;
377
-    }
378
-
379
-
380
-    /**
381
-     * Gets the name of the wordpress option that should store these job parameters
382
-     *
383
-     * @return string
384
-     */
385
-    public function option_name()
386
-    {
387
-        return JobParameters::wp_option_prefix . $this->job_id();
388
-    }
389
-
390
-
391
-    /**
392
-     * Gets the job\s current status. One of JobParameters::valid_stati();
393
-     *
394
-     * @return string
395
-     */
396
-    public function status()
397
-    {
398
-        return $this->_status;
399
-    }
400
-
401
-
402
-    /**
403
-     * @param string $status on eof JobParameters::valid_stati()
404
-     */
405
-    public function set_status($status)
406
-    {
407
-        $this->_status = $status;
408
-    }
17
+	// phpcs:disable Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
18
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
19
+	// phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore
20
+	/**
21
+	 * status indicating the job should continue
22
+	 */
23
+	const status_continue = 'continue';
24
+
25
+	/**
26
+	 * status indicated the job has been completed successfully and should be cleaned up next
27
+	 */
28
+	const status_complete = 'complete';
29
+
30
+	/**
31
+	 * status indicating there was an error and the job should be cleaned up
32
+	 */
33
+	const status_error = 'error';
34
+
35
+	/**
36
+	 * status indicating the job has been cleaned up, and so this is probably the last
37
+	 * time you'll see this job
38
+	 */
39
+	const status_cleaned_up = 'cleaned_up';
40
+
41
+	const wp_option_prefix = 'ee_job_parameters_';
42
+
43
+
44
+	/**
45
+	 * String uniquely identifying the job
46
+	 *
47
+	 * @var string
48
+	 */
49
+	protected $_job_id;
50
+
51
+	/**
52
+	 * @var string
53
+	 */
54
+	protected $_classname;
55
+
56
+	/**
57
+	 * @var array
58
+	 */
59
+	protected $_request_data;
60
+
61
+	/**
62
+	 * Array of any extra data we want to remember about this request, that
63
+	 * wasn't necessarily past in with the request data
64
+	 *
65
+	 * @var array
66
+	 */
67
+	protected $_extra_data;
68
+
69
+	/**
70
+	 * Estimate of how many units HAVE been processed
71
+	 *
72
+	 * @var int
73
+	 */
74
+	protected $_units_processed = 0;
75
+
76
+	/**
77
+	 * @var string
78
+	 */
79
+	protected $_status;
80
+
81
+	/**
82
+	 * The size of the total job in whatever units you want.
83
+	 * If you can't provide an estimate leave as 0.
84
+	 * Once _units_processed equals _job_size, we should be done
85
+	 *
86
+	 * @var int
87
+	 */
88
+	protected $_job_size = 0;
89
+
90
+
91
+	/**
92
+	 * @param string $job_id
93
+	 * @param string $classname
94
+	 * @param array  $request_data
95
+	 * @param array  $extra_data
96
+	 */
97
+	public function __construct($job_id, $classname, $request_data, $extra_data = array())
98
+	{
99
+		$this->set_job_id($job_id);
100
+		$this->set_classname($classname);
101
+		$this->set_request_data($request_data);
102
+		$this->set_extra_data($extra_data);
103
+		$this->set_status(JobParameters::status_continue);
104
+	}
105
+
106
+
107
+	/**
108
+	 * Returns the array of strings of valid stati
109
+	 *
110
+	 * @return array
111
+	 */
112
+	public static function valid_stati()
113
+	{
114
+		return array(
115
+			JobParameters::status_complete,
116
+			JobParameters::status_continue,
117
+			JobParameters::status_error,
118
+			JobParameters::status_cleaned_up,
119
+		);
120
+	}
121
+
122
+
123
+	/**
124
+	 * Saves this option to the database (wordpress options table)
125
+	 *
126
+	 * @param boolean $first
127
+	 * @return boolean success
128
+	 */
129
+	public function save($first = false)
130
+	{
131
+		$object_vars = get_object_vars($this);
132
+		if ($first) {
133
+			return add_option($this->option_name(), $object_vars, null, 'no');
134
+		} else {
135
+			return update_option($this->option_name(), $object_vars);
136
+		}
137
+	}
138
+
139
+
140
+	/**
141
+	 * Deletes the job from teh database, although this object is still usable
142
+	 * for the rest of the request
143
+	 *
144
+	 * @return boolean
145
+	 */
146
+	public function delete()
147
+	{
148
+		return delete_option($this->option_name());
149
+	}
150
+
151
+
152
+	/**
153
+	 * Loads the specified job from the database
154
+	 *
155
+	 * @param string $job_id
156
+	 * @return JobParameters
157
+	 * @throws BatchRequestException
158
+	 */
159
+	public static function load($job_id)
160
+	{
161
+		$job_parameter_vars = get_option(JobParameters::wp_option_prefix . $job_id);
162
+		if (! is_array($job_parameter_vars) ||
163
+			! isset($job_parameter_vars['_classname']) ||
164
+			! isset($job_parameter_vars['_request_data'])
165
+		) {
166
+			throw new BatchRequestException(
167
+				sprintf(
168
+					__(
169
+						'Could not retrieve job %1$s from the Wordpress options table, and so the job could not continue. The wordpress option was %2$s',
170
+						'event_espresso'
171
+					),
172
+					$job_id,
173
+					get_option(JobParameters::wp_option_prefix . $job_id)
174
+				)
175
+			);
176
+		}
177
+		$job_parameters = new JobParameters(
178
+			$job_id,
179
+			$job_parameter_vars['_classname'],
180
+			$job_parameter_vars['_request_data']
181
+		);
182
+		foreach ($job_parameter_vars as $key => $value) {
183
+			$job_parameters->{$key} = $value;
184
+		}
185
+		return $job_parameters;
186
+	}
187
+
188
+
189
+	/**
190
+	 * Gets the job's unique string
191
+	 *
192
+	 * @return string
193
+	 */
194
+	public function job_id()
195
+	{
196
+		return $this->_job_id;
197
+	}
198
+
199
+
200
+	/**
201
+	 * Gets the classname that should run this job
202
+	 *
203
+	 * @return string
204
+	 */
205
+	public function classname()
206
+	{
207
+		return $this->_classname;
208
+	}
209
+
210
+
211
+	/**
212
+	 * Gets the original array of $_REQUEST data for this job
213
+	 *
214
+	 * @return array
215
+	 */
216
+	public function request_data()
217
+	{
218
+		return $this->_request_data;
219
+	}
220
+
221
+
222
+	/**
223
+	 * Gets a single item from the request data
224
+	 *
225
+	 * @param string       $key
226
+	 * @param string|array $default
227
+	 * @return string|array
228
+	 */
229
+	public function request_datum($key, $default = '')
230
+	{
231
+		if (isset($this->_request_data[ $key ])) {
232
+			return $this->_request_data[ $key ];
233
+		} else {
234
+			return $default;
235
+		}
236
+	}
237
+
238
+
239
+	/**
240
+	 * Gets a single item from the extra data
241
+	 *
242
+	 * @param string       $key
243
+	 * @param string|array $default
244
+	 * @return string|array
245
+	 */
246
+	public function extra_datum($key, $default = '')
247
+	{
248
+		if (isset($this->_extra_data[ $key ])) {
249
+			return $this->_extra_data[ $key ];
250
+		} else {
251
+			return $default;
252
+		}
253
+	}
254
+
255
+
256
+	/**
257
+	 * Adds an extra piece of extra data that we're going to want later during the job
258
+	 *
259
+	 * @param string                $key
260
+	 * @param string|int|array|null $value almost any extra data you want to store
261
+	 */
262
+	public function add_extra_data($key, $value)
263
+	{
264
+		$this->_extra_data[ $key ] = $value;
265
+	}
266
+
267
+
268
+	/**
269
+	 * Array of any extra data we want to store
270
+	 *
271
+	 * @return array
272
+	 */
273
+	public function extra_data()
274
+	{
275
+		return $this->_extra_data;
276
+	}
277
+
278
+
279
+	/**
280
+	 * Returns the job size, in whatever units you want
281
+	 *
282
+	 * @return int
283
+	 */
284
+	public function job_size()
285
+	{
286
+		return $this->_job_size;
287
+	}
288
+
289
+
290
+	/**
291
+	 * Sets the job size. You decide what units to use
292
+	 *
293
+	 * @param int $size
294
+	 */
295
+	public function set_job_size($size)
296
+	{
297
+		$this->_job_size = $size;
298
+	}
299
+
300
+
301
+	/**
302
+	 * The number of "units" processed, in the same units as the "job size"
303
+	 *
304
+	 * @return int
305
+	 */
306
+	public function units_processed()
307
+	{
308
+		return $this->_units_processed;
309
+	}
310
+
311
+
312
+	/**
313
+	 * Marks more units as processed
314
+	 *
315
+	 * @param int $newly_processed
316
+	 * @return int updated units processed
317
+	 */
318
+	public function mark_processed($newly_processed)
319
+	{
320
+		$this->_units_processed += $newly_processed;
321
+		return $this->_units_processed;
322
+	}
323
+
324
+
325
+	/**
326
+	 * Sets the total count of units processed. You might prefer to use mark_processed
327
+	 *
328
+	 * @param int $total_units_processed
329
+	 */
330
+	public function set_units_processed($total_units_processed)
331
+	{
332
+		$this->_units_processed = $total_units_processed;
333
+	}
334
+
335
+
336
+	/**
337
+	 * Sets the job's ID
338
+	 *
339
+	 * @param string $job_id
340
+	 */
341
+	public function set_job_id($job_id)
342
+	{
343
+		$this->_job_id = $job_id;
344
+	}
345
+
346
+
347
+	/**
348
+	 * sets the classname
349
+	 *
350
+	 * @param string $classname
351
+	 */
352
+	public function set_classname($classname)
353
+	{
354
+		$this->_classname = $classname;
355
+	}
356
+
357
+
358
+	/**
359
+	 * Sets the request data
360
+	 *
361
+	 * @param array $request_data
362
+	 */
363
+	public function set_request_data($request_data)
364
+	{
365
+		$this->_request_data = $request_data;
366
+	}
367
+
368
+
369
+	/**
370
+	 * Sets the array of extra data we want to store on this request
371
+	 *
372
+	 * @param array $extra_data
373
+	 */
374
+	public function set_extra_data($extra_data)
375
+	{
376
+		$this->_extra_data = $extra_data;
377
+	}
378
+
379
+
380
+	/**
381
+	 * Gets the name of the wordpress option that should store these job parameters
382
+	 *
383
+	 * @return string
384
+	 */
385
+	public function option_name()
386
+	{
387
+		return JobParameters::wp_option_prefix . $this->job_id();
388
+	}
389
+
390
+
391
+	/**
392
+	 * Gets the job\s current status. One of JobParameters::valid_stati();
393
+	 *
394
+	 * @return string
395
+	 */
396
+	public function status()
397
+	{
398
+		return $this->_status;
399
+	}
400
+
401
+
402
+	/**
403
+	 * @param string $status on eof JobParameters::valid_stati()
404
+	 */
405
+	public function set_status($status)
406
+	{
407
+		$this->_status = $status;
408
+	}
409 409
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -158,8 +158,8 @@  discard block
 block discarded – undo
158 158
      */
159 159
     public static function load($job_id)
160 160
     {
161
-        $job_parameter_vars = get_option(JobParameters::wp_option_prefix . $job_id);
162
-        if (! is_array($job_parameter_vars) ||
161
+        $job_parameter_vars = get_option(JobParameters::wp_option_prefix.$job_id);
162
+        if ( ! is_array($job_parameter_vars) ||
163 163
             ! isset($job_parameter_vars['_classname']) ||
164 164
             ! isset($job_parameter_vars['_request_data'])
165 165
         ) {
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
                         'event_espresso'
171 171
                     ),
172 172
                     $job_id,
173
-                    get_option(JobParameters::wp_option_prefix . $job_id)
173
+                    get_option(JobParameters::wp_option_prefix.$job_id)
174 174
                 )
175 175
             );
176 176
         }
@@ -228,8 +228,8 @@  discard block
 block discarded – undo
228 228
      */
229 229
     public function request_datum($key, $default = '')
230 230
     {
231
-        if (isset($this->_request_data[ $key ])) {
232
-            return $this->_request_data[ $key ];
231
+        if (isset($this->_request_data[$key])) {
232
+            return $this->_request_data[$key];
233 233
         } else {
234 234
             return $default;
235 235
         }
@@ -245,8 +245,8 @@  discard block
 block discarded – undo
245 245
      */
246 246
     public function extra_datum($key, $default = '')
247 247
     {
248
-        if (isset($this->_extra_data[ $key ])) {
249
-            return $this->_extra_data[ $key ];
248
+        if (isset($this->_extra_data[$key])) {
249
+            return $this->_extra_data[$key];
250 250
         } else {
251 251
             return $default;
252 252
         }
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
      */
262 262
     public function add_extra_data($key, $value)
263 263
     {
264
-        $this->_extra_data[ $key ] = $value;
264
+        $this->_extra_data[$key] = $value;
265 265
     }
266 266
 
267 267
 
@@ -384,7 +384,7 @@  discard block
 block discarded – undo
384 384
      */
385 385
     public function option_name()
386 386
     {
387
-        return JobParameters::wp_option_prefix . $this->job_id();
387
+        return JobParameters::wp_option_prefix.$this->job_id();
388 388
     }
389 389
 
390 390
 
Please login to merge, or discard this patch.
core/libraries/batch/Helpers/JobStepResponse.php 1 patch
Indentation   +84 added lines, -84 removed lines patch added patch discarded remove patch
@@ -13,99 +13,99 @@
 block discarded – undo
13 13
  */
14 14
 class JobStepResponse
15 15
 {
16
-    // phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore
17
-    /**
18
-     * Description fo what happened during this step
19
-     *
20
-     * @var string
21
-     */
22
-    protected $_update_text;
16
+	// phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore
17
+	/**
18
+	 * Description fo what happened during this step
19
+	 *
20
+	 * @var string
21
+	 */
22
+	protected $_update_text;
23 23
 
24
-    /**
25
-     * @var JobParameters
26
-     */
27
-    protected $_job_parameters;
24
+	/**
25
+	 * @var JobParameters
26
+	 */
27
+	protected $_job_parameters;
28 28
 
29
-    /**
30
-     * Extra data to include as part of the response.
31
-     *
32
-     * @var array
33
-     */
34
-    protected $_extra_data = array();
35
-    // phpcs:enable
29
+	/**
30
+	 * Extra data to include as part of the response.
31
+	 *
32
+	 * @var array
33
+	 */
34
+	protected $_extra_data = array();
35
+	// phpcs:enable
36 36
 
37
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
38
-    /**
39
-     * @param \EventEspressoBatchRequest\Helpers\JobParameters $job_parameters
40
-     * @param string                                           $update_text
41
-     * @param array                                            $extra_data
42
-     */
43
-    public function __construct(JobParameters $job_parameters, $update_text, $extra_data = array())
44
-    {
45
-        $this->_job_parameters = $job_parameters;
46
-        $this->_update_text = $update_text;
47
-        $this->_extra_data = (array) $extra_data;
48
-    }
37
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
38
+	/**
39
+	 * @param \EventEspressoBatchRequest\Helpers\JobParameters $job_parameters
40
+	 * @param string                                           $update_text
41
+	 * @param array                                            $extra_data
42
+	 */
43
+	public function __construct(JobParameters $job_parameters, $update_text, $extra_data = array())
44
+	{
45
+		$this->_job_parameters = $job_parameters;
46
+		$this->_update_text = $update_text;
47
+		$this->_extra_data = (array) $extra_data;
48
+	}
49 49
 
50 50
 
51
-    /**
52
-     * @return JobParameters
53
-     */
54
-    public function job_parameters()
55
-    {
56
-        return $this->_job_parameters;
57
-    }
51
+	/**
52
+	 * @return JobParameters
53
+	 */
54
+	public function job_parameters()
55
+	{
56
+		return $this->_job_parameters;
57
+	}
58 58
 
59 59
 
60
-    /**
61
-     * Gets the update_text of what happened in this job during the current step
62
-     *
63
-     * @return string
64
-     */
65
-    public function update_text()
66
-    {
67
-        return $this->_update_text;
68
-    }
60
+	/**
61
+	 * Gets the update_text of what happened in this job during the current step
62
+	 *
63
+	 * @return string
64
+	 */
65
+	public function update_text()
66
+	{
67
+		return $this->_update_text;
68
+	}
69 69
 
70 70
 
71
-    /**
72
-     * Returns any extra data we may want to include with this response
73
-     *
74
-     * @return array
75
-     */
76
-    public function extra_data()
77
-    {
78
-        return $this->_extra_data;
79
-    }
71
+	/**
72
+	 * Returns any extra data we may want to include with this response
73
+	 *
74
+	 * @return array
75
+	 */
76
+	public function extra_data()
77
+	{
78
+		return $this->_extra_data;
79
+	}
80 80
 
81 81
 
82
-    /**
83
-     * Converts this response into an array that can be easily serialized.
84
-     * This is most useful for serializing or json encoding
85
-     *
86
-     * @return array {
87
-     * @type string $status          , one of JobParameters::valid_stati()
88
-     * @type int    $units_processed count of units processed
89
-     * @type int    $job_size        total number of units TO process
90
-     * @type string $job_id          unique string identifying the job
91
-     * @type string $update_text     string describing what happened during this step
92
-     * } and any other items from $this->extra_data()
93
-     */
94
-    public function to_array()
95
-    {
96
-        return apply_filters(
97
-            'FHEE__EventEspressoBatchRequest\Helpers\JobStepResponse__to_array__return',
98
-            array_merge(
99
-                $this->extra_data(),
100
-                array(
101
-                    'status'          => $this->job_parameters()->status(),
102
-                    'units_processed' => $this->job_parameters()->units_processed(),
103
-                    'job_size'        => $this->job_parameters()->job_size(),
104
-                    'job_id'          => $this->job_parameters()->job_id(),
105
-                    'update_text'     => $this->update_text(),
106
-                )
107
-            ),
108
-            $this
109
-        );
110
-    }
82
+	/**
83
+	 * Converts this response into an array that can be easily serialized.
84
+	 * This is most useful for serializing or json encoding
85
+	 *
86
+	 * @return array {
87
+	 * @type string $status          , one of JobParameters::valid_stati()
88
+	 * @type int    $units_processed count of units processed
89
+	 * @type int    $job_size        total number of units TO process
90
+	 * @type string $job_id          unique string identifying the job
91
+	 * @type string $update_text     string describing what happened during this step
92
+	 * } and any other items from $this->extra_data()
93
+	 */
94
+	public function to_array()
95
+	{
96
+		return apply_filters(
97
+			'FHEE__EventEspressoBatchRequest\Helpers\JobStepResponse__to_array__return',
98
+			array_merge(
99
+				$this->extra_data(),
100
+				array(
101
+					'status'          => $this->job_parameters()->status(),
102
+					'units_processed' => $this->job_parameters()->units_processed(),
103
+					'job_size'        => $this->job_parameters()->job_size(),
104
+					'job_id'          => $this->job_parameters()->job_id(),
105
+					'update_text'     => $this->update_text(),
106
+				)
107
+			),
108
+			$this
109
+		);
110
+	}
111 111
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/strategies/filter/VsprintfFilter.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -19,45 +19,45 @@
 block discarded – undo
19 19
 class VsprintfFilter extends FormHtmlFilter
20 20
 {
21 21
 
22
-    /**
23
-     * @var string $format
24
-     */
25
-    protected $format = '';
26
-
27
-
28
-    /**
29
-     * @var array $args
30
-     */
31
-    protected $args = array();
32
-
33
-
34
-    /**
35
-     * VsprintfFilter constructor.
36
-     *
37
-     * @param string $format
38
-     * @param array  $args
39
-     */
40
-    public function __construct($format, array $args)
41
-    {
42
-        $this->format = $format;
43
-        $this->args = $args;
44
-    }
45
-
46
-
47
-    /**
48
-     * @param                             $html
49
-     * @param EE_Form_Section_Validatable $form_section
50
-     * @return string
51
-     */
52
-    public function filterHtml($html, EE_Form_Section_Validatable $form_section)
53
-    {
54
-        $this->args[] = $html;
55
-        if ($form_section instanceof EE_Form_Section_Proper) {
56
-            $subsections = $form_section->subsections();
57
-            foreach ((array) $subsections as $subsection) {
58
-                $this->args[] = $subsection->get_html();
59
-            }
60
-        }
61
-        return vsprintf($this->format, $this->args);
62
-    }
22
+	/**
23
+	 * @var string $format
24
+	 */
25
+	protected $format = '';
26
+
27
+
28
+	/**
29
+	 * @var array $args
30
+	 */
31
+	protected $args = array();
32
+
33
+
34
+	/**
35
+	 * VsprintfFilter constructor.
36
+	 *
37
+	 * @param string $format
38
+	 * @param array  $args
39
+	 */
40
+	public function __construct($format, array $args)
41
+	{
42
+		$this->format = $format;
43
+		$this->args = $args;
44
+	}
45
+
46
+
47
+	/**
48
+	 * @param                             $html
49
+	 * @param EE_Form_Section_Validatable $form_section
50
+	 * @return string
51
+	 */
52
+	public function filterHtml($html, EE_Form_Section_Validatable $form_section)
53
+	{
54
+		$this->args[] = $html;
55
+		if ($form_section instanceof EE_Form_Section_Proper) {
56
+			$subsections = $form_section->subsections();
57
+			foreach ((array) $subsections as $subsection) {
58
+				$this->args[] = $subsection->get_html();
59
+			}
60
+		}
61
+		return vsprintf($this->format, $this->args);
62
+	}
63 63
 }
Please login to merge, or discard this patch.