Completed
Branch BUG/3575-event-deletion-previe... (bbeda1)
by
unknown
06:40 queued 04:49
created
core/libraries/rest_api/controllers/model/Read.php 2 patches
Indentation   +1625 added lines, -1625 removed lines patch added patch discarded remove patch
@@ -51,1629 +51,1629 @@
 block discarded – undo
51 51
 {
52 52
 
53 53
 
54
-    /**
55
-     * @var CalculatedModelFields
56
-     */
57
-    protected $fields_calculator;
58
-
59
-
60
-    /**
61
-     * Read constructor.
62
-     *
63
-     * @param CalculatedModelFields $fields_calculator
64
-     */
65
-    public function __construct(CalculatedModelFields $fields_calculator)
66
-    {
67
-        parent::__construct();
68
-        $this->fields_calculator = $fields_calculator;
69
-    }
70
-
71
-
72
-    /**
73
-     * Handles requests to get all (or a filtered subset) of entities for a particular model
74
-     *
75
-     * @param WP_REST_Request $request
76
-     * @param string          $version
77
-     * @param string          $model_name
78
-     * @return WP_REST_Response|WP_Error
79
-     * @throws InvalidArgumentException
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidInterfaceException
82
-     */
83
-    public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name)
84
-    {
85
-        $controller =
86
-            LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
87
-        try {
88
-            $controller->setRequestedVersion($version);
89
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
90
-                return $controller->sendResponse(
91
-                    new WP_Error(
92
-                        'endpoint_parsing_error',
93
-                        sprintf(
94
-                            esc_html__(
95
-                                'There is no model for endpoint %s. Please contact event espresso support',
96
-                                'event_espresso'
97
-                            ),
98
-                            $model_name
99
-                        )
100
-                    )
101
-                );
102
-            }
103
-            return $controller->sendResponse(
104
-                $controller->getEntitiesFromModel(
105
-                    $controller->getModelVersionInfo()->loadModel($model_name),
106
-                    $request
107
-                )
108
-            );
109
-        } catch (Exception $e) {
110
-            return $controller->sendResponse($e);
111
-        }
112
-    }
113
-
114
-
115
-    /**
116
-     * Prepares and returns schema for any OPTIONS request.
117
-     *
118
-     * @param string $version    The API endpoint version being used.
119
-     * @param string $model_name Something like `Event` or `Registration`
120
-     * @return array
121
-     * @throws InvalidArgumentException
122
-     * @throws InvalidDataTypeException
123
-     * @throws InvalidInterfaceException
124
-     */
125
-    public static function handleSchemaRequest($version, $model_name)
126
-    {
127
-        $controller =
128
-            LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
129
-        try {
130
-            $controller->setRequestedVersion($version);
131
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
132
-                return [];
133
-            }
134
-            // get the model for this version
135
-            $model        = $controller->getModelVersionInfo()->loadModel($model_name);
136
-            $model_schema = new JsonModelSchema(
137
-                $model,
138
-                LoaderFactory::getLoader()->getShared('EventEspresso\core\libraries\rest_api\CalculatedModelFields')
139
-            );
140
-            return $model_schema->getModelSchemaForRelations(
141
-                $controller->getModelVersionInfo()->relationSettings($model),
142
-                $controller->customizeSchemaForRestResponse(
143
-                    $model,
144
-                    $model_schema->getModelSchemaForFields(
145
-                        $controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model),
146
-                        $model_schema->getInitialSchemaStructure()
147
-                    )
148
-                )
149
-            );
150
-        } catch (Exception $e) {
151
-            return [];
152
-        }
153
-    }
154
-
155
-
156
-    /**
157
-     * This loops through each field in the given schema for the model and does the following:
158
-     * - add any extra fields that are REST API specific and related to existing fields.
159
-     * - transform default values into the correct format for a REST API response.
160
-     *
161
-     * @param EEM_Base $model
162
-     * @param array    $schema
163
-     * @return array  The final schema.
164
-     * @throws EE_Error
165
-     * @throws EE_Error
166
-     */
167
-    protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema)
168
-    {
169
-        foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) {
170
-            $schema = $this->translateDefaultsForRestResponse(
171
-                $field_name,
172
-                $field,
173
-                $this->maybeAddExtraFieldsToSchema($field_name, $field, $schema)
174
-            );
175
-        }
176
-        return $schema;
177
-    }
178
-
179
-
180
-    /**
181
-     * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
182
-     * response.
183
-     *
184
-     * @param                      $field_name
185
-     * @param EE_Model_Field_Base  $field
186
-     * @param array                $schema
187
-     * @return array
188
-     * @throws RestException  if a default value has a PHP object, which we should never do
189
-     *                                  (but if we did, let's know about it ASAP, so let the exception bubble up)
190
-     * @throws EE_Error
191
-     *
192
-     */
193
-    protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
194
-    {
195
-        if (isset($schema['properties'][ $field_name ]['default'])) {
196
-            if (is_array($schema['properties'][ $field_name ]['default'])) {
197
-                foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) {
198
-                    if ($default_key === 'raw') {
199
-                        $schema['properties'][ $field_name ]['default'][ $default_key ] =
200
-                            ModelDataTranslator::prepareFieldValueForJson(
201
-                                $field,
202
-                                $default_value,
203
-                                $this->getModelVersionInfo()->requestedVersion()
204
-                            );
205
-                    }
206
-                }
207
-            } else {
208
-                $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson(
209
-                    $field,
210
-                    $schema['properties'][ $field_name ]['default'],
211
-                    $this->getModelVersionInfo()->requestedVersion()
212
-                );
213
-            }
214
-        }
215
-        return $schema;
216
-    }
217
-
218
-
219
-    /**
220
-     * Adds additional fields to the schema
221
-     * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
222
-     * needs to be added to the schema.
223
-     *
224
-     * @param                      $field_name
225
-     * @param EE_Model_Field_Base  $field
226
-     * @param array                $schema
227
-     * @return array
228
-     */
229
-    protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
230
-    {
231
-        if ($field instanceof EE_Datetime_Field) {
232
-            $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema();
233
-            // modify the description
234
-            $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf(
235
-                esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
236
-                wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
237
-            );
238
-        }
239
-        return $schema;
240
-    }
241
-
242
-
243
-    /**
244
-     * Used to figure out the route from the request when a `WP_REST_Request` object is not available
245
-     *
246
-     * @return string
247
-     */
248
-    protected function getRouteFromRequest()
249
-    {
250
-        if (
251
-            isset($GLOBALS['wp'])
252
-            && $GLOBALS['wp'] instanceof WP
253
-            && isset($GLOBALS['wp']->query_vars['rest_route'])
254
-        ) {
255
-            return $GLOBALS['wp']->query_vars['rest_route'];
256
-        } else {
257
-            /** @var RequestInterface $request */
258
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
259
-            return $request->serverParamIsSet('PATH_INFO')
260
-                ? $request->getServerParam('PATH_INFO')
261
-                : '/';
262
-        }
263
-    }
264
-
265
-
266
-    /**
267
-     * Gets a single entity related to the model indicated in the path and its id
268
-     *
269
-     * @param WP_REST_Request $request
270
-     * @param string          $version
271
-     * @param string          $model_name
272
-     * @return WP_REST_Response|WP_Error
273
-     * @throws InvalidDataTypeException
274
-     * @throws InvalidInterfaceException
275
-     * @throws InvalidArgumentException
276
-     */
277
-    public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name)
278
-    {
279
-        $controller =
280
-            LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
281
-        try {
282
-            $controller->setRequestedVersion($version);
283
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
284
-                return $controller->sendResponse(
285
-                    new WP_Error(
286
-                        'endpoint_parsing_error',
287
-                        sprintf(
288
-                            esc_html__(
289
-                                'There is no model for endpoint %s. Please contact event espresso support',
290
-                                'event_espresso'
291
-                            ),
292
-                            $model_name
293
-                        )
294
-                    )
295
-                );
296
-            }
297
-            return $controller->sendResponse(
298
-                $controller->getEntityFromModel(
299
-                    $controller->getModelVersionInfo()->loadModel($model_name),
300
-                    $request
301
-                )
302
-            );
303
-        } catch (Exception $e) {
304
-            return $controller->sendResponse($e);
305
-        }
306
-    }
307
-
308
-
309
-    /**
310
-     * Gets all the related entities (or if its a belongs-to relation just the one)
311
-     * to the item with the given id
312
-     *
313
-     * @param WP_REST_Request $request
314
-     * @param string          $version
315
-     * @param string          $model_name
316
-     * @param string          $related_model_name
317
-     * @return WP_REST_Response|WP_Error
318
-     * @throws InvalidDataTypeException
319
-     * @throws InvalidInterfaceException
320
-     * @throws InvalidArgumentException
321
-     */
322
-    public static function handleRequestGetRelated(
323
-        WP_REST_Request $request,
324
-        $version,
325
-        $model_name,
326
-        $related_model_name
327
-    ) {
328
-        $controller =
329
-            LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
330
-        try {
331
-            $controller->setRequestedVersion($version);
332
-            $main_model = $controller->validateModel($model_name);
333
-            $controller->validateModel($related_model_name);
334
-            return $controller->sendResponse(
335
-                $controller->getEntitiesFromRelation(
336
-                    $request->get_param('id'),
337
-                    $main_model->related_settings_for($related_model_name),
338
-                    $request
339
-                )
340
-            );
341
-        } catch (Exception $e) {
342
-            return $controller->sendResponse($e);
343
-        }
344
-    }
345
-
346
-
347
-    /**
348
-     * Gets a collection for the given model and filters
349
-     *
350
-     * @param EEM_Base        $model
351
-     * @param WP_REST_Request $request
352
-     * @return array
353
-     * @throws EE_Error
354
-     * @throws InvalidArgumentException
355
-     * @throws InvalidDataTypeException
356
-     * @throws InvalidInterfaceException
357
-     * @throws ReflectionException
358
-     * @throws RestException
359
-     */
360
-    public function getEntitiesFromModel($model, $request)
361
-    {
362
-        $query_params = $this->createModelQueryParams($model, $request->get_params());
363
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
364
-            $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
365
-            throw new RestException(
366
-                sprintf('rest_%s_cannot_list', $model_name_plural),
367
-                sprintf(
368
-                    esc_html__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
369
-                    $model_name_plural,
370
-                    Capabilities::getMissingPermissionsString($model, $query_params['caps'])
371
-                ),
372
-                ['status' => 403]
373
-            );
374
-        }
375
-        if (! $request->get_header('no_rest_headers')) {
376
-            $this->setHeadersFromQueryParams($model, $query_params);
377
-        }
378
-        /** @type array $results */
379
-        $results      = $model->get_all_wpdb_results($query_params);
380
-        $nice_results = [];
381
-        foreach ($results as $result) {
382
-            $nice_results[] = $this->createEntityFromWpdbResult(
383
-                $model,
384
-                $result,
385
-                $request
386
-            );
387
-        }
388
-        return $nice_results;
389
-    }
390
-
391
-
392
-    /**
393
-     * Gets the collection for given relation object
394
-     * The same as Read::get_entities_from_model(), except if the relation
395
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
396
-     * the join-model-object into the results
397
-     *
398
-     * @param array                  $primary_model_query_params  query params for finding the item from which
399
-     *                                                            relations will be based
400
-     * @param EE_Model_Relation_Base $relation
401
-     * @param WP_REST_Request        $request
402
-     * @return array
403
-     * @throws EE_Error
404
-     * @throws InvalidArgumentException
405
-     * @throws InvalidDataTypeException
406
-     * @throws InvalidInterfaceException
407
-     * @throws ReflectionException
408
-     * @throws RestException
409
-     * @throws ModelConfigurationException
410
-     */
411
-    protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request)
412
-    {
413
-        $context       = $this->validateContext($request->get_param('caps'));
414
-        $model         = $relation->get_this_model();
415
-        $related_model = $relation->get_other_model();
416
-        if (! isset($primary_model_query_params[0])) {
417
-            $primary_model_query_params[0] = [];
418
-        }
419
-        // check if they can access the 1st model object
420
-        $primary_model_query_params = [
421
-            0       => $primary_model_query_params[0],
422
-            'limit' => 1,
423
-        ];
424
-        if ($model instanceof EEM_Soft_Delete_Base) {
425
-            $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included(
426
-                $primary_model_query_params
427
-            );
428
-        }
429
-        $restricted_query_params          = $primary_model_query_params;
430
-        $restricted_query_params['caps']  = $context;
431
-        $restricted_query_params['limit'] = 1;
432
-        $this->setDebugInfo('main model query params', $restricted_query_params);
433
-        $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
434
-        $primary_model_rows = $model->get_all_wpdb_results($restricted_query_params);
435
-        $primary_model_row  = null;
436
-        if (is_array($primary_model_rows)) {
437
-            $primary_model_row = reset($primary_model_rows);
438
-        }
439
-        if (
440
-            ! (
441
-                $primary_model_row
442
-                && Capabilities::currentUserHasPartialAccessTo($related_model, $context)
443
-            )
444
-        ) {
445
-            if ($relation instanceof EE_Belongs_To_Relation) {
446
-                $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
447
-            } else {
448
-                $related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower(
449
-                    $related_model->get_this_model_name()
450
-                );
451
-            }
452
-            throw new RestException(
453
-                sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
454
-                sprintf(
455
-                    esc_html__(
456
-                        'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
457
-                        'event_espresso'
458
-                    ),
459
-                    $related_model_name_maybe_plural,
460
-                    $relation->get_this_model()->get_this_model_name(),
461
-                    implode(
462
-                        ',',
463
-                        array_keys(
464
-                            Capabilities::getMissingPermissions($related_model, $context)
465
-                        )
466
-                    )
467
-                ),
468
-                ['status' => 403]
469
-            );
470
-        }
471
-
472
-        $this->checkPassword(
473
-            $model,
474
-            $primary_model_row,
475
-            $restricted_query_params,
476
-            $request
477
-        );
478
-        $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
479
-        foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
480
-            $query_params[0][ $relation->get_this_model()->get_this_model_name()
481
-                              . '.'
482
-                              . $where_condition_key ] = $where_condition_value;
483
-        }
484
-        $query_params['default_where_conditions'] = 'none';
485
-        $query_params['caps']                     = $context;
486
-        if (! $request->get_header('no_rest_headers')) {
487
-            $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
488
-        }
489
-        /** @type array $results */
490
-        $results      = $relation->get_other_model()->get_all_wpdb_results($query_params);
491
-        $nice_results = [];
492
-        foreach ($results as $result) {
493
-            $nice_result = $this->createEntityFromWpdbResult(
494
-                $relation->get_other_model(),
495
-                $result,
496
-                $request
497
-            );
498
-            if ($relation instanceof EE_HABTM_Relation) {
499
-                // put the unusual stuff (properties from the HABTM relation) first, and make sure
500
-                // if there are conflicts we prefer the properties from the main model
501
-                $join_model_result = $this->createEntityFromWpdbResult(
502
-                    $relation->get_join_model(),
503
-                    $result,
504
-                    $request
505
-                );
506
-                $joined_result     = array_merge($join_model_result, $nice_result);
507
-                // but keep the meta stuff from the main model
508
-                if (isset($nice_result['meta'])) {
509
-                    $joined_result['meta'] = $nice_result['meta'];
510
-                }
511
-                $nice_result = $joined_result;
512
-            }
513
-            $nice_results[] = $nice_result;
514
-        }
515
-        if ($relation instanceof EE_Belongs_To_Relation) {
516
-            return array_shift($nice_results);
517
-        } else {
518
-            return $nice_results;
519
-        }
520
-    }
521
-
522
-
523
-    /**
524
-     * Gets the collection for given relation object
525
-     * The same as Read::get_entities_from_model(), except if the relation
526
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
527
-     * the join-model-object into the results
528
-     *
529
-     * @param string                 $id the ID of the thing we are fetching related stuff from
530
-     * @param EE_Model_Relation_Base $relation
531
-     * @param WP_REST_Request        $request
532
-     * @return array
533
-     * @throws EE_Error
534
-     * @throws ReflectionException
535
-     */
536
-    public function getEntitiesFromRelation($id, $relation, $request)
537
-    {
538
-        if (! $relation->get_this_model()->has_primary_key_field()) {
539
-            throw new EE_Error(
540
-                sprintf(
541
-                    esc_html__(
542
-                    // @codingStandardsIgnoreStart
543
-                        'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
544
-                        // @codingStandardsIgnoreEnd
545
-                        'event_espresso'
546
-                    ),
547
-                    $relation->get_this_model()->get_this_model_name()
548
-                )
549
-            );
550
-        }
551
-        // can we edit that main item?
552
-        // if not, show nothing but an error
553
-        // otherwise, please proceed
554
-        return $this->getEntitiesFromRelationUsingModelQueryParams(
555
-            [
556
-                [
557
-                    $relation->get_this_model()->primary_key_name() => $id,
558
-                ],
559
-            ],
560
-            $relation,
561
-            $request
562
-        );
563
-    }
564
-
565
-
566
-    /**
567
-     * Sets the headers that are based on the model and query params,
568
-     * like the total records. This should only be called on the original request
569
-     * from the client, not on subsequent internal
570
-     *
571
-     * @param EEM_Base $model
572
-     * @param array    $query_params
573
-     * @return void
574
-     * @throws EE_Error
575
-     * @throws EE_Error
576
-     */
577
-    protected function setHeadersFromQueryParams($model, $query_params)
578
-    {
579
-        $this->setDebugInfo('model query params', $query_params);
580
-        $this->setDebugInfo(
581
-            'missing caps',
582
-            Capabilities::getMissingPermissionsString($model, $query_params['caps'])
583
-        );
584
-        // normally the limit to a 2-part array, where the 2nd item is the limit
585
-        if (! isset($query_params['limit'])) {
586
-            $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
587
-        }
588
-        if (is_array($query_params['limit'])) {
589
-            $limit_parts = $query_params['limit'];
590
-        } else {
591
-            $limit_parts = explode(',', $query_params['limit']);
592
-            if (count($limit_parts) == 1) {
593
-                $limit_parts = [0, $limit_parts[0]];
594
-            }
595
-        }
596
-        // remove the group by and having parts of the query, as those will
597
-        // make the sql query return an array of values, instead of just a single value
598
-        unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
599
-        $count = $model->count($query_params, null, true);
600
-        $pages = $count / $limit_parts[1];
601
-        $this->setResponseHeader('Total', $count, false);
602
-        $this->setResponseHeader('PageSize', $limit_parts[1], false);
603
-        $this->setResponseHeader('TotalPages', ceil($pages), false);
604
-    }
605
-
606
-
607
-    /**
608
-     * Changes database results into REST API entities
609
-     *
610
-     * @param EEM_Base        $model
611
-     * @param array           $db_row     like results from $wpdb->get_results()
612
-     * @param WP_REST_Request $rest_request
613
-     * @param string          $deprecated no longer used
614
-     * @return array ready for being converted into json for sending to client
615
-     * @throws EE_Error
616
-     * @throws RestException
617
-     * @throws InvalidDataTypeException
618
-     * @throws InvalidInterfaceException
619
-     * @throws InvalidArgumentException
620
-     * @throws ReflectionException
621
-     */
622
-    public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
623
-    {
624
-        if (! $rest_request instanceof WP_REST_Request) {
625
-            // ok so this was called in the old style, where the 3rd arg was
626
-            // $include, and the 4th arg was $context
627
-            // now setup the request just to avoid fatal errors, although we won't be able
628
-            // to truly make use of it because it's kinda devoid of info
629
-            $rest_request = new WP_REST_Request();
630
-            $rest_request->set_param('include', $rest_request);
631
-            $rest_request->set_param('caps', $deprecated);
632
-        }
633
-        if ($rest_request->get_param('caps') == null) {
634
-            $rest_request->set_param('caps', EEM_Base::caps_read);
635
-        }
636
-        $current_user_full_access_to_entity = $model->currentUserCan(
637
-            EEM_Base::caps_read_admin,
638
-            $model->deduce_fields_n_values_from_cols_n_values($db_row)
639
-        );
640
-        $entity_array                       = $this->createBareEntityFromWpdbResults($model, $db_row);
641
-        $entity_array                       = $this->addExtraFields($model, $db_row, $entity_array);
642
-        $entity_array['_links']             = $this->getEntityLinks($model, $db_row, $entity_array);
643
-        // when it's a regular read request for a model with a password and the password wasn't provided
644
-        // remove the password protected fields
645
-        $has_protected_fields = false;
646
-        try {
647
-            $this->checkPassword(
648
-                $model,
649
-                $db_row,
650
-                $model->alter_query_params_to_restrict_by_ID(
651
-                    $model->get_index_primary_key_string(
652
-                        $model->deduce_fields_n_values_from_cols_n_values($db_row)
653
-                    )
654
-                ),
655
-                $rest_request
656
-            );
657
-        } catch (RestPasswordRequiredException $e) {
658
-            if ($model->hasPassword()) {
659
-                // just remove protected fields
660
-                $has_protected_fields = true;
661
-                $entity_array         = Capabilities::filterOutPasswordProtectedFields(
662
-                    $entity_array,
663
-                    $model,
664
-                    $this->getModelVersionInfo()
665
-                );
666
-            } else {
667
-                // that's a problem. None of this should be accessible if no password was provided
668
-                throw $e;
669
-            }
670
-        }
671
-
672
-        $entity_array['_calculated_fields'] =
673
-            $this->getEntityCalculations($model, $db_row, $rest_request, $has_protected_fields);
674
-        $entity_array                       = apply_filters(
675
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
676
-            $entity_array,
677
-            $model,
678
-            $rest_request->get_param('caps'),
679
-            $rest_request,
680
-            $this
681
-        );
682
-        // add an empty protected property for now. If it's still around after we remove everything the request didn't
683
-        // want, we'll populate it then. k?
684
-        $entity_array['_protected'] = [];
685
-        // remove any properties the request didn't want. This way _protected won't bother mentioning them
686
-        $entity_array = $this->includeOnlyRequestedProperties($model, $rest_request, $entity_array);
687
-        $entity_array =
688
-            $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row, $has_protected_fields);
689
-        // if they still wanted the _protected property, add it.
690
-        if (isset($entity_array['_protected'])) {
691
-            $entity_array = $this->addProtectedProperty($model, $entity_array, $has_protected_fields);
692
-        }
693
-        $entity_array = apply_filters(
694
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
695
-            $entity_array,
696
-            $model,
697
-            $rest_request->get_param('caps'),
698
-            $rest_request,
699
-            $this
700
-        );
701
-        if (! $current_user_full_access_to_entity) {
702
-            $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields(
703
-                $entity_array,
704
-                $model,
705
-                $rest_request->get_param('caps'),
706
-                $this->getModelVersionInfo()
707
-            );
708
-        } else {
709
-            $result_without_inaccessible_fields = $entity_array;
710
-        }
711
-        $this->setDebugInfo(
712
-            'inaccessible fields',
713
-            array_keys(array_diff_key((array) $entity_array, (array) $result_without_inaccessible_fields))
714
-        );
715
-        return apply_filters(
716
-            'FHEE__Read__create_entity_from_wpdb_results__entity_return',
717
-            $result_without_inaccessible_fields,
718
-            $model,
719
-            $rest_request->get_param('caps')
720
-        );
721
-    }
722
-
723
-
724
-    /**
725
-     * Returns an array describing which fields can be protected, and which actually were removed this request
726
-     *
727
-     * @param EEM_Base $model
728
-     * @param array    $results_so_far
729
-     * @param bool     $protected
730
-     * @return array results
731
-     * @throws EE_Error
732
-     * @since 4.9.74.p
733
-     */
734
-    protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected)
735
-    {
736
-        if (! $model->hasPassword() || ! $protected) {
737
-            return $results_so_far;
738
-        }
739
-        $password_field  = $model->getPasswordField();
740
-        $all_protected   = array_merge(
741
-            [$password_field->get_name()],
742
-            $password_field->protectedFields()
743
-        );
744
-        $fields_included = array_keys($results_so_far);
745
-        $fields_included = array_intersect(
746
-            $all_protected,
747
-            $fields_included
748
-        );
749
-        foreach ($fields_included as $field_name) {
750
-            $results_so_far['_protected'][] = $field_name;
751
-        }
752
-        return $results_so_far;
753
-    }
754
-
755
-
756
-    /**
757
-     * Creates a REST entity array (JSON object we're going to return in the response, but
758
-     * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
759
-     * from $wpdb->get_row( $sql, ARRAY_A)
760
-     *
761
-     * @param EEM_Base $model
762
-     * @param array    $db_row
763
-     * @return array entity mostly ready for converting to JSON and sending in the response
764
-     * @throws EE_Error
765
-     * @throws ReflectionException
766
-     * @throws RestException
767
-     */
768
-    protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row)
769
-    {
770
-        $result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
771
-        $result = array_intersect_key(
772
-            $result,
773
-            $this->getModelVersionInfo()->fieldsOnModelInThisVersion($model)
774
-        );
775
-        // if this is a CPT, we need to set the global $post to it,
776
-        // otherwise shortcodes etc won't work properly while rendering it
777
-        if ($model instanceof EEM_CPT_Base) {
778
-            $do_chevy_shuffle = true;
779
-        } else {
780
-            $do_chevy_shuffle = false;
781
-        }
782
-        if ($do_chevy_shuffle) {
783
-            global $post;
784
-            $old_post = $post;
785
-            $post     = get_post($result[ $model->primary_key_name() ]);
786
-            if (! $post instanceof WP_Post) {
787
-                // well that's weird, because $result is what we JUST fetched from the database
788
-                throw new RestException(
789
-                    'error_fetching_post_from_database_results',
790
-                    esc_html__(
791
-                        'An item was retrieved from the database but it\'s not a WP_Post like it should be.',
792
-                        'event_espresso'
793
-                    )
794
-                );
795
-            }
796
-            $model_object_classname          = 'EE_' . $model->get_this_model_name();
797
-            $post->{$model_object_classname} = EE_Registry::instance()->load_class(
798
-                $model_object_classname,
799
-                $result,
800
-                false,
801
-                false
802
-            );
803
-        }
804
-        foreach ($result as $field_name => $field_value) {
805
-            $field_obj = $model->field_settings_for($field_name);
806
-            if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
807
-                unset($result[ $field_name ]);
808
-            } elseif (
809
-                $this->isSubclassOfOne(
810
-                    $field_obj,
811
-                    $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
812
-                )
813
-            ) {
814
-                $result[ $field_name ] = [
815
-                    'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
816
-                    'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
817
-                ];
818
-            } elseif (
819
-                $this->isSubclassOfOne(
820
-                    $field_obj,
821
-                    $this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
822
-                )
823
-            ) {
824
-                $result[ $field_name ] = [
825
-                    'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
826
-                    'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
827
-                ];
828
-            } elseif ($field_obj instanceof EE_Datetime_Field) {
829
-                $field_value = $field_obj->prepare_for_set_from_db($field_value);
830
-                // if the value is null, but we're not supposed to permit null, then set to the field's default
831
-                if (is_null($field_value)) {
832
-                    $field_value = $field_obj->getDefaultDateTimeObj();
833
-                }
834
-                if (is_null($field_value)) {
835
-                    $gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson(
836
-                        $field_obj,
837
-                        $field_value,
838
-                        $this->getModelVersionInfo()->requestedVersion()
839
-                    );
840
-                } else {
841
-                    $timezone = $field_value->getTimezone();
842
-                    EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC'));
843
-                    $gmt_date = ModelDataTranslator::prepareFieldValuesForJson(
844
-                        $field_obj,
845
-                        $field_value,
846
-                        $this->getModelVersionInfo()->requestedVersion()
847
-                    );
848
-                    EEH_DTT_Helper::setTimezone($field_value, $timezone);
849
-                    $local_date = ModelDataTranslator::prepareFieldValuesForJson(
850
-                        $field_obj,
851
-                        $field_value,
852
-                        $this->getModelVersionInfo()->requestedVersion()
853
-                    );
854
-                }
855
-                $result[ $field_name . '_gmt' ] = $gmt_date;
856
-                $result[ $field_name ]          = $local_date;
857
-            } else {
858
-                $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
859
-            }
860
-        }
861
-        if ($do_chevy_shuffle) {
862
-            $post = $old_post;
863
-        }
864
-        return $result;
865
-    }
866
-
867
-
868
-    /**
869
-     * Takes a value all the way from the DB representation, to the model object's representation, to the
870
-     * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB
871
-     * representation using $field_obj->prepare_for_set_from_db())
872
-     *
873
-     * @param EE_Model_Field_Base $field_obj
874
-     * @param mixed               $value  as it's stored on a model object
875
-     * @param string              $format valid values are 'normal' (default), 'pretty', 'datetime_obj'
876
-     * @return array
877
-     * @throws RestException if $value contains a PHP object
878
-     * @throws EE_Error
879
-     */
880
-    protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal')
881
-    {
882
-        $value = $field_obj->prepare_for_set_from_db($value);
883
-        switch ($format) {
884
-            case 'pretty':
885
-                $value = $field_obj->prepare_for_pretty_echoing($value);
886
-                break;
887
-            case 'normal':
888
-            default:
889
-                $value = $field_obj->prepare_for_get($value);
890
-                break;
891
-        }
892
-        return ModelDataTranslator::prepareFieldValuesForJson(
893
-            $field_obj,
894
-            $value,
895
-            $this->getModelVersionInfo()->requestedVersion()
896
-        );
897
-    }
898
-
899
-
900
-    /**
901
-     * Adds a few extra fields to the entity response
902
-     *
903
-     * @param EEM_Base $model
904
-     * @param array    $db_row
905
-     * @param array    $entity_array
906
-     * @return array modified entity
907
-     * @throws EE_Error
908
-     * @throws EE_Error
909
-     */
910
-    protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
911
-    {
912
-        if ($model instanceof EEM_CPT_Base) {
913
-            $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]);
914
-        }
915
-        return $entity_array;
916
-    }
917
-
918
-
919
-    /**
920
-     * Gets links we want to add to the response
921
-     *
922
-     * @param EEM_Base        $model
923
-     * @param array           $db_row
924
-     * @param array           $entity_array
925
-     * @return array the _links item in the entity
926
-     * @throws EE_Error
927
-     * @throws EE_Error
928
-     * @global WP_REST_Server $wp_rest_server
929
-     */
930
-    protected function getEntityLinks($model, $db_row, $entity_array)
931
-    {
932
-        // add basic links
933
-        $links = [];
934
-        if ($model->has_primary_key_field()) {
935
-            $links['self'] = [
936
-                [
937
-                    'href' => $this->getVersionedLinkTo(
938
-                        EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
939
-                        . '/'
940
-                        . $entity_array[ $model->primary_key_name() ]
941
-                    ),
942
-                ],
943
-            ];
944
-        }
945
-        $links['collection'] = [
946
-            [
947
-                'href' => $this->getVersionedLinkTo(
948
-                    EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
949
-                ),
950
-            ],
951
-        ];
952
-        // add links to related models
953
-        if ($model->has_primary_key_field()) {
954
-            foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
955
-                $related_model_part                                                      =
956
-                    Read::getRelatedEntityName($relation_name, $relation_obj);
957
-                $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [
958
-                    [
959
-                        'href'   => $this->getVersionedLinkTo(
960
-                            EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
961
-                            . '/'
962
-                            . $entity_array[ $model->primary_key_name() ]
963
-                            . '/'
964
-                            . $related_model_part
965
-                        ),
966
-                        'single' => $relation_obj instanceof EE_Belongs_To_Relation,
967
-                    ],
968
-                ];
969
-            }
970
-        }
971
-        return $links;
972
-    }
973
-
974
-
975
-    /**
976
-     * Adds the included models indicated in the request to the entity provided
977
-     *
978
-     * @param EEM_Base        $model
979
-     * @param WP_REST_Request $rest_request
980
-     * @param array           $entity_array
981
-     * @param array           $db_row
982
-     * @param boolean         $included_items_protected if the original item is password protected, don't include any
983
-     *                                                  related models.
984
-     * @return array the modified entity
985
-     * @throws EE_Error
986
-     * @throws ReflectionException
987
-     */
988
-    protected function includeRequestedModels(
989
-        EEM_Base $model,
990
-        WP_REST_Request $rest_request,
991
-        $entity_array,
992
-        $db_row = [],
993
-        $included_items_protected = false
994
-    ) {
995
-        // if $db_row not included, hope the entity array has what we need
996
-        if (! $db_row) {
997
-            $db_row = $entity_array;
998
-        }
999
-        $relation_settings = $this->getModelVersionInfo()->relationSettings($model);
1000
-        foreach ($relation_settings as $relation_name => $relation_obj) {
1001
-            $related_fields_to_include   = $this->explodeAndGetItemsPrefixedWith(
1002
-                $rest_request->get_param('include'),
1003
-                $relation_name
1004
-            );
1005
-            $related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith(
1006
-                $rest_request->get_param('calculate'),
1007
-                $relation_name
1008
-            );
1009
-            // did they specify they wanted to include a related model, or
1010
-            // specific fields from a related model?
1011
-            // or did they specify to calculate a field from a related model?
1012
-            if ($related_fields_to_include || $related_fields_to_calculate) {
1013
-                // if so, we should include at least some part of the related model
1014
-                $pretend_related_request = new WP_REST_Request();
1015
-                $pretend_related_request->set_query_params(
1016
-                    [
1017
-                        'caps'      => $rest_request->get_param('caps'),
1018
-                        'include'   => $related_fields_to_include,
1019
-                        'calculate' => $related_fields_to_calculate,
1020
-                        'password'  => $rest_request->get_param('password'),
1021
-                    ]
1022
-                );
1023
-                $pretend_related_request->add_header('no_rest_headers', true);
1024
-                $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
1025
-                    $model->get_index_primary_key_string(
1026
-                        $model->deduce_fields_n_values_from_cols_n_values($db_row)
1027
-                    )
1028
-                );
1029
-                if (! $included_items_protected) {
1030
-                    try {
1031
-                        $related_results = $this->getEntitiesFromRelationUsingModelQueryParams(
1032
-                            $primary_model_query_params,
1033
-                            $relation_obj,
1034
-                            $pretend_related_request
1035
-                        );
1036
-                    } catch (RestException $e) {
1037
-                        $related_results = null;
1038
-                    }
1039
-                } else {
1040
-                    // they're protected, hide them.
1041
-                    $related_results              = null;
1042
-                    $entity_array['_protected'][] = Read::getRelatedEntityName($relation_name, $relation_obj);
1043
-                }
1044
-                if ($related_results instanceof WP_Error || $related_results === null) {
1045
-                    $related_results =
1046
-                        $relation_obj instanceof EE_Belongs_To_Relation
1047
-                            ? null
1048
-                            : [];
1049
-                }
1050
-                $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results;
1051
-            }
1052
-        }
1053
-        return $entity_array;
1054
-    }
1055
-
1056
-
1057
-    /**
1058
-     * If the user has requested only specific properties (including meta properties like _links or _protected)
1059
-     * remove everything else.
1060
-     *
1061
-     * @param EEM_Base        $model
1062
-     * @param WP_REST_Request $rest_request
1063
-     * @param                 $entity_array
1064
-     * @return array
1065
-     * @throws EE_Error
1066
-     * @since 4.9.74.p
1067
-     */
1068
-    protected function includeOnlyRequestedProperties(
1069
-        EEM_Base $model,
1070
-        WP_REST_Request $rest_request,
1071
-        $entity_array
1072
-    ) {
1073
-
1074
-        $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
1075
-        $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
1076
-        // if they passed in * or didn't specify any includes, return everything
1077
-        if (
1078
-            ! in_array('*', $includes_for_this_model)
1079
-            && ! empty($includes_for_this_model)
1080
-        ) {
1081
-            if ($model->has_primary_key_field()) {
1082
-                // always include the primary key. ya just gotta know that at least
1083
-                $includes_for_this_model[] = $model->primary_key_name();
1084
-            }
1085
-            if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) {
1086
-                $includes_for_this_model[] = '_calculated_fields';
1087
-            }
1088
-            $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
1089
-        }
1090
-        return $entity_array;
1091
-    }
1092
-
1093
-
1094
-    /**
1095
-     * Returns a new array with all the names of models removed. Eg
1096
-     * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
1097
-     *
1098
-     * @param array $arr
1099
-     * @return array
1100
-     */
1101
-    private function removeModelNamesFromArray($arr)
1102
-    {
1103
-        return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models));
1104
-    }
1105
-
1106
-
1107
-    /**
1108
-     * Gets the calculated fields for the response
1109
-     *
1110
-     * @param EEM_Base        $model
1111
-     * @param array           $wpdb_row
1112
-     * @param WP_REST_Request $rest_request
1113
-     * @param boolean         $row_is_protected whether this row is password protected or not
1114
-     * @return stdClass the _calculations item in the entity
1115
-     * @throws RestException if a default value has a PHP object, which should never do (and if we
1116
-     * @throws EE_Error
1117
-     *                                          did, let's know about it ASAP, so let the exception bubble up)
1118
-     */
1119
-    protected function getEntityCalculations($model, $wpdb_row, $rest_request, $row_is_protected = false)
1120
-    {
1121
-        $calculated_fields = $this->explodeAndGetItemsPrefixedWith(
1122
-            $rest_request->get_param('calculate'),
1123
-            ''
1124
-        );
1125
-        // note: setting calculate=* doesn't do anything
1126
-        $calculated_fields_to_return = new stdClass();
1127
-        $protected_fields            = [];
1128
-        foreach ($calculated_fields as $field_to_calculate) {
1129
-            try {
1130
-                // it's password protected, so they shouldn't be able to read this. Remove the value
1131
-                $schema = $this->fields_calculator->getJsonSchemaForModel($model);
1132
-                if (
1133
-                    $row_is_protected
1134
-                    && isset($schema['properties'][ $field_to_calculate ]['protected'])
1135
-                    && $schema['properties'][ $field_to_calculate ]['protected']
1136
-                ) {
1137
-                    $calculated_value   = null;
1138
-                    $protected_fields[] = $field_to_calculate;
1139
-                    if ($schema['properties'][ $field_to_calculate ]['type']) {
1140
-                        switch ($schema['properties'][ $field_to_calculate ]['type']) {
1141
-                            case 'boolean':
1142
-                                $calculated_value = false;
1143
-                                break;
1144
-                            case 'integer':
1145
-                                $calculated_value = 0;
1146
-                                break;
1147
-                            case 'string':
1148
-                                $calculated_value = '';
1149
-                                break;
1150
-                            case 'array':
1151
-                                $calculated_value = [];
1152
-                                break;
1153
-                            case 'object':
1154
-                                $calculated_value = new stdClass();
1155
-                                break;
1156
-                        }
1157
-                    }
1158
-                } else {
1159
-                    $calculated_value = ModelDataTranslator::prepareFieldValueForJson(
1160
-                        null,
1161
-                        $this->fields_calculator->retrieveCalculatedFieldValue(
1162
-                            $model,
1163
-                            $field_to_calculate,
1164
-                            $wpdb_row,
1165
-                            $rest_request,
1166
-                            $this
1167
-                        ),
1168
-                        $this->getModelVersionInfo()->requestedVersion()
1169
-                    );
1170
-                }
1171
-                $calculated_fields_to_return->{$field_to_calculate} = $calculated_value;
1172
-            } catch (RestException $e) {
1173
-                // if we don't have permission to read it, just leave it out. but let devs know about the problem
1174
-                $this->setResponseHeader(
1175
-                    'Notices-Field-Calculation-Errors['
1176
-                    . $e->getStringCode()
1177
-                    . ']['
1178
-                    . $model->get_this_model_name()
1179
-                    . ']['
1180
-                    . $field_to_calculate
1181
-                    . ']',
1182
-                    $e->getMessage(),
1183
-                    true
1184
-                );
1185
-            }
1186
-        }
1187
-        $calculated_fields_to_return->_protected = $protected_fields;
1188
-        return $calculated_fields_to_return;
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * Gets the full URL to the resource, taking the requested version into account
1194
-     *
1195
-     * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
1196
-     * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
1197
-     * @throws EE_Error
1198
-     * @throws EE_Error
1199
-     */
1200
-    public function getVersionedLinkTo($link_part_after_version_and_slash)
1201
-    {
1202
-        return rest_url(
1203
-            EED_Core_Rest_Api::get_versioned_route_to(
1204
-                $link_part_after_version_and_slash,
1205
-                $this->getModelVersionInfo()->requestedVersion()
1206
-            )
1207
-        );
1208
-    }
1209
-
1210
-
1211
-    /**
1212
-     * Gets the correct lowercase name for the relation in the API according
1213
-     * to the relation's type
1214
-     *
1215
-     * @param string                 $relation_name
1216
-     * @param EE_Model_Relation_Base $relation_obj
1217
-     * @return string
1218
-     */
1219
-    public static function getRelatedEntityName($relation_name, $relation_obj)
1220
-    {
1221
-        if ($relation_obj instanceof EE_Belongs_To_Relation) {
1222
-            return strtolower($relation_name);
1223
-        } else {
1224
-            return EEH_Inflector::pluralize_and_lower($relation_name);
1225
-        }
1226
-    }
1227
-
1228
-
1229
-    /**
1230
-     * Gets the one model object with the specified id for the specified model
1231
-     *
1232
-     * @param EEM_Base        $model
1233
-     * @param WP_REST_Request $request
1234
-     * @return array
1235
-     * @throws EE_Error
1236
-     * @throws EE_Error
1237
-     * @throws ReflectionException
1238
-     */
1239
-    public function getEntityFromModel($model, $request)
1240
-    {
1241
-        $context = $this->validateContext($request->get_param('caps'));
1242
-        return $this->getOneOrReportPermissionError($model, $request, $context);
1243
-    }
1244
-
1245
-
1246
-    /**
1247
-     * If a context is provided which isn't valid, maybe it was added in a future
1248
-     * version so just treat it as a default read
1249
-     *
1250
-     * @param string $context
1251
-     * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
1252
-     */
1253
-    public function validateContext($context)
1254
-    {
1255
-        if (! $context) {
1256
-            $context = EEM_Base::caps_read;
1257
-        }
1258
-        $valid_contexts = EEM_Base::valid_cap_contexts();
1259
-        if (in_array($context, $valid_contexts)) {
1260
-            return $context;
1261
-        } else {
1262
-            return EEM_Base::caps_read;
1263
-        }
1264
-    }
1265
-
1266
-
1267
-    /**
1268
-     * Verifies the passed in value is an allowable default where conditions value.
1269
-     *
1270
-     * @param $default_query_params
1271
-     * @return string
1272
-     */
1273
-    public function validateDefaultQueryParams($default_query_params)
1274
-    {
1275
-        $valid_default_where_conditions_for_api_calls = [
1276
-            EEM_Base::default_where_conditions_all,
1277
-            EEM_Base::default_where_conditions_minimum_all,
1278
-            EEM_Base::default_where_conditions_minimum_others,
1279
-        ];
1280
-        if (! $default_query_params) {
1281
-            $default_query_params = EEM_Base::default_where_conditions_all;
1282
-        }
1283
-        if (
1284
-            in_array(
1285
-                $default_query_params,
1286
-                $valid_default_where_conditions_for_api_calls,
1287
-                true
1288
-            )
1289
-        ) {
1290
-            return $default_query_params;
1291
-        }
1292
-        return EEM_Base::default_where_conditions_all;
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * Translates API filter get parameter into model query params @see
1298
-     * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions.
1299
-     * Note: right now the query parameter keys for fields (and related fields) can be left as-is, but it's quite
1300
-     * possible this will change someday. Also, this method's contents might be candidate for moving to
1301
-     * Model_Data_Translator
1302
-     *
1303
-     * @param EEM_Base $model
1304
-     * @param array    $query_params
1305
-     * @return array model query params (@see
1306
-     *               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions)
1307
-     *               or FALSE to indicate that absolutely no results should be returned
1308
-     * @throws EE_Error
1309
-     * @throws RestException
1310
-     */
1311
-    public function createModelQueryParams($model, $query_params)
1312
-    {
1313
-        $model_query_params = [];
1314
-        if (isset($query_params['where'])) {
1315
-            $model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1316
-                $query_params['where'],
1317
-                $model,
1318
-                $this->getModelVersionInfo()->requestedVersion()
1319
-            );
1320
-        }
1321
-        if (isset($query_params['order_by'])) {
1322
-            $order_by = $query_params['order_by'];
1323
-        } elseif (isset($query_params['orderby'])) {
1324
-            $order_by = $query_params['orderby'];
1325
-        } else {
1326
-            $order_by = null;
1327
-        }
1328
-        if ($order_by !== null) {
1329
-            if (is_array($order_by)) {
1330
-                $order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by);
1331
-            } else {
1332
-                // it's a single item
1333
-                $order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by);
1334
-            }
1335
-            $model_query_params['order_by'] = $order_by;
1336
-        }
1337
-        if (isset($query_params['group_by'])) {
1338
-            $group_by = $query_params['group_by'];
1339
-        } elseif (isset($query_params['groupby'])) {
1340
-            $group_by = $query_params['groupby'];
1341
-        } else {
1342
-            $group_by = array_keys($model->get_combined_primary_key_fields());
1343
-        }
1344
-        // make sure they're all real names
1345
-        if (is_array($group_by)) {
1346
-            $group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by);
1347
-        }
1348
-        if ($group_by !== null) {
1349
-            $model_query_params['group_by'] = $group_by;
1350
-        }
1351
-        if (isset($query_params['having'])) {
1352
-            $model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1353
-                $query_params['having'],
1354
-                $model,
1355
-                $this->getModelVersionInfo()->requestedVersion()
1356
-            );
1357
-        }
1358
-        if (isset($query_params['order'])) {
1359
-            $model_query_params['order'] = $query_params['order'];
1360
-        }
1361
-        if (isset($query_params['mine'])) {
1362
-            $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1363
-        }
1364
-        if (isset($query_params['limit'])) {
1365
-            // limit should be either a string like '23' or '23,43', or an array with two items in it
1366
-            if (! is_array($query_params['limit'])) {
1367
-                $limit_array = explode(',', (string) $query_params['limit']);
1368
-            } else {
1369
-                $limit_array = $query_params['limit'];
1370
-            }
1371
-            $sanitized_limit = [];
1372
-            foreach ($limit_array as $limit_part) {
1373
-                if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1374
-                    throw new EE_Error(
1375
-                        sprintf(
1376
-                            esc_html__(
1377
-                            // @codingStandardsIgnoreStart
1378
-                                'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.',
1379
-                                // @codingStandardsIgnoreEnd
1380
-                                'event_espresso'
1381
-                            ),
1382
-                            wp_json_encode($query_params['limit'])
1383
-                        )
1384
-                    );
1385
-                }
1386
-                $sanitized_limit[] = (int) $limit_part;
1387
-            }
1388
-            $model_query_params['limit'] = implode(',', $sanitized_limit);
1389
-        } else {
1390
-            $model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
1391
-        }
1392
-        if (isset($query_params['caps'])) {
1393
-            $model_query_params['caps'] = $this->validateContext($query_params['caps']);
1394
-        } else {
1395
-            $model_query_params['caps'] = EEM_Base::caps_read;
1396
-        }
1397
-        if (isset($query_params['default_where_conditions'])) {
1398
-            $model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams(
1399
-                $query_params['default_where_conditions']
1400
-            );
1401
-        }
1402
-        // if this is a model protected by a password on another model, exclude the password protected
1403
-        // entities by default. But if they passed in a password, try to show them all. If the password is wrong,
1404
-        // though, they'll get an error (see Read::createEntityFromWpdbResult() which calls Read::checkPassword)
1405
-        if (
1406
-            ! $model->hasPassword()
1407
-            && $model->restrictedByRelatedModelPassword()
1408
-            && $model_query_params['caps'] === EEM_Base::caps_read
1409
-        ) {
1410
-            if (empty($query_params['password'])) {
1411
-                $model_query_params['exclude_protected'] = true;
1412
-            }
1413
-        }
1414
-
1415
-        return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_params, $model);
1416
-    }
1417
-
1418
-
1419
-    /**
1420
-     * Changes the REST-style query params for use in the models
1421
-     *
1422
-     * @param EEM_Base $model
1423
-     * @param array    $query_params sub-array from @see EEM_Base::get_all()
1424
-     * @return array
1425
-     * @deprecated
1426
-     */
1427
-    public function prepareRestQueryParamsKeyForModels($model, $query_params)
1428
-    {
1429
-        $model_ready_query_params = [];
1430
-        foreach ($query_params as $key => $value) {
1431
-            $model_ready_query_params[ $key ] = is_array($value)
1432
-                ? $this->prepareRestQueryParamsKeyForModels($model, $value)
1433
-                : $value;
1434
-        }
1435
-        return $model_ready_query_params;
1436
-    }
1437
-
1438
-
1439
-    /**
1440
-     * @param $model
1441
-     * @param $query_params
1442
-     * @return array
1443
-     * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson()
1444
-     */
1445
-    public function prepareRestQueryParamsValuesForModels($model, $query_params)
1446
-    {
1447
-        $model_ready_query_params = [];
1448
-        foreach ($query_params as $key => $value) {
1449
-            if (is_array($value)) {
1450
-                $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1451
-            } else {
1452
-                $model_ready_query_params[ $key ] = $value;
1453
-            }
1454
-        }
1455
-        return $model_ready_query_params;
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * Explodes the string on commas, and only returns items with $prefix followed by a period.
1461
-     * If no prefix is specified, returns items with no period.
1462
-     *
1463
-     * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' )
1464
-     * @param string       $prefix            "Event" or "foobar"
1465
-     * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1466
-     *                                        we only return strings starting with that and a period; if no prefix was
1467
-     *                                        specified we return all items containing NO periods
1468
-     */
1469
-    public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix)
1470
-    {
1471
-        if (is_string($string_to_explode)) {
1472
-            $exploded_contents = explode(',', $string_to_explode);
1473
-        } elseif (is_array($string_to_explode)) {
1474
-            $exploded_contents = $string_to_explode;
1475
-        } else {
1476
-            $exploded_contents = [];
1477
-        }
1478
-        // if the string was empty, we want an empty array
1479
-        $exploded_contents    = array_filter($exploded_contents);
1480
-        $contents_with_prefix = [];
1481
-        foreach ($exploded_contents as $item) {
1482
-            $item = trim($item);
1483
-            // if no prefix was provided, so we look for items with no "." in them
1484
-            if (! $prefix) {
1485
-                // does this item have a period?
1486
-                if (strpos($item, '.') === false) {
1487
-                    // if not, then its what we're looking for
1488
-                    $contents_with_prefix[] = $item;
1489
-                }
1490
-            } elseif (strpos($item, $prefix . '.') === 0) {
1491
-                // this item has the prefix and a period, grab it
1492
-                $contents_with_prefix[] = substr(
1493
-                    $item,
1494
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1495
-                );
1496
-            } elseif ($item === $prefix) {
1497
-                // this item is JUST the prefix
1498
-                // so let's grab everything after, which is a blank string
1499
-                $contents_with_prefix[] = '';
1500
-            }
1501
-        }
1502
-        return $contents_with_prefix;
1503
-    }
1504
-
1505
-
1506
-    /**
1507
-     * @param string $include_string @see Read:handle_request_get_all
1508
-     * @param string $model_name
1509
-     * @return array of fields for this model. If $model_name is provided, then
1510
-     *                               the fields for that model, with the model's name removed from each.
1511
-     *                               If $include_string was blank or '*' returns an empty array
1512
-     * @throws EE_Error
1513
-     * @throws EE_Error
1514
-     * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1515
-     *                               Deprecated because its return values were really quite confusing- sometimes it
1516
-     *                               returned an empty array (when the include string was blank or '*') or sometimes it
1517
-     *                               returned array('*') (when you provided a model and a model of that kind was
1518
-     *                               found). Parses the $include_string so we fetch all the field names relating to
1519
-     *                               THIS model
1520
-     *                               (ie have NO period in them), or for the provided model (ie start with the model
1521
-     *                               name and then a period).
1522
-     */
1523
-    public function extractIncludesForThisModel($include_string, $model_name = null)
1524
-    {
1525
-        if (is_array($include_string)) {
1526
-            $include_string = implode(',', $include_string);
1527
-        }
1528
-        if ($include_string === '*' || $include_string === '') {
1529
-            return [];
1530
-        }
1531
-        $includes                    = explode(',', $include_string);
1532
-        $extracted_fields_to_include = [];
1533
-        if ($model_name) {
1534
-            foreach ($includes as $field_to_include) {
1535
-                $field_to_include = trim($field_to_include);
1536
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1537
-                    // found the model name at the exact start
1538
-                    $field_sans_model_name         = str_replace($model_name . '.', '', $field_to_include);
1539
-                    $extracted_fields_to_include[] = $field_sans_model_name;
1540
-                } elseif ($field_to_include == $model_name) {
1541
-                    $extracted_fields_to_include[] = '*';
1542
-                }
1543
-            }
1544
-        } else {
1545
-            // look for ones with no period
1546
-            foreach ($includes as $field_to_include) {
1547
-                $field_to_include = trim($field_to_include);
1548
-                if (
1549
-                    strpos($field_to_include, '.') === false
1550
-                    && ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include)
1551
-                ) {
1552
-                    $extracted_fields_to_include[] = $field_to_include;
1553
-                }
1554
-            }
1555
-        }
1556
-        return $extracted_fields_to_include;
1557
-    }
1558
-
1559
-
1560
-    /**
1561
-     * Gets the single item using the model according to the request in the context given, otherwise
1562
-     * returns that it's inaccessible to the current user
1563
-     *
1564
-     * @param EEM_Base        $model
1565
-     * @param WP_REST_Request $request
1566
-     * @param null            $context
1567
-     * @return array
1568
-     * @throws EE_Error
1569
-     * @throws ReflectionException
1570
-     */
1571
-    public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null)
1572
-    {
1573
-        $query_params = [[$model->primary_key_name() => $request->get_param('id')], 'limit' => 1];
1574
-        if ($model instanceof EEM_Soft_Delete_Base) {
1575
-            $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
1576
-        }
1577
-        $restricted_query_params         = $query_params;
1578
-        $restricted_query_params['caps'] = $context;
1579
-        $this->setDebugInfo('model query params', $restricted_query_params);
1580
-        $model_rows = $model->get_all_wpdb_results($restricted_query_params);
1581
-        if (! empty($model_rows)) {
1582
-            return $this->createEntityFromWpdbResult(
1583
-                $model,
1584
-                reset($model_rows),
1585
-                $request
1586
-            );
1587
-        } else {
1588
-            // ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1589
-            $lowercase_model_name = strtolower($model->get_this_model_name());
1590
-            if ($model->exists($query_params)) {
1591
-                // you got shafted- it existed but we didn't want to tell you!
1592
-                throw new RestException(
1593
-                    'rest_user_cannot_' . $context,
1594
-                    sprintf(
1595
-                        esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1596
-                        $context,
1597
-                        $lowercase_model_name,
1598
-                        Capabilities::getMissingPermissionsString(
1599
-                            $model,
1600
-                            $context
1601
-                        )
1602
-                    ),
1603
-                    ['status' => 403]
1604
-                );
1605
-            } else {
1606
-                // it's not you. It just doesn't exist
1607
-                throw new RestException(
1608
-                    sprintf('rest_%s_invalid_id', $lowercase_model_name),
1609
-                    sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
1610
-                    ['status' => 404]
1611
-                );
1612
-            }
1613
-        }
1614
-    }
1615
-
1616
-
1617
-    /**
1618
-     * Checks that if this content requires a password to be read, that it's been provided and is correct.
1619
-     *
1620
-     * @param EEM_Base        $model
1621
-     * @param array           $model_row
1622
-     * @param array           $query_params Adds 'default_where_conditions' => 'minimum'
1623
-     *                                      to ensure we don't confuse trashed with password protected.
1624
-     * @param WP_REST_Request $request
1625
-     * @throws EE_Error
1626
-     * @throws InvalidArgumentException
1627
-     * @throws InvalidDataTypeException
1628
-     * @throws InvalidInterfaceException
1629
-     * @throws RestPasswordRequiredException
1630
-     * @throws RestPasswordIncorrectException
1631
-     * @throws ModelConfigurationException
1632
-     * @throws ReflectionException
1633
-     * @since 4.9.74.p
1634
-     */
1635
-    protected function checkPassword(EEM_Base $model, $model_row, $query_params, WP_REST_Request $request)
1636
-    {
1637
-        $query_params['default_where_conditions'] = 'minimum';
1638
-        // stuff is only "protected" for front-end requests. Elsewhere, you either get full permission to access the object
1639
-        // or you don't.
1640
-        $request_caps = $request->get_param('caps');
1641
-        if (isset($request_caps) && $request_caps !== EEM_Base::caps_read) {
1642
-            return;
1643
-        }
1644
-        // if this entity requires a password, they better give it and it better be right!
1645
-        if (
1646
-            $model->hasPassword()
1647
-            && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== ''
1648
-        ) {
1649
-            if (empty($request['password'])) {
1650
-                throw new RestPasswordRequiredException();
1651
-            }
1652
-            if (
1653
-                ! hash_equals(
1654
-                    $model_row[ $model->getPasswordField()->get_qualified_column() ],
1655
-                    $request['password']
1656
-                )
1657
-            ) {
1658
-                throw new RestPasswordIncorrectException();
1659
-            }
1660
-        } elseif (
1661
-            // wait! maybe this content is password protected
1662
-            $model->restrictedByRelatedModelPassword()
1663
-            && $request->get_param('caps') === EEM_Base::caps_read
1664
-        ) {
1665
-            $password_supplied = $request->get_param('password');
1666
-            if (empty($password_supplied)) {
1667
-                $query_params['exclude_protected'] = true;
1668
-                if (! $model->exists($query_params)) {
1669
-                    throw new RestPasswordRequiredException();
1670
-                }
1671
-            } else {
1672
-                $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied;
1673
-                if (! $model->exists($query_params)) {
1674
-                    throw new RestPasswordIncorrectException();
1675
-                }
1676
-            }
1677
-        }
1678
-    }
54
+	/**
55
+	 * @var CalculatedModelFields
56
+	 */
57
+	protected $fields_calculator;
58
+
59
+
60
+	/**
61
+	 * Read constructor.
62
+	 *
63
+	 * @param CalculatedModelFields $fields_calculator
64
+	 */
65
+	public function __construct(CalculatedModelFields $fields_calculator)
66
+	{
67
+		parent::__construct();
68
+		$this->fields_calculator = $fields_calculator;
69
+	}
70
+
71
+
72
+	/**
73
+	 * Handles requests to get all (or a filtered subset) of entities for a particular model
74
+	 *
75
+	 * @param WP_REST_Request $request
76
+	 * @param string          $version
77
+	 * @param string          $model_name
78
+	 * @return WP_REST_Response|WP_Error
79
+	 * @throws InvalidArgumentException
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidInterfaceException
82
+	 */
83
+	public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name)
84
+	{
85
+		$controller =
86
+			LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
87
+		try {
88
+			$controller->setRequestedVersion($version);
89
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
90
+				return $controller->sendResponse(
91
+					new WP_Error(
92
+						'endpoint_parsing_error',
93
+						sprintf(
94
+							esc_html__(
95
+								'There is no model for endpoint %s. Please contact event espresso support',
96
+								'event_espresso'
97
+							),
98
+							$model_name
99
+						)
100
+					)
101
+				);
102
+			}
103
+			return $controller->sendResponse(
104
+				$controller->getEntitiesFromModel(
105
+					$controller->getModelVersionInfo()->loadModel($model_name),
106
+					$request
107
+				)
108
+			);
109
+		} catch (Exception $e) {
110
+			return $controller->sendResponse($e);
111
+		}
112
+	}
113
+
114
+
115
+	/**
116
+	 * Prepares and returns schema for any OPTIONS request.
117
+	 *
118
+	 * @param string $version    The API endpoint version being used.
119
+	 * @param string $model_name Something like `Event` or `Registration`
120
+	 * @return array
121
+	 * @throws InvalidArgumentException
122
+	 * @throws InvalidDataTypeException
123
+	 * @throws InvalidInterfaceException
124
+	 */
125
+	public static function handleSchemaRequest($version, $model_name)
126
+	{
127
+		$controller =
128
+			LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
129
+		try {
130
+			$controller->setRequestedVersion($version);
131
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
132
+				return [];
133
+			}
134
+			// get the model for this version
135
+			$model        = $controller->getModelVersionInfo()->loadModel($model_name);
136
+			$model_schema = new JsonModelSchema(
137
+				$model,
138
+				LoaderFactory::getLoader()->getShared('EventEspresso\core\libraries\rest_api\CalculatedModelFields')
139
+			);
140
+			return $model_schema->getModelSchemaForRelations(
141
+				$controller->getModelVersionInfo()->relationSettings($model),
142
+				$controller->customizeSchemaForRestResponse(
143
+					$model,
144
+					$model_schema->getModelSchemaForFields(
145
+						$controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model),
146
+						$model_schema->getInitialSchemaStructure()
147
+					)
148
+				)
149
+			);
150
+		} catch (Exception $e) {
151
+			return [];
152
+		}
153
+	}
154
+
155
+
156
+	/**
157
+	 * This loops through each field in the given schema for the model and does the following:
158
+	 * - add any extra fields that are REST API specific and related to existing fields.
159
+	 * - transform default values into the correct format for a REST API response.
160
+	 *
161
+	 * @param EEM_Base $model
162
+	 * @param array    $schema
163
+	 * @return array  The final schema.
164
+	 * @throws EE_Error
165
+	 * @throws EE_Error
166
+	 */
167
+	protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema)
168
+	{
169
+		foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) {
170
+			$schema = $this->translateDefaultsForRestResponse(
171
+				$field_name,
172
+				$field,
173
+				$this->maybeAddExtraFieldsToSchema($field_name, $field, $schema)
174
+			);
175
+		}
176
+		return $schema;
177
+	}
178
+
179
+
180
+	/**
181
+	 * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
182
+	 * response.
183
+	 *
184
+	 * @param                      $field_name
185
+	 * @param EE_Model_Field_Base  $field
186
+	 * @param array                $schema
187
+	 * @return array
188
+	 * @throws RestException  if a default value has a PHP object, which we should never do
189
+	 *                                  (but if we did, let's know about it ASAP, so let the exception bubble up)
190
+	 * @throws EE_Error
191
+	 *
192
+	 */
193
+	protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
194
+	{
195
+		if (isset($schema['properties'][ $field_name ]['default'])) {
196
+			if (is_array($schema['properties'][ $field_name ]['default'])) {
197
+				foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) {
198
+					if ($default_key === 'raw') {
199
+						$schema['properties'][ $field_name ]['default'][ $default_key ] =
200
+							ModelDataTranslator::prepareFieldValueForJson(
201
+								$field,
202
+								$default_value,
203
+								$this->getModelVersionInfo()->requestedVersion()
204
+							);
205
+					}
206
+				}
207
+			} else {
208
+				$schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson(
209
+					$field,
210
+					$schema['properties'][ $field_name ]['default'],
211
+					$this->getModelVersionInfo()->requestedVersion()
212
+				);
213
+			}
214
+		}
215
+		return $schema;
216
+	}
217
+
218
+
219
+	/**
220
+	 * Adds additional fields to the schema
221
+	 * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
222
+	 * needs to be added to the schema.
223
+	 *
224
+	 * @param                      $field_name
225
+	 * @param EE_Model_Field_Base  $field
226
+	 * @param array                $schema
227
+	 * @return array
228
+	 */
229
+	protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
230
+	{
231
+		if ($field instanceof EE_Datetime_Field) {
232
+			$schema['properties'][ $field_name . '_gmt' ] = $field->getSchema();
233
+			// modify the description
234
+			$schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf(
235
+				esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
236
+				wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
237
+			);
238
+		}
239
+		return $schema;
240
+	}
241
+
242
+
243
+	/**
244
+	 * Used to figure out the route from the request when a `WP_REST_Request` object is not available
245
+	 *
246
+	 * @return string
247
+	 */
248
+	protected function getRouteFromRequest()
249
+	{
250
+		if (
251
+			isset($GLOBALS['wp'])
252
+			&& $GLOBALS['wp'] instanceof WP
253
+			&& isset($GLOBALS['wp']->query_vars['rest_route'])
254
+		) {
255
+			return $GLOBALS['wp']->query_vars['rest_route'];
256
+		} else {
257
+			/** @var RequestInterface $request */
258
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
259
+			return $request->serverParamIsSet('PATH_INFO')
260
+				? $request->getServerParam('PATH_INFO')
261
+				: '/';
262
+		}
263
+	}
264
+
265
+
266
+	/**
267
+	 * Gets a single entity related to the model indicated in the path and its id
268
+	 *
269
+	 * @param WP_REST_Request $request
270
+	 * @param string          $version
271
+	 * @param string          $model_name
272
+	 * @return WP_REST_Response|WP_Error
273
+	 * @throws InvalidDataTypeException
274
+	 * @throws InvalidInterfaceException
275
+	 * @throws InvalidArgumentException
276
+	 */
277
+	public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name)
278
+	{
279
+		$controller =
280
+			LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
281
+		try {
282
+			$controller->setRequestedVersion($version);
283
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
284
+				return $controller->sendResponse(
285
+					new WP_Error(
286
+						'endpoint_parsing_error',
287
+						sprintf(
288
+							esc_html__(
289
+								'There is no model for endpoint %s. Please contact event espresso support',
290
+								'event_espresso'
291
+							),
292
+							$model_name
293
+						)
294
+					)
295
+				);
296
+			}
297
+			return $controller->sendResponse(
298
+				$controller->getEntityFromModel(
299
+					$controller->getModelVersionInfo()->loadModel($model_name),
300
+					$request
301
+				)
302
+			);
303
+		} catch (Exception $e) {
304
+			return $controller->sendResponse($e);
305
+		}
306
+	}
307
+
308
+
309
+	/**
310
+	 * Gets all the related entities (or if its a belongs-to relation just the one)
311
+	 * to the item with the given id
312
+	 *
313
+	 * @param WP_REST_Request $request
314
+	 * @param string          $version
315
+	 * @param string          $model_name
316
+	 * @param string          $related_model_name
317
+	 * @return WP_REST_Response|WP_Error
318
+	 * @throws InvalidDataTypeException
319
+	 * @throws InvalidInterfaceException
320
+	 * @throws InvalidArgumentException
321
+	 */
322
+	public static function handleRequestGetRelated(
323
+		WP_REST_Request $request,
324
+		$version,
325
+		$model_name,
326
+		$related_model_name
327
+	) {
328
+		$controller =
329
+			LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
330
+		try {
331
+			$controller->setRequestedVersion($version);
332
+			$main_model = $controller->validateModel($model_name);
333
+			$controller->validateModel($related_model_name);
334
+			return $controller->sendResponse(
335
+				$controller->getEntitiesFromRelation(
336
+					$request->get_param('id'),
337
+					$main_model->related_settings_for($related_model_name),
338
+					$request
339
+				)
340
+			);
341
+		} catch (Exception $e) {
342
+			return $controller->sendResponse($e);
343
+		}
344
+	}
345
+
346
+
347
+	/**
348
+	 * Gets a collection for the given model and filters
349
+	 *
350
+	 * @param EEM_Base        $model
351
+	 * @param WP_REST_Request $request
352
+	 * @return array
353
+	 * @throws EE_Error
354
+	 * @throws InvalidArgumentException
355
+	 * @throws InvalidDataTypeException
356
+	 * @throws InvalidInterfaceException
357
+	 * @throws ReflectionException
358
+	 * @throws RestException
359
+	 */
360
+	public function getEntitiesFromModel($model, $request)
361
+	{
362
+		$query_params = $this->createModelQueryParams($model, $request->get_params());
363
+		if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
364
+			$model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
365
+			throw new RestException(
366
+				sprintf('rest_%s_cannot_list', $model_name_plural),
367
+				sprintf(
368
+					esc_html__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
369
+					$model_name_plural,
370
+					Capabilities::getMissingPermissionsString($model, $query_params['caps'])
371
+				),
372
+				['status' => 403]
373
+			);
374
+		}
375
+		if (! $request->get_header('no_rest_headers')) {
376
+			$this->setHeadersFromQueryParams($model, $query_params);
377
+		}
378
+		/** @type array $results */
379
+		$results      = $model->get_all_wpdb_results($query_params);
380
+		$nice_results = [];
381
+		foreach ($results as $result) {
382
+			$nice_results[] = $this->createEntityFromWpdbResult(
383
+				$model,
384
+				$result,
385
+				$request
386
+			);
387
+		}
388
+		return $nice_results;
389
+	}
390
+
391
+
392
+	/**
393
+	 * Gets the collection for given relation object
394
+	 * The same as Read::get_entities_from_model(), except if the relation
395
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
396
+	 * the join-model-object into the results
397
+	 *
398
+	 * @param array                  $primary_model_query_params  query params for finding the item from which
399
+	 *                                                            relations will be based
400
+	 * @param EE_Model_Relation_Base $relation
401
+	 * @param WP_REST_Request        $request
402
+	 * @return array
403
+	 * @throws EE_Error
404
+	 * @throws InvalidArgumentException
405
+	 * @throws InvalidDataTypeException
406
+	 * @throws InvalidInterfaceException
407
+	 * @throws ReflectionException
408
+	 * @throws RestException
409
+	 * @throws ModelConfigurationException
410
+	 */
411
+	protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request)
412
+	{
413
+		$context       = $this->validateContext($request->get_param('caps'));
414
+		$model         = $relation->get_this_model();
415
+		$related_model = $relation->get_other_model();
416
+		if (! isset($primary_model_query_params[0])) {
417
+			$primary_model_query_params[0] = [];
418
+		}
419
+		// check if they can access the 1st model object
420
+		$primary_model_query_params = [
421
+			0       => $primary_model_query_params[0],
422
+			'limit' => 1,
423
+		];
424
+		if ($model instanceof EEM_Soft_Delete_Base) {
425
+			$primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included(
426
+				$primary_model_query_params
427
+			);
428
+		}
429
+		$restricted_query_params          = $primary_model_query_params;
430
+		$restricted_query_params['caps']  = $context;
431
+		$restricted_query_params['limit'] = 1;
432
+		$this->setDebugInfo('main model query params', $restricted_query_params);
433
+		$this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
434
+		$primary_model_rows = $model->get_all_wpdb_results($restricted_query_params);
435
+		$primary_model_row  = null;
436
+		if (is_array($primary_model_rows)) {
437
+			$primary_model_row = reset($primary_model_rows);
438
+		}
439
+		if (
440
+			! (
441
+				$primary_model_row
442
+				&& Capabilities::currentUserHasPartialAccessTo($related_model, $context)
443
+			)
444
+		) {
445
+			if ($relation instanceof EE_Belongs_To_Relation) {
446
+				$related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
447
+			} else {
448
+				$related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower(
449
+					$related_model->get_this_model_name()
450
+				);
451
+			}
452
+			throw new RestException(
453
+				sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
454
+				sprintf(
455
+					esc_html__(
456
+						'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
457
+						'event_espresso'
458
+					),
459
+					$related_model_name_maybe_plural,
460
+					$relation->get_this_model()->get_this_model_name(),
461
+					implode(
462
+						',',
463
+						array_keys(
464
+							Capabilities::getMissingPermissions($related_model, $context)
465
+						)
466
+					)
467
+				),
468
+				['status' => 403]
469
+			);
470
+		}
471
+
472
+		$this->checkPassword(
473
+			$model,
474
+			$primary_model_row,
475
+			$restricted_query_params,
476
+			$request
477
+		);
478
+		$query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
479
+		foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
480
+			$query_params[0][ $relation->get_this_model()->get_this_model_name()
481
+							  . '.'
482
+							  . $where_condition_key ] = $where_condition_value;
483
+		}
484
+		$query_params['default_where_conditions'] = 'none';
485
+		$query_params['caps']                     = $context;
486
+		if (! $request->get_header('no_rest_headers')) {
487
+			$this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
488
+		}
489
+		/** @type array $results */
490
+		$results      = $relation->get_other_model()->get_all_wpdb_results($query_params);
491
+		$nice_results = [];
492
+		foreach ($results as $result) {
493
+			$nice_result = $this->createEntityFromWpdbResult(
494
+				$relation->get_other_model(),
495
+				$result,
496
+				$request
497
+			);
498
+			if ($relation instanceof EE_HABTM_Relation) {
499
+				// put the unusual stuff (properties from the HABTM relation) first, and make sure
500
+				// if there are conflicts we prefer the properties from the main model
501
+				$join_model_result = $this->createEntityFromWpdbResult(
502
+					$relation->get_join_model(),
503
+					$result,
504
+					$request
505
+				);
506
+				$joined_result     = array_merge($join_model_result, $nice_result);
507
+				// but keep the meta stuff from the main model
508
+				if (isset($nice_result['meta'])) {
509
+					$joined_result['meta'] = $nice_result['meta'];
510
+				}
511
+				$nice_result = $joined_result;
512
+			}
513
+			$nice_results[] = $nice_result;
514
+		}
515
+		if ($relation instanceof EE_Belongs_To_Relation) {
516
+			return array_shift($nice_results);
517
+		} else {
518
+			return $nice_results;
519
+		}
520
+	}
521
+
522
+
523
+	/**
524
+	 * Gets the collection for given relation object
525
+	 * The same as Read::get_entities_from_model(), except if the relation
526
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
527
+	 * the join-model-object into the results
528
+	 *
529
+	 * @param string                 $id the ID of the thing we are fetching related stuff from
530
+	 * @param EE_Model_Relation_Base $relation
531
+	 * @param WP_REST_Request        $request
532
+	 * @return array
533
+	 * @throws EE_Error
534
+	 * @throws ReflectionException
535
+	 */
536
+	public function getEntitiesFromRelation($id, $relation, $request)
537
+	{
538
+		if (! $relation->get_this_model()->has_primary_key_field()) {
539
+			throw new EE_Error(
540
+				sprintf(
541
+					esc_html__(
542
+					// @codingStandardsIgnoreStart
543
+						'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
544
+						// @codingStandardsIgnoreEnd
545
+						'event_espresso'
546
+					),
547
+					$relation->get_this_model()->get_this_model_name()
548
+				)
549
+			);
550
+		}
551
+		// can we edit that main item?
552
+		// if not, show nothing but an error
553
+		// otherwise, please proceed
554
+		return $this->getEntitiesFromRelationUsingModelQueryParams(
555
+			[
556
+				[
557
+					$relation->get_this_model()->primary_key_name() => $id,
558
+				],
559
+			],
560
+			$relation,
561
+			$request
562
+		);
563
+	}
564
+
565
+
566
+	/**
567
+	 * Sets the headers that are based on the model and query params,
568
+	 * like the total records. This should only be called on the original request
569
+	 * from the client, not on subsequent internal
570
+	 *
571
+	 * @param EEM_Base $model
572
+	 * @param array    $query_params
573
+	 * @return void
574
+	 * @throws EE_Error
575
+	 * @throws EE_Error
576
+	 */
577
+	protected function setHeadersFromQueryParams($model, $query_params)
578
+	{
579
+		$this->setDebugInfo('model query params', $query_params);
580
+		$this->setDebugInfo(
581
+			'missing caps',
582
+			Capabilities::getMissingPermissionsString($model, $query_params['caps'])
583
+		);
584
+		// normally the limit to a 2-part array, where the 2nd item is the limit
585
+		if (! isset($query_params['limit'])) {
586
+			$query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
587
+		}
588
+		if (is_array($query_params['limit'])) {
589
+			$limit_parts = $query_params['limit'];
590
+		} else {
591
+			$limit_parts = explode(',', $query_params['limit']);
592
+			if (count($limit_parts) == 1) {
593
+				$limit_parts = [0, $limit_parts[0]];
594
+			}
595
+		}
596
+		// remove the group by and having parts of the query, as those will
597
+		// make the sql query return an array of values, instead of just a single value
598
+		unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
599
+		$count = $model->count($query_params, null, true);
600
+		$pages = $count / $limit_parts[1];
601
+		$this->setResponseHeader('Total', $count, false);
602
+		$this->setResponseHeader('PageSize', $limit_parts[1], false);
603
+		$this->setResponseHeader('TotalPages', ceil($pages), false);
604
+	}
605
+
606
+
607
+	/**
608
+	 * Changes database results into REST API entities
609
+	 *
610
+	 * @param EEM_Base        $model
611
+	 * @param array           $db_row     like results from $wpdb->get_results()
612
+	 * @param WP_REST_Request $rest_request
613
+	 * @param string          $deprecated no longer used
614
+	 * @return array ready for being converted into json for sending to client
615
+	 * @throws EE_Error
616
+	 * @throws RestException
617
+	 * @throws InvalidDataTypeException
618
+	 * @throws InvalidInterfaceException
619
+	 * @throws InvalidArgumentException
620
+	 * @throws ReflectionException
621
+	 */
622
+	public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
623
+	{
624
+		if (! $rest_request instanceof WP_REST_Request) {
625
+			// ok so this was called in the old style, where the 3rd arg was
626
+			// $include, and the 4th arg was $context
627
+			// now setup the request just to avoid fatal errors, although we won't be able
628
+			// to truly make use of it because it's kinda devoid of info
629
+			$rest_request = new WP_REST_Request();
630
+			$rest_request->set_param('include', $rest_request);
631
+			$rest_request->set_param('caps', $deprecated);
632
+		}
633
+		if ($rest_request->get_param('caps') == null) {
634
+			$rest_request->set_param('caps', EEM_Base::caps_read);
635
+		}
636
+		$current_user_full_access_to_entity = $model->currentUserCan(
637
+			EEM_Base::caps_read_admin,
638
+			$model->deduce_fields_n_values_from_cols_n_values($db_row)
639
+		);
640
+		$entity_array                       = $this->createBareEntityFromWpdbResults($model, $db_row);
641
+		$entity_array                       = $this->addExtraFields($model, $db_row, $entity_array);
642
+		$entity_array['_links']             = $this->getEntityLinks($model, $db_row, $entity_array);
643
+		// when it's a regular read request for a model with a password and the password wasn't provided
644
+		// remove the password protected fields
645
+		$has_protected_fields = false;
646
+		try {
647
+			$this->checkPassword(
648
+				$model,
649
+				$db_row,
650
+				$model->alter_query_params_to_restrict_by_ID(
651
+					$model->get_index_primary_key_string(
652
+						$model->deduce_fields_n_values_from_cols_n_values($db_row)
653
+					)
654
+				),
655
+				$rest_request
656
+			);
657
+		} catch (RestPasswordRequiredException $e) {
658
+			if ($model->hasPassword()) {
659
+				// just remove protected fields
660
+				$has_protected_fields = true;
661
+				$entity_array         = Capabilities::filterOutPasswordProtectedFields(
662
+					$entity_array,
663
+					$model,
664
+					$this->getModelVersionInfo()
665
+				);
666
+			} else {
667
+				// that's a problem. None of this should be accessible if no password was provided
668
+				throw $e;
669
+			}
670
+		}
671
+
672
+		$entity_array['_calculated_fields'] =
673
+			$this->getEntityCalculations($model, $db_row, $rest_request, $has_protected_fields);
674
+		$entity_array                       = apply_filters(
675
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
676
+			$entity_array,
677
+			$model,
678
+			$rest_request->get_param('caps'),
679
+			$rest_request,
680
+			$this
681
+		);
682
+		// add an empty protected property for now. If it's still around after we remove everything the request didn't
683
+		// want, we'll populate it then. k?
684
+		$entity_array['_protected'] = [];
685
+		// remove any properties the request didn't want. This way _protected won't bother mentioning them
686
+		$entity_array = $this->includeOnlyRequestedProperties($model, $rest_request, $entity_array);
687
+		$entity_array =
688
+			$this->includeRequestedModels($model, $rest_request, $entity_array, $db_row, $has_protected_fields);
689
+		// if they still wanted the _protected property, add it.
690
+		if (isset($entity_array['_protected'])) {
691
+			$entity_array = $this->addProtectedProperty($model, $entity_array, $has_protected_fields);
692
+		}
693
+		$entity_array = apply_filters(
694
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
695
+			$entity_array,
696
+			$model,
697
+			$rest_request->get_param('caps'),
698
+			$rest_request,
699
+			$this
700
+		);
701
+		if (! $current_user_full_access_to_entity) {
702
+			$result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields(
703
+				$entity_array,
704
+				$model,
705
+				$rest_request->get_param('caps'),
706
+				$this->getModelVersionInfo()
707
+			);
708
+		} else {
709
+			$result_without_inaccessible_fields = $entity_array;
710
+		}
711
+		$this->setDebugInfo(
712
+			'inaccessible fields',
713
+			array_keys(array_diff_key((array) $entity_array, (array) $result_without_inaccessible_fields))
714
+		);
715
+		return apply_filters(
716
+			'FHEE__Read__create_entity_from_wpdb_results__entity_return',
717
+			$result_without_inaccessible_fields,
718
+			$model,
719
+			$rest_request->get_param('caps')
720
+		);
721
+	}
722
+
723
+
724
+	/**
725
+	 * Returns an array describing which fields can be protected, and which actually were removed this request
726
+	 *
727
+	 * @param EEM_Base $model
728
+	 * @param array    $results_so_far
729
+	 * @param bool     $protected
730
+	 * @return array results
731
+	 * @throws EE_Error
732
+	 * @since 4.9.74.p
733
+	 */
734
+	protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected)
735
+	{
736
+		if (! $model->hasPassword() || ! $protected) {
737
+			return $results_so_far;
738
+		}
739
+		$password_field  = $model->getPasswordField();
740
+		$all_protected   = array_merge(
741
+			[$password_field->get_name()],
742
+			$password_field->protectedFields()
743
+		);
744
+		$fields_included = array_keys($results_so_far);
745
+		$fields_included = array_intersect(
746
+			$all_protected,
747
+			$fields_included
748
+		);
749
+		foreach ($fields_included as $field_name) {
750
+			$results_so_far['_protected'][] = $field_name;
751
+		}
752
+		return $results_so_far;
753
+	}
754
+
755
+
756
+	/**
757
+	 * Creates a REST entity array (JSON object we're going to return in the response, but
758
+	 * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
759
+	 * from $wpdb->get_row( $sql, ARRAY_A)
760
+	 *
761
+	 * @param EEM_Base $model
762
+	 * @param array    $db_row
763
+	 * @return array entity mostly ready for converting to JSON and sending in the response
764
+	 * @throws EE_Error
765
+	 * @throws ReflectionException
766
+	 * @throws RestException
767
+	 */
768
+	protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row)
769
+	{
770
+		$result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
771
+		$result = array_intersect_key(
772
+			$result,
773
+			$this->getModelVersionInfo()->fieldsOnModelInThisVersion($model)
774
+		);
775
+		// if this is a CPT, we need to set the global $post to it,
776
+		// otherwise shortcodes etc won't work properly while rendering it
777
+		if ($model instanceof EEM_CPT_Base) {
778
+			$do_chevy_shuffle = true;
779
+		} else {
780
+			$do_chevy_shuffle = false;
781
+		}
782
+		if ($do_chevy_shuffle) {
783
+			global $post;
784
+			$old_post = $post;
785
+			$post     = get_post($result[ $model->primary_key_name() ]);
786
+			if (! $post instanceof WP_Post) {
787
+				// well that's weird, because $result is what we JUST fetched from the database
788
+				throw new RestException(
789
+					'error_fetching_post_from_database_results',
790
+					esc_html__(
791
+						'An item was retrieved from the database but it\'s not a WP_Post like it should be.',
792
+						'event_espresso'
793
+					)
794
+				);
795
+			}
796
+			$model_object_classname          = 'EE_' . $model->get_this_model_name();
797
+			$post->{$model_object_classname} = EE_Registry::instance()->load_class(
798
+				$model_object_classname,
799
+				$result,
800
+				false,
801
+				false
802
+			);
803
+		}
804
+		foreach ($result as $field_name => $field_value) {
805
+			$field_obj = $model->field_settings_for($field_name);
806
+			if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
807
+				unset($result[ $field_name ]);
808
+			} elseif (
809
+				$this->isSubclassOfOne(
810
+					$field_obj,
811
+					$this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
812
+				)
813
+			) {
814
+				$result[ $field_name ] = [
815
+					'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
816
+					'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
817
+				];
818
+			} elseif (
819
+				$this->isSubclassOfOne(
820
+					$field_obj,
821
+					$this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
822
+				)
823
+			) {
824
+				$result[ $field_name ] = [
825
+					'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
826
+					'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
827
+				];
828
+			} elseif ($field_obj instanceof EE_Datetime_Field) {
829
+				$field_value = $field_obj->prepare_for_set_from_db($field_value);
830
+				// if the value is null, but we're not supposed to permit null, then set to the field's default
831
+				if (is_null($field_value)) {
832
+					$field_value = $field_obj->getDefaultDateTimeObj();
833
+				}
834
+				if (is_null($field_value)) {
835
+					$gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson(
836
+						$field_obj,
837
+						$field_value,
838
+						$this->getModelVersionInfo()->requestedVersion()
839
+					);
840
+				} else {
841
+					$timezone = $field_value->getTimezone();
842
+					EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC'));
843
+					$gmt_date = ModelDataTranslator::prepareFieldValuesForJson(
844
+						$field_obj,
845
+						$field_value,
846
+						$this->getModelVersionInfo()->requestedVersion()
847
+					);
848
+					EEH_DTT_Helper::setTimezone($field_value, $timezone);
849
+					$local_date = ModelDataTranslator::prepareFieldValuesForJson(
850
+						$field_obj,
851
+						$field_value,
852
+						$this->getModelVersionInfo()->requestedVersion()
853
+					);
854
+				}
855
+				$result[ $field_name . '_gmt' ] = $gmt_date;
856
+				$result[ $field_name ]          = $local_date;
857
+			} else {
858
+				$result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
859
+			}
860
+		}
861
+		if ($do_chevy_shuffle) {
862
+			$post = $old_post;
863
+		}
864
+		return $result;
865
+	}
866
+
867
+
868
+	/**
869
+	 * Takes a value all the way from the DB representation, to the model object's representation, to the
870
+	 * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB
871
+	 * representation using $field_obj->prepare_for_set_from_db())
872
+	 *
873
+	 * @param EE_Model_Field_Base $field_obj
874
+	 * @param mixed               $value  as it's stored on a model object
875
+	 * @param string              $format valid values are 'normal' (default), 'pretty', 'datetime_obj'
876
+	 * @return array
877
+	 * @throws RestException if $value contains a PHP object
878
+	 * @throws EE_Error
879
+	 */
880
+	protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal')
881
+	{
882
+		$value = $field_obj->prepare_for_set_from_db($value);
883
+		switch ($format) {
884
+			case 'pretty':
885
+				$value = $field_obj->prepare_for_pretty_echoing($value);
886
+				break;
887
+			case 'normal':
888
+			default:
889
+				$value = $field_obj->prepare_for_get($value);
890
+				break;
891
+		}
892
+		return ModelDataTranslator::prepareFieldValuesForJson(
893
+			$field_obj,
894
+			$value,
895
+			$this->getModelVersionInfo()->requestedVersion()
896
+		);
897
+	}
898
+
899
+
900
+	/**
901
+	 * Adds a few extra fields to the entity response
902
+	 *
903
+	 * @param EEM_Base $model
904
+	 * @param array    $db_row
905
+	 * @param array    $entity_array
906
+	 * @return array modified entity
907
+	 * @throws EE_Error
908
+	 * @throws EE_Error
909
+	 */
910
+	protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
911
+	{
912
+		if ($model instanceof EEM_CPT_Base) {
913
+			$entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]);
914
+		}
915
+		return $entity_array;
916
+	}
917
+
918
+
919
+	/**
920
+	 * Gets links we want to add to the response
921
+	 *
922
+	 * @param EEM_Base        $model
923
+	 * @param array           $db_row
924
+	 * @param array           $entity_array
925
+	 * @return array the _links item in the entity
926
+	 * @throws EE_Error
927
+	 * @throws EE_Error
928
+	 * @global WP_REST_Server $wp_rest_server
929
+	 */
930
+	protected function getEntityLinks($model, $db_row, $entity_array)
931
+	{
932
+		// add basic links
933
+		$links = [];
934
+		if ($model->has_primary_key_field()) {
935
+			$links['self'] = [
936
+				[
937
+					'href' => $this->getVersionedLinkTo(
938
+						EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
939
+						. '/'
940
+						. $entity_array[ $model->primary_key_name() ]
941
+					),
942
+				],
943
+			];
944
+		}
945
+		$links['collection'] = [
946
+			[
947
+				'href' => $this->getVersionedLinkTo(
948
+					EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
949
+				),
950
+			],
951
+		];
952
+		// add links to related models
953
+		if ($model->has_primary_key_field()) {
954
+			foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
955
+				$related_model_part                                                      =
956
+					Read::getRelatedEntityName($relation_name, $relation_obj);
957
+				$links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [
958
+					[
959
+						'href'   => $this->getVersionedLinkTo(
960
+							EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
961
+							. '/'
962
+							. $entity_array[ $model->primary_key_name() ]
963
+							. '/'
964
+							. $related_model_part
965
+						),
966
+						'single' => $relation_obj instanceof EE_Belongs_To_Relation,
967
+					],
968
+				];
969
+			}
970
+		}
971
+		return $links;
972
+	}
973
+
974
+
975
+	/**
976
+	 * Adds the included models indicated in the request to the entity provided
977
+	 *
978
+	 * @param EEM_Base        $model
979
+	 * @param WP_REST_Request $rest_request
980
+	 * @param array           $entity_array
981
+	 * @param array           $db_row
982
+	 * @param boolean         $included_items_protected if the original item is password protected, don't include any
983
+	 *                                                  related models.
984
+	 * @return array the modified entity
985
+	 * @throws EE_Error
986
+	 * @throws ReflectionException
987
+	 */
988
+	protected function includeRequestedModels(
989
+		EEM_Base $model,
990
+		WP_REST_Request $rest_request,
991
+		$entity_array,
992
+		$db_row = [],
993
+		$included_items_protected = false
994
+	) {
995
+		// if $db_row not included, hope the entity array has what we need
996
+		if (! $db_row) {
997
+			$db_row = $entity_array;
998
+		}
999
+		$relation_settings = $this->getModelVersionInfo()->relationSettings($model);
1000
+		foreach ($relation_settings as $relation_name => $relation_obj) {
1001
+			$related_fields_to_include   = $this->explodeAndGetItemsPrefixedWith(
1002
+				$rest_request->get_param('include'),
1003
+				$relation_name
1004
+			);
1005
+			$related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith(
1006
+				$rest_request->get_param('calculate'),
1007
+				$relation_name
1008
+			);
1009
+			// did they specify they wanted to include a related model, or
1010
+			// specific fields from a related model?
1011
+			// or did they specify to calculate a field from a related model?
1012
+			if ($related_fields_to_include || $related_fields_to_calculate) {
1013
+				// if so, we should include at least some part of the related model
1014
+				$pretend_related_request = new WP_REST_Request();
1015
+				$pretend_related_request->set_query_params(
1016
+					[
1017
+						'caps'      => $rest_request->get_param('caps'),
1018
+						'include'   => $related_fields_to_include,
1019
+						'calculate' => $related_fields_to_calculate,
1020
+						'password'  => $rest_request->get_param('password'),
1021
+					]
1022
+				);
1023
+				$pretend_related_request->add_header('no_rest_headers', true);
1024
+				$primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
1025
+					$model->get_index_primary_key_string(
1026
+						$model->deduce_fields_n_values_from_cols_n_values($db_row)
1027
+					)
1028
+				);
1029
+				if (! $included_items_protected) {
1030
+					try {
1031
+						$related_results = $this->getEntitiesFromRelationUsingModelQueryParams(
1032
+							$primary_model_query_params,
1033
+							$relation_obj,
1034
+							$pretend_related_request
1035
+						);
1036
+					} catch (RestException $e) {
1037
+						$related_results = null;
1038
+					}
1039
+				} else {
1040
+					// they're protected, hide them.
1041
+					$related_results              = null;
1042
+					$entity_array['_protected'][] = Read::getRelatedEntityName($relation_name, $relation_obj);
1043
+				}
1044
+				if ($related_results instanceof WP_Error || $related_results === null) {
1045
+					$related_results =
1046
+						$relation_obj instanceof EE_Belongs_To_Relation
1047
+							? null
1048
+							: [];
1049
+				}
1050
+				$entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results;
1051
+			}
1052
+		}
1053
+		return $entity_array;
1054
+	}
1055
+
1056
+
1057
+	/**
1058
+	 * If the user has requested only specific properties (including meta properties like _links or _protected)
1059
+	 * remove everything else.
1060
+	 *
1061
+	 * @param EEM_Base        $model
1062
+	 * @param WP_REST_Request $rest_request
1063
+	 * @param                 $entity_array
1064
+	 * @return array
1065
+	 * @throws EE_Error
1066
+	 * @since 4.9.74.p
1067
+	 */
1068
+	protected function includeOnlyRequestedProperties(
1069
+		EEM_Base $model,
1070
+		WP_REST_Request $rest_request,
1071
+		$entity_array
1072
+	) {
1073
+
1074
+		$includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
1075
+		$includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
1076
+		// if they passed in * or didn't specify any includes, return everything
1077
+		if (
1078
+			! in_array('*', $includes_for_this_model)
1079
+			&& ! empty($includes_for_this_model)
1080
+		) {
1081
+			if ($model->has_primary_key_field()) {
1082
+				// always include the primary key. ya just gotta know that at least
1083
+				$includes_for_this_model[] = $model->primary_key_name();
1084
+			}
1085
+			if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) {
1086
+				$includes_for_this_model[] = '_calculated_fields';
1087
+			}
1088
+			$entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
1089
+		}
1090
+		return $entity_array;
1091
+	}
1092
+
1093
+
1094
+	/**
1095
+	 * Returns a new array with all the names of models removed. Eg
1096
+	 * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
1097
+	 *
1098
+	 * @param array $arr
1099
+	 * @return array
1100
+	 */
1101
+	private function removeModelNamesFromArray($arr)
1102
+	{
1103
+		return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models));
1104
+	}
1105
+
1106
+
1107
+	/**
1108
+	 * Gets the calculated fields for the response
1109
+	 *
1110
+	 * @param EEM_Base        $model
1111
+	 * @param array           $wpdb_row
1112
+	 * @param WP_REST_Request $rest_request
1113
+	 * @param boolean         $row_is_protected whether this row is password protected or not
1114
+	 * @return stdClass the _calculations item in the entity
1115
+	 * @throws RestException if a default value has a PHP object, which should never do (and if we
1116
+	 * @throws EE_Error
1117
+	 *                                          did, let's know about it ASAP, so let the exception bubble up)
1118
+	 */
1119
+	protected function getEntityCalculations($model, $wpdb_row, $rest_request, $row_is_protected = false)
1120
+	{
1121
+		$calculated_fields = $this->explodeAndGetItemsPrefixedWith(
1122
+			$rest_request->get_param('calculate'),
1123
+			''
1124
+		);
1125
+		// note: setting calculate=* doesn't do anything
1126
+		$calculated_fields_to_return = new stdClass();
1127
+		$protected_fields            = [];
1128
+		foreach ($calculated_fields as $field_to_calculate) {
1129
+			try {
1130
+				// it's password protected, so they shouldn't be able to read this. Remove the value
1131
+				$schema = $this->fields_calculator->getJsonSchemaForModel($model);
1132
+				if (
1133
+					$row_is_protected
1134
+					&& isset($schema['properties'][ $field_to_calculate ]['protected'])
1135
+					&& $schema['properties'][ $field_to_calculate ]['protected']
1136
+				) {
1137
+					$calculated_value   = null;
1138
+					$protected_fields[] = $field_to_calculate;
1139
+					if ($schema['properties'][ $field_to_calculate ]['type']) {
1140
+						switch ($schema['properties'][ $field_to_calculate ]['type']) {
1141
+							case 'boolean':
1142
+								$calculated_value = false;
1143
+								break;
1144
+							case 'integer':
1145
+								$calculated_value = 0;
1146
+								break;
1147
+							case 'string':
1148
+								$calculated_value = '';
1149
+								break;
1150
+							case 'array':
1151
+								$calculated_value = [];
1152
+								break;
1153
+							case 'object':
1154
+								$calculated_value = new stdClass();
1155
+								break;
1156
+						}
1157
+					}
1158
+				} else {
1159
+					$calculated_value = ModelDataTranslator::prepareFieldValueForJson(
1160
+						null,
1161
+						$this->fields_calculator->retrieveCalculatedFieldValue(
1162
+							$model,
1163
+							$field_to_calculate,
1164
+							$wpdb_row,
1165
+							$rest_request,
1166
+							$this
1167
+						),
1168
+						$this->getModelVersionInfo()->requestedVersion()
1169
+					);
1170
+				}
1171
+				$calculated_fields_to_return->{$field_to_calculate} = $calculated_value;
1172
+			} catch (RestException $e) {
1173
+				// if we don't have permission to read it, just leave it out. but let devs know about the problem
1174
+				$this->setResponseHeader(
1175
+					'Notices-Field-Calculation-Errors['
1176
+					. $e->getStringCode()
1177
+					. ']['
1178
+					. $model->get_this_model_name()
1179
+					. ']['
1180
+					. $field_to_calculate
1181
+					. ']',
1182
+					$e->getMessage(),
1183
+					true
1184
+				);
1185
+			}
1186
+		}
1187
+		$calculated_fields_to_return->_protected = $protected_fields;
1188
+		return $calculated_fields_to_return;
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * Gets the full URL to the resource, taking the requested version into account
1194
+	 *
1195
+	 * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
1196
+	 * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
1197
+	 * @throws EE_Error
1198
+	 * @throws EE_Error
1199
+	 */
1200
+	public function getVersionedLinkTo($link_part_after_version_and_slash)
1201
+	{
1202
+		return rest_url(
1203
+			EED_Core_Rest_Api::get_versioned_route_to(
1204
+				$link_part_after_version_and_slash,
1205
+				$this->getModelVersionInfo()->requestedVersion()
1206
+			)
1207
+		);
1208
+	}
1209
+
1210
+
1211
+	/**
1212
+	 * Gets the correct lowercase name for the relation in the API according
1213
+	 * to the relation's type
1214
+	 *
1215
+	 * @param string                 $relation_name
1216
+	 * @param EE_Model_Relation_Base $relation_obj
1217
+	 * @return string
1218
+	 */
1219
+	public static function getRelatedEntityName($relation_name, $relation_obj)
1220
+	{
1221
+		if ($relation_obj instanceof EE_Belongs_To_Relation) {
1222
+			return strtolower($relation_name);
1223
+		} else {
1224
+			return EEH_Inflector::pluralize_and_lower($relation_name);
1225
+		}
1226
+	}
1227
+
1228
+
1229
+	/**
1230
+	 * Gets the one model object with the specified id for the specified model
1231
+	 *
1232
+	 * @param EEM_Base        $model
1233
+	 * @param WP_REST_Request $request
1234
+	 * @return array
1235
+	 * @throws EE_Error
1236
+	 * @throws EE_Error
1237
+	 * @throws ReflectionException
1238
+	 */
1239
+	public function getEntityFromModel($model, $request)
1240
+	{
1241
+		$context = $this->validateContext($request->get_param('caps'));
1242
+		return $this->getOneOrReportPermissionError($model, $request, $context);
1243
+	}
1244
+
1245
+
1246
+	/**
1247
+	 * If a context is provided which isn't valid, maybe it was added in a future
1248
+	 * version so just treat it as a default read
1249
+	 *
1250
+	 * @param string $context
1251
+	 * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
1252
+	 */
1253
+	public function validateContext($context)
1254
+	{
1255
+		if (! $context) {
1256
+			$context = EEM_Base::caps_read;
1257
+		}
1258
+		$valid_contexts = EEM_Base::valid_cap_contexts();
1259
+		if (in_array($context, $valid_contexts)) {
1260
+			return $context;
1261
+		} else {
1262
+			return EEM_Base::caps_read;
1263
+		}
1264
+	}
1265
+
1266
+
1267
+	/**
1268
+	 * Verifies the passed in value is an allowable default where conditions value.
1269
+	 *
1270
+	 * @param $default_query_params
1271
+	 * @return string
1272
+	 */
1273
+	public function validateDefaultQueryParams($default_query_params)
1274
+	{
1275
+		$valid_default_where_conditions_for_api_calls = [
1276
+			EEM_Base::default_where_conditions_all,
1277
+			EEM_Base::default_where_conditions_minimum_all,
1278
+			EEM_Base::default_where_conditions_minimum_others,
1279
+		];
1280
+		if (! $default_query_params) {
1281
+			$default_query_params = EEM_Base::default_where_conditions_all;
1282
+		}
1283
+		if (
1284
+			in_array(
1285
+				$default_query_params,
1286
+				$valid_default_where_conditions_for_api_calls,
1287
+				true
1288
+			)
1289
+		) {
1290
+			return $default_query_params;
1291
+		}
1292
+		return EEM_Base::default_where_conditions_all;
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * Translates API filter get parameter into model query params @see
1298
+	 * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions.
1299
+	 * Note: right now the query parameter keys for fields (and related fields) can be left as-is, but it's quite
1300
+	 * possible this will change someday. Also, this method's contents might be candidate for moving to
1301
+	 * Model_Data_Translator
1302
+	 *
1303
+	 * @param EEM_Base $model
1304
+	 * @param array    $query_params
1305
+	 * @return array model query params (@see
1306
+	 *               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions)
1307
+	 *               or FALSE to indicate that absolutely no results should be returned
1308
+	 * @throws EE_Error
1309
+	 * @throws RestException
1310
+	 */
1311
+	public function createModelQueryParams($model, $query_params)
1312
+	{
1313
+		$model_query_params = [];
1314
+		if (isset($query_params['where'])) {
1315
+			$model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1316
+				$query_params['where'],
1317
+				$model,
1318
+				$this->getModelVersionInfo()->requestedVersion()
1319
+			);
1320
+		}
1321
+		if (isset($query_params['order_by'])) {
1322
+			$order_by = $query_params['order_by'];
1323
+		} elseif (isset($query_params['orderby'])) {
1324
+			$order_by = $query_params['orderby'];
1325
+		} else {
1326
+			$order_by = null;
1327
+		}
1328
+		if ($order_by !== null) {
1329
+			if (is_array($order_by)) {
1330
+				$order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by);
1331
+			} else {
1332
+				// it's a single item
1333
+				$order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by);
1334
+			}
1335
+			$model_query_params['order_by'] = $order_by;
1336
+		}
1337
+		if (isset($query_params['group_by'])) {
1338
+			$group_by = $query_params['group_by'];
1339
+		} elseif (isset($query_params['groupby'])) {
1340
+			$group_by = $query_params['groupby'];
1341
+		} else {
1342
+			$group_by = array_keys($model->get_combined_primary_key_fields());
1343
+		}
1344
+		// make sure they're all real names
1345
+		if (is_array($group_by)) {
1346
+			$group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by);
1347
+		}
1348
+		if ($group_by !== null) {
1349
+			$model_query_params['group_by'] = $group_by;
1350
+		}
1351
+		if (isset($query_params['having'])) {
1352
+			$model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1353
+				$query_params['having'],
1354
+				$model,
1355
+				$this->getModelVersionInfo()->requestedVersion()
1356
+			);
1357
+		}
1358
+		if (isset($query_params['order'])) {
1359
+			$model_query_params['order'] = $query_params['order'];
1360
+		}
1361
+		if (isset($query_params['mine'])) {
1362
+			$model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1363
+		}
1364
+		if (isset($query_params['limit'])) {
1365
+			// limit should be either a string like '23' or '23,43', or an array with two items in it
1366
+			if (! is_array($query_params['limit'])) {
1367
+				$limit_array = explode(',', (string) $query_params['limit']);
1368
+			} else {
1369
+				$limit_array = $query_params['limit'];
1370
+			}
1371
+			$sanitized_limit = [];
1372
+			foreach ($limit_array as $limit_part) {
1373
+				if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1374
+					throw new EE_Error(
1375
+						sprintf(
1376
+							esc_html__(
1377
+							// @codingStandardsIgnoreStart
1378
+								'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.',
1379
+								// @codingStandardsIgnoreEnd
1380
+								'event_espresso'
1381
+							),
1382
+							wp_json_encode($query_params['limit'])
1383
+						)
1384
+					);
1385
+				}
1386
+				$sanitized_limit[] = (int) $limit_part;
1387
+			}
1388
+			$model_query_params['limit'] = implode(',', $sanitized_limit);
1389
+		} else {
1390
+			$model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
1391
+		}
1392
+		if (isset($query_params['caps'])) {
1393
+			$model_query_params['caps'] = $this->validateContext($query_params['caps']);
1394
+		} else {
1395
+			$model_query_params['caps'] = EEM_Base::caps_read;
1396
+		}
1397
+		if (isset($query_params['default_where_conditions'])) {
1398
+			$model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams(
1399
+				$query_params['default_where_conditions']
1400
+			);
1401
+		}
1402
+		// if this is a model protected by a password on another model, exclude the password protected
1403
+		// entities by default. But if they passed in a password, try to show them all. If the password is wrong,
1404
+		// though, they'll get an error (see Read::createEntityFromWpdbResult() which calls Read::checkPassword)
1405
+		if (
1406
+			! $model->hasPassword()
1407
+			&& $model->restrictedByRelatedModelPassword()
1408
+			&& $model_query_params['caps'] === EEM_Base::caps_read
1409
+		) {
1410
+			if (empty($query_params['password'])) {
1411
+				$model_query_params['exclude_protected'] = true;
1412
+			}
1413
+		}
1414
+
1415
+		return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_params, $model);
1416
+	}
1417
+
1418
+
1419
+	/**
1420
+	 * Changes the REST-style query params for use in the models
1421
+	 *
1422
+	 * @param EEM_Base $model
1423
+	 * @param array    $query_params sub-array from @see EEM_Base::get_all()
1424
+	 * @return array
1425
+	 * @deprecated
1426
+	 */
1427
+	public function prepareRestQueryParamsKeyForModels($model, $query_params)
1428
+	{
1429
+		$model_ready_query_params = [];
1430
+		foreach ($query_params as $key => $value) {
1431
+			$model_ready_query_params[ $key ] = is_array($value)
1432
+				? $this->prepareRestQueryParamsKeyForModels($model, $value)
1433
+				: $value;
1434
+		}
1435
+		return $model_ready_query_params;
1436
+	}
1437
+
1438
+
1439
+	/**
1440
+	 * @param $model
1441
+	 * @param $query_params
1442
+	 * @return array
1443
+	 * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson()
1444
+	 */
1445
+	public function prepareRestQueryParamsValuesForModels($model, $query_params)
1446
+	{
1447
+		$model_ready_query_params = [];
1448
+		foreach ($query_params as $key => $value) {
1449
+			if (is_array($value)) {
1450
+				$model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1451
+			} else {
1452
+				$model_ready_query_params[ $key ] = $value;
1453
+			}
1454
+		}
1455
+		return $model_ready_query_params;
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * Explodes the string on commas, and only returns items with $prefix followed by a period.
1461
+	 * If no prefix is specified, returns items with no period.
1462
+	 *
1463
+	 * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' )
1464
+	 * @param string       $prefix            "Event" or "foobar"
1465
+	 * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1466
+	 *                                        we only return strings starting with that and a period; if no prefix was
1467
+	 *                                        specified we return all items containing NO periods
1468
+	 */
1469
+	public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix)
1470
+	{
1471
+		if (is_string($string_to_explode)) {
1472
+			$exploded_contents = explode(',', $string_to_explode);
1473
+		} elseif (is_array($string_to_explode)) {
1474
+			$exploded_contents = $string_to_explode;
1475
+		} else {
1476
+			$exploded_contents = [];
1477
+		}
1478
+		// if the string was empty, we want an empty array
1479
+		$exploded_contents    = array_filter($exploded_contents);
1480
+		$contents_with_prefix = [];
1481
+		foreach ($exploded_contents as $item) {
1482
+			$item = trim($item);
1483
+			// if no prefix was provided, so we look for items with no "." in them
1484
+			if (! $prefix) {
1485
+				// does this item have a period?
1486
+				if (strpos($item, '.') === false) {
1487
+					// if not, then its what we're looking for
1488
+					$contents_with_prefix[] = $item;
1489
+				}
1490
+			} elseif (strpos($item, $prefix . '.') === 0) {
1491
+				// this item has the prefix and a period, grab it
1492
+				$contents_with_prefix[] = substr(
1493
+					$item,
1494
+					strpos($item, $prefix . '.') + strlen($prefix . '.')
1495
+				);
1496
+			} elseif ($item === $prefix) {
1497
+				// this item is JUST the prefix
1498
+				// so let's grab everything after, which is a blank string
1499
+				$contents_with_prefix[] = '';
1500
+			}
1501
+		}
1502
+		return $contents_with_prefix;
1503
+	}
1504
+
1505
+
1506
+	/**
1507
+	 * @param string $include_string @see Read:handle_request_get_all
1508
+	 * @param string $model_name
1509
+	 * @return array of fields for this model. If $model_name is provided, then
1510
+	 *                               the fields for that model, with the model's name removed from each.
1511
+	 *                               If $include_string was blank or '*' returns an empty array
1512
+	 * @throws EE_Error
1513
+	 * @throws EE_Error
1514
+	 * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1515
+	 *                               Deprecated because its return values were really quite confusing- sometimes it
1516
+	 *                               returned an empty array (when the include string was blank or '*') or sometimes it
1517
+	 *                               returned array('*') (when you provided a model and a model of that kind was
1518
+	 *                               found). Parses the $include_string so we fetch all the field names relating to
1519
+	 *                               THIS model
1520
+	 *                               (ie have NO period in them), or for the provided model (ie start with the model
1521
+	 *                               name and then a period).
1522
+	 */
1523
+	public function extractIncludesForThisModel($include_string, $model_name = null)
1524
+	{
1525
+		if (is_array($include_string)) {
1526
+			$include_string = implode(',', $include_string);
1527
+		}
1528
+		if ($include_string === '*' || $include_string === '') {
1529
+			return [];
1530
+		}
1531
+		$includes                    = explode(',', $include_string);
1532
+		$extracted_fields_to_include = [];
1533
+		if ($model_name) {
1534
+			foreach ($includes as $field_to_include) {
1535
+				$field_to_include = trim($field_to_include);
1536
+				if (strpos($field_to_include, $model_name . '.') === 0) {
1537
+					// found the model name at the exact start
1538
+					$field_sans_model_name         = str_replace($model_name . '.', '', $field_to_include);
1539
+					$extracted_fields_to_include[] = $field_sans_model_name;
1540
+				} elseif ($field_to_include == $model_name) {
1541
+					$extracted_fields_to_include[] = '*';
1542
+				}
1543
+			}
1544
+		} else {
1545
+			// look for ones with no period
1546
+			foreach ($includes as $field_to_include) {
1547
+				$field_to_include = trim($field_to_include);
1548
+				if (
1549
+					strpos($field_to_include, '.') === false
1550
+					&& ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include)
1551
+				) {
1552
+					$extracted_fields_to_include[] = $field_to_include;
1553
+				}
1554
+			}
1555
+		}
1556
+		return $extracted_fields_to_include;
1557
+	}
1558
+
1559
+
1560
+	/**
1561
+	 * Gets the single item using the model according to the request in the context given, otherwise
1562
+	 * returns that it's inaccessible to the current user
1563
+	 *
1564
+	 * @param EEM_Base        $model
1565
+	 * @param WP_REST_Request $request
1566
+	 * @param null            $context
1567
+	 * @return array
1568
+	 * @throws EE_Error
1569
+	 * @throws ReflectionException
1570
+	 */
1571
+	public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null)
1572
+	{
1573
+		$query_params = [[$model->primary_key_name() => $request->get_param('id')], 'limit' => 1];
1574
+		if ($model instanceof EEM_Soft_Delete_Base) {
1575
+			$query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
1576
+		}
1577
+		$restricted_query_params         = $query_params;
1578
+		$restricted_query_params['caps'] = $context;
1579
+		$this->setDebugInfo('model query params', $restricted_query_params);
1580
+		$model_rows = $model->get_all_wpdb_results($restricted_query_params);
1581
+		if (! empty($model_rows)) {
1582
+			return $this->createEntityFromWpdbResult(
1583
+				$model,
1584
+				reset($model_rows),
1585
+				$request
1586
+			);
1587
+		} else {
1588
+			// ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1589
+			$lowercase_model_name = strtolower($model->get_this_model_name());
1590
+			if ($model->exists($query_params)) {
1591
+				// you got shafted- it existed but we didn't want to tell you!
1592
+				throw new RestException(
1593
+					'rest_user_cannot_' . $context,
1594
+					sprintf(
1595
+						esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1596
+						$context,
1597
+						$lowercase_model_name,
1598
+						Capabilities::getMissingPermissionsString(
1599
+							$model,
1600
+							$context
1601
+						)
1602
+					),
1603
+					['status' => 403]
1604
+				);
1605
+			} else {
1606
+				// it's not you. It just doesn't exist
1607
+				throw new RestException(
1608
+					sprintf('rest_%s_invalid_id', $lowercase_model_name),
1609
+					sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
1610
+					['status' => 404]
1611
+				);
1612
+			}
1613
+		}
1614
+	}
1615
+
1616
+
1617
+	/**
1618
+	 * Checks that if this content requires a password to be read, that it's been provided and is correct.
1619
+	 *
1620
+	 * @param EEM_Base        $model
1621
+	 * @param array           $model_row
1622
+	 * @param array           $query_params Adds 'default_where_conditions' => 'minimum'
1623
+	 *                                      to ensure we don't confuse trashed with password protected.
1624
+	 * @param WP_REST_Request $request
1625
+	 * @throws EE_Error
1626
+	 * @throws InvalidArgumentException
1627
+	 * @throws InvalidDataTypeException
1628
+	 * @throws InvalidInterfaceException
1629
+	 * @throws RestPasswordRequiredException
1630
+	 * @throws RestPasswordIncorrectException
1631
+	 * @throws ModelConfigurationException
1632
+	 * @throws ReflectionException
1633
+	 * @since 4.9.74.p
1634
+	 */
1635
+	protected function checkPassword(EEM_Base $model, $model_row, $query_params, WP_REST_Request $request)
1636
+	{
1637
+		$query_params['default_where_conditions'] = 'minimum';
1638
+		// stuff is only "protected" for front-end requests. Elsewhere, you either get full permission to access the object
1639
+		// or you don't.
1640
+		$request_caps = $request->get_param('caps');
1641
+		if (isset($request_caps) && $request_caps !== EEM_Base::caps_read) {
1642
+			return;
1643
+		}
1644
+		// if this entity requires a password, they better give it and it better be right!
1645
+		if (
1646
+			$model->hasPassword()
1647
+			&& $model_row[ $model->getPasswordField()->get_qualified_column() ] !== ''
1648
+		) {
1649
+			if (empty($request['password'])) {
1650
+				throw new RestPasswordRequiredException();
1651
+			}
1652
+			if (
1653
+				! hash_equals(
1654
+					$model_row[ $model->getPasswordField()->get_qualified_column() ],
1655
+					$request['password']
1656
+				)
1657
+			) {
1658
+				throw new RestPasswordIncorrectException();
1659
+			}
1660
+		} elseif (
1661
+			// wait! maybe this content is password protected
1662
+			$model->restrictedByRelatedModelPassword()
1663
+			&& $request->get_param('caps') === EEM_Base::caps_read
1664
+		) {
1665
+			$password_supplied = $request->get_param('password');
1666
+			if (empty($password_supplied)) {
1667
+				$query_params['exclude_protected'] = true;
1668
+				if (! $model->exists($query_params)) {
1669
+					throw new RestPasswordRequiredException();
1670
+				}
1671
+			} else {
1672
+				$query_params[0][ $model->modelChainAndPassword() ] = $password_supplied;
1673
+				if (! $model->exists($query_params)) {
1674
+					throw new RestPasswordIncorrectException();
1675
+				}
1676
+			}
1677
+		}
1678
+	}
1679 1679
 }
Please login to merge, or discard this patch.
Spacing   +63 added lines, -63 removed lines patch added patch discarded remove patch
@@ -86,7 +86,7 @@  discard block
 block discarded – undo
86 86
             LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
87 87
         try {
88 88
             $controller->setRequestedVersion($version);
89
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
89
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
90 90
                 return $controller->sendResponse(
91 91
                     new WP_Error(
92 92
                         'endpoint_parsing_error',
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
             LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
129 129
         try {
130 130
             $controller->setRequestedVersion($version);
131
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
131
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
132 132
                 return [];
133 133
             }
134 134
             // get the model for this version
@@ -192,11 +192,11 @@  discard block
 block discarded – undo
192 192
      */
193 193
     protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
194 194
     {
195
-        if (isset($schema['properties'][ $field_name ]['default'])) {
196
-            if (is_array($schema['properties'][ $field_name ]['default'])) {
197
-                foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) {
195
+        if (isset($schema['properties'][$field_name]['default'])) {
196
+            if (is_array($schema['properties'][$field_name]['default'])) {
197
+                foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) {
198 198
                     if ($default_key === 'raw') {
199
-                        $schema['properties'][ $field_name ]['default'][ $default_key ] =
199
+                        $schema['properties'][$field_name]['default'][$default_key] =
200 200
                             ModelDataTranslator::prepareFieldValueForJson(
201 201
                                 $field,
202 202
                                 $default_value,
@@ -205,9 +205,9 @@  discard block
 block discarded – undo
205 205
                     }
206 206
                 }
207 207
             } else {
208
-                $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson(
208
+                $schema['properties'][$field_name]['default'] = ModelDataTranslator::prepareFieldValueForJson(
209 209
                     $field,
210
-                    $schema['properties'][ $field_name ]['default'],
210
+                    $schema['properties'][$field_name]['default'],
211 211
                     $this->getModelVersionInfo()->requestedVersion()
212 212
                 );
213 213
             }
@@ -229,9 +229,9 @@  discard block
 block discarded – undo
229 229
     protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
230 230
     {
231 231
         if ($field instanceof EE_Datetime_Field) {
232
-            $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema();
232
+            $schema['properties'][$field_name.'_gmt'] = $field->getSchema();
233 233
             // modify the description
234
-            $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf(
234
+            $schema['properties'][$field_name.'_gmt']['description'] = sprintf(
235 235
                 esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
236 236
                 wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
237 237
             );
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
             LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
281 281
         try {
282 282
             $controller->setRequestedVersion($version);
283
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
283
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
284 284
                 return $controller->sendResponse(
285 285
                     new WP_Error(
286 286
                         'endpoint_parsing_error',
@@ -360,7 +360,7 @@  discard block
 block discarded – undo
360 360
     public function getEntitiesFromModel($model, $request)
361 361
     {
362 362
         $query_params = $this->createModelQueryParams($model, $request->get_params());
363
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
363
+        if ( ! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
364 364
             $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
365 365
             throw new RestException(
366 366
                 sprintf('rest_%s_cannot_list', $model_name_plural),
@@ -372,7 +372,7 @@  discard block
 block discarded – undo
372 372
                 ['status' => 403]
373 373
             );
374 374
         }
375
-        if (! $request->get_header('no_rest_headers')) {
375
+        if ( ! $request->get_header('no_rest_headers')) {
376 376
             $this->setHeadersFromQueryParams($model, $query_params);
377 377
         }
378 378
         /** @type array $results */
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
         $context       = $this->validateContext($request->get_param('caps'));
414 414
         $model         = $relation->get_this_model();
415 415
         $related_model = $relation->get_other_model();
416
-        if (! isset($primary_model_query_params[0])) {
416
+        if ( ! isset($primary_model_query_params[0])) {
417 417
             $primary_model_query_params[0] = [];
418 418
         }
419 419
         // check if they can access the 1st model object
@@ -477,13 +477,13 @@  discard block
 block discarded – undo
477 477
         );
478 478
         $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
479 479
         foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
480
-            $query_params[0][ $relation->get_this_model()->get_this_model_name()
480
+            $query_params[0][$relation->get_this_model()->get_this_model_name()
481 481
                               . '.'
482
-                              . $where_condition_key ] = $where_condition_value;
482
+                              . $where_condition_key] = $where_condition_value;
483 483
         }
484 484
         $query_params['default_where_conditions'] = 'none';
485 485
         $query_params['caps']                     = $context;
486
-        if (! $request->get_header('no_rest_headers')) {
486
+        if ( ! $request->get_header('no_rest_headers')) {
487 487
             $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
488 488
         }
489 489
         /** @type array $results */
@@ -503,7 +503,7 @@  discard block
 block discarded – undo
503 503
                     $result,
504 504
                     $request
505 505
                 );
506
-                $joined_result     = array_merge($join_model_result, $nice_result);
506
+                $joined_result = array_merge($join_model_result, $nice_result);
507 507
                 // but keep the meta stuff from the main model
508 508
                 if (isset($nice_result['meta'])) {
509 509
                     $joined_result['meta'] = $nice_result['meta'];
@@ -535,7 +535,7 @@  discard block
 block discarded – undo
535 535
      */
536 536
     public function getEntitiesFromRelation($id, $relation, $request)
537 537
     {
538
-        if (! $relation->get_this_model()->has_primary_key_field()) {
538
+        if ( ! $relation->get_this_model()->has_primary_key_field()) {
539 539
             throw new EE_Error(
540 540
                 sprintf(
541 541
                     esc_html__(
@@ -582,7 +582,7 @@  discard block
 block discarded – undo
582 582
             Capabilities::getMissingPermissionsString($model, $query_params['caps'])
583 583
         );
584 584
         // normally the limit to a 2-part array, where the 2nd item is the limit
585
-        if (! isset($query_params['limit'])) {
585
+        if ( ! isset($query_params['limit'])) {
586 586
             $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
587 587
         }
588 588
         if (is_array($query_params['limit'])) {
@@ -621,7 +621,7 @@  discard block
 block discarded – undo
621 621
      */
622 622
     public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
623 623
     {
624
-        if (! $rest_request instanceof WP_REST_Request) {
624
+        if ( ! $rest_request instanceof WP_REST_Request) {
625 625
             // ok so this was called in the old style, where the 3rd arg was
626 626
             // $include, and the 4th arg was $context
627 627
             // now setup the request just to avoid fatal errors, although we won't be able
@@ -698,7 +698,7 @@  discard block
 block discarded – undo
698 698
             $rest_request,
699 699
             $this
700 700
         );
701
-        if (! $current_user_full_access_to_entity) {
701
+        if ( ! $current_user_full_access_to_entity) {
702 702
             $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields(
703 703
                 $entity_array,
704 704
                 $model,
@@ -733,7 +733,7 @@  discard block
 block discarded – undo
733 733
      */
734 734
     protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected)
735 735
     {
736
-        if (! $model->hasPassword() || ! $protected) {
736
+        if ( ! $model->hasPassword() || ! $protected) {
737 737
             return $results_so_far;
738 738
         }
739 739
         $password_field  = $model->getPasswordField();
@@ -782,8 +782,8 @@  discard block
 block discarded – undo
782 782
         if ($do_chevy_shuffle) {
783 783
             global $post;
784 784
             $old_post = $post;
785
-            $post     = get_post($result[ $model->primary_key_name() ]);
786
-            if (! $post instanceof WP_Post) {
785
+            $post     = get_post($result[$model->primary_key_name()]);
786
+            if ( ! $post instanceof WP_Post) {
787 787
                 // well that's weird, because $result is what we JUST fetched from the database
788 788
                 throw new RestException(
789 789
                     'error_fetching_post_from_database_results',
@@ -793,7 +793,7 @@  discard block
 block discarded – undo
793 793
                     )
794 794
                 );
795 795
             }
796
-            $model_object_classname          = 'EE_' . $model->get_this_model_name();
796
+            $model_object_classname          = 'EE_'.$model->get_this_model_name();
797 797
             $post->{$model_object_classname} = EE_Registry::instance()->load_class(
798 798
                 $model_object_classname,
799 799
                 $result,
@@ -804,14 +804,14 @@  discard block
 block discarded – undo
804 804
         foreach ($result as $field_name => $field_value) {
805 805
             $field_obj = $model->field_settings_for($field_name);
806 806
             if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
807
-                unset($result[ $field_name ]);
807
+                unset($result[$field_name]);
808 808
             } elseif (
809 809
                 $this->isSubclassOfOne(
810 810
                     $field_obj,
811 811
                     $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
812 812
                 )
813 813
             ) {
814
-                $result[ $field_name ] = [
814
+                $result[$field_name] = [
815 815
                     'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
816 816
                     'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
817 817
                 ];
@@ -821,7 +821,7 @@  discard block
 block discarded – undo
821 821
                     $this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
822 822
                 )
823 823
             ) {
824
-                $result[ $field_name ] = [
824
+                $result[$field_name] = [
825 825
                     'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
826 826
                     'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
827 827
                 ];
@@ -852,10 +852,10 @@  discard block
 block discarded – undo
852 852
                         $this->getModelVersionInfo()->requestedVersion()
853 853
                     );
854 854
                 }
855
-                $result[ $field_name . '_gmt' ] = $gmt_date;
856
-                $result[ $field_name ]          = $local_date;
855
+                $result[$field_name.'_gmt'] = $gmt_date;
856
+                $result[$field_name]          = $local_date;
857 857
             } else {
858
-                $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
858
+                $result[$field_name] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
859 859
             }
860 860
         }
861 861
         if ($do_chevy_shuffle) {
@@ -910,7 +910,7 @@  discard block
 block discarded – undo
910 910
     protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
911 911
     {
912 912
         if ($model instanceof EEM_CPT_Base) {
913
-            $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]);
913
+            $entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
914 914
         }
915 915
         return $entity_array;
916 916
     }
@@ -937,7 +937,7 @@  discard block
 block discarded – undo
937 937
                     'href' => $this->getVersionedLinkTo(
938 938
                         EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
939 939
                         . '/'
940
-                        . $entity_array[ $model->primary_key_name() ]
940
+                        . $entity_array[$model->primary_key_name()]
941 941
                     ),
942 942
                 ],
943 943
             ];
@@ -954,12 +954,12 @@  discard block
 block discarded – undo
954 954
             foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
955 955
                 $related_model_part                                                      =
956 956
                     Read::getRelatedEntityName($relation_name, $relation_obj);
957
-                $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [
957
+                $links[EED_Core_Rest_Api::ee_api_link_namespace.$related_model_part] = [
958 958
                     [
959 959
                         'href'   => $this->getVersionedLinkTo(
960 960
                             EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
961 961
                             . '/'
962
-                            . $entity_array[ $model->primary_key_name() ]
962
+                            . $entity_array[$model->primary_key_name()]
963 963
                             . '/'
964 964
                             . $related_model_part
965 965
                         ),
@@ -993,12 +993,12 @@  discard block
 block discarded – undo
993 993
         $included_items_protected = false
994 994
     ) {
995 995
         // if $db_row not included, hope the entity array has what we need
996
-        if (! $db_row) {
996
+        if ( ! $db_row) {
997 997
             $db_row = $entity_array;
998 998
         }
999 999
         $relation_settings = $this->getModelVersionInfo()->relationSettings($model);
1000 1000
         foreach ($relation_settings as $relation_name => $relation_obj) {
1001
-            $related_fields_to_include   = $this->explodeAndGetItemsPrefixedWith(
1001
+            $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith(
1002 1002
                 $rest_request->get_param('include'),
1003 1003
                 $relation_name
1004 1004
             );
@@ -1026,7 +1026,7 @@  discard block
 block discarded – undo
1026 1026
                         $model->deduce_fields_n_values_from_cols_n_values($db_row)
1027 1027
                     )
1028 1028
                 );
1029
-                if (! $included_items_protected) {
1029
+                if ( ! $included_items_protected) {
1030 1030
                     try {
1031 1031
                         $related_results = $this->getEntitiesFromRelationUsingModelQueryParams(
1032 1032
                             $primary_model_query_params,
@@ -1047,7 +1047,7 @@  discard block
 block discarded – undo
1047 1047
                             ? null
1048 1048
                             : [];
1049 1049
                 }
1050
-                $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results;
1050
+                $entity_array[Read::getRelatedEntityName($relation_name, $relation_obj)] = $related_results;
1051 1051
             }
1052 1052
         }
1053 1053
         return $entity_array;
@@ -1131,13 +1131,13 @@  discard block
 block discarded – undo
1131 1131
                 $schema = $this->fields_calculator->getJsonSchemaForModel($model);
1132 1132
                 if (
1133 1133
                     $row_is_protected
1134
-                    && isset($schema['properties'][ $field_to_calculate ]['protected'])
1135
-                    && $schema['properties'][ $field_to_calculate ]['protected']
1134
+                    && isset($schema['properties'][$field_to_calculate]['protected'])
1135
+                    && $schema['properties'][$field_to_calculate]['protected']
1136 1136
                 ) {
1137 1137
                     $calculated_value   = null;
1138 1138
                     $protected_fields[] = $field_to_calculate;
1139
-                    if ($schema['properties'][ $field_to_calculate ]['type']) {
1140
-                        switch ($schema['properties'][ $field_to_calculate ]['type']) {
1139
+                    if ($schema['properties'][$field_to_calculate]['type']) {
1140
+                        switch ($schema['properties'][$field_to_calculate]['type']) {
1141 1141
                             case 'boolean':
1142 1142
                                 $calculated_value = false;
1143 1143
                                 break;
@@ -1252,7 +1252,7 @@  discard block
 block discarded – undo
1252 1252
      */
1253 1253
     public function validateContext($context)
1254 1254
     {
1255
-        if (! $context) {
1255
+        if ( ! $context) {
1256 1256
             $context = EEM_Base::caps_read;
1257 1257
         }
1258 1258
         $valid_contexts = EEM_Base::valid_cap_contexts();
@@ -1277,7 +1277,7 @@  discard block
 block discarded – undo
1277 1277
             EEM_Base::default_where_conditions_minimum_all,
1278 1278
             EEM_Base::default_where_conditions_minimum_others,
1279 1279
         ];
1280
-        if (! $default_query_params) {
1280
+        if ( ! $default_query_params) {
1281 1281
             $default_query_params = EEM_Base::default_where_conditions_all;
1282 1282
         }
1283 1283
         if (
@@ -1363,14 +1363,14 @@  discard block
 block discarded – undo
1363 1363
         }
1364 1364
         if (isset($query_params['limit'])) {
1365 1365
             // limit should be either a string like '23' or '23,43', or an array with two items in it
1366
-            if (! is_array($query_params['limit'])) {
1366
+            if ( ! is_array($query_params['limit'])) {
1367 1367
                 $limit_array = explode(',', (string) $query_params['limit']);
1368 1368
             } else {
1369 1369
                 $limit_array = $query_params['limit'];
1370 1370
             }
1371 1371
             $sanitized_limit = [];
1372 1372
             foreach ($limit_array as $limit_part) {
1373
-                if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1373
+                if ($this->debug_mode && ( ! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1374 1374
                     throw new EE_Error(
1375 1375
                         sprintf(
1376 1376
                             esc_html__(
@@ -1428,7 +1428,7 @@  discard block
 block discarded – undo
1428 1428
     {
1429 1429
         $model_ready_query_params = [];
1430 1430
         foreach ($query_params as $key => $value) {
1431
-            $model_ready_query_params[ $key ] = is_array($value)
1431
+            $model_ready_query_params[$key] = is_array($value)
1432 1432
                 ? $this->prepareRestQueryParamsKeyForModels($model, $value)
1433 1433
                 : $value;
1434 1434
         }
@@ -1447,9 +1447,9 @@  discard block
 block discarded – undo
1447 1447
         $model_ready_query_params = [];
1448 1448
         foreach ($query_params as $key => $value) {
1449 1449
             if (is_array($value)) {
1450
-                $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1450
+                $model_ready_query_params[$key] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1451 1451
             } else {
1452
-                $model_ready_query_params[ $key ] = $value;
1452
+                $model_ready_query_params[$key] = $value;
1453 1453
             }
1454 1454
         }
1455 1455
         return $model_ready_query_params;
@@ -1481,17 +1481,17 @@  discard block
 block discarded – undo
1481 1481
         foreach ($exploded_contents as $item) {
1482 1482
             $item = trim($item);
1483 1483
             // if no prefix was provided, so we look for items with no "." in them
1484
-            if (! $prefix) {
1484
+            if ( ! $prefix) {
1485 1485
                 // does this item have a period?
1486 1486
                 if (strpos($item, '.') === false) {
1487 1487
                     // if not, then its what we're looking for
1488 1488
                     $contents_with_prefix[] = $item;
1489 1489
                 }
1490
-            } elseif (strpos($item, $prefix . '.') === 0) {
1490
+            } elseif (strpos($item, $prefix.'.') === 0) {
1491 1491
                 // this item has the prefix and a period, grab it
1492 1492
                 $contents_with_prefix[] = substr(
1493 1493
                     $item,
1494
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1494
+                    strpos($item, $prefix.'.') + strlen($prefix.'.')
1495 1495
                 );
1496 1496
             } elseif ($item === $prefix) {
1497 1497
                 // this item is JUST the prefix
@@ -1533,9 +1533,9 @@  discard block
 block discarded – undo
1533 1533
         if ($model_name) {
1534 1534
             foreach ($includes as $field_to_include) {
1535 1535
                 $field_to_include = trim($field_to_include);
1536
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1536
+                if (strpos($field_to_include, $model_name.'.') === 0) {
1537 1537
                     // found the model name at the exact start
1538
-                    $field_sans_model_name         = str_replace($model_name . '.', '', $field_to_include);
1538
+                    $field_sans_model_name         = str_replace($model_name.'.', '', $field_to_include);
1539 1539
                     $extracted_fields_to_include[] = $field_sans_model_name;
1540 1540
                 } elseif ($field_to_include == $model_name) {
1541 1541
                     $extracted_fields_to_include[] = '*';
@@ -1578,7 +1578,7 @@  discard block
 block discarded – undo
1578 1578
         $restricted_query_params['caps'] = $context;
1579 1579
         $this->setDebugInfo('model query params', $restricted_query_params);
1580 1580
         $model_rows = $model->get_all_wpdb_results($restricted_query_params);
1581
-        if (! empty($model_rows)) {
1581
+        if ( ! empty($model_rows)) {
1582 1582
             return $this->createEntityFromWpdbResult(
1583 1583
                 $model,
1584 1584
                 reset($model_rows),
@@ -1590,7 +1590,7 @@  discard block
 block discarded – undo
1590 1590
             if ($model->exists($query_params)) {
1591 1591
                 // you got shafted- it existed but we didn't want to tell you!
1592 1592
                 throw new RestException(
1593
-                    'rest_user_cannot_' . $context,
1593
+                    'rest_user_cannot_'.$context,
1594 1594
                     sprintf(
1595 1595
                         esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1596 1596
                         $context,
@@ -1644,14 +1644,14 @@  discard block
 block discarded – undo
1644 1644
         // if this entity requires a password, they better give it and it better be right!
1645 1645
         if (
1646 1646
             $model->hasPassword()
1647
-            && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== ''
1647
+            && $model_row[$model->getPasswordField()->get_qualified_column()] !== ''
1648 1648
         ) {
1649 1649
             if (empty($request['password'])) {
1650 1650
                 throw new RestPasswordRequiredException();
1651 1651
             }
1652 1652
             if (
1653 1653
                 ! hash_equals(
1654
-                    $model_row[ $model->getPasswordField()->get_qualified_column() ],
1654
+                    $model_row[$model->getPasswordField()->get_qualified_column()],
1655 1655
                     $request['password']
1656 1656
                 )
1657 1657
             ) {
@@ -1665,12 +1665,12 @@  discard block
 block discarded – undo
1665 1665
             $password_supplied = $request->get_param('password');
1666 1666
             if (empty($password_supplied)) {
1667 1667
                 $query_params['exclude_protected'] = true;
1668
-                if (! $model->exists($query_params)) {
1668
+                if ( ! $model->exists($query_params)) {
1669 1669
                     throw new RestPasswordRequiredException();
1670 1670
                 }
1671 1671
             } else {
1672
-                $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied;
1673
-                if (! $model->exists($query_params)) {
1672
+                $query_params[0][$model->modelChainAndPassword()] = $password_supplied;
1673
+                if ( ! $model->exists($query_params)) {
1674 1674
                     throw new RestPasswordIncorrectException();
1675 1675
                 }
1676 1676
             }
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/model/Write.php 2 patches
Indentation   +546 added lines, -546 removed lines patch added patch discarded remove patch
@@ -39,573 +39,573 @@
 block discarded – undo
39 39
 {
40 40
 
41 41
 
42
-    public function __construct()
43
-    {
44
-        parent::__construct();
45
-        EE_Registry::instance()->load_helper('Inflector');
46
-    }
42
+	public function __construct()
43
+	{
44
+		parent::__construct();
45
+		EE_Registry::instance()->load_helper('Inflector');
46
+	}
47 47
 
48 48
 
49
-    /**
50
-     * Handles requests to get all (or a filtered subset) of entities for a particular model
51
-     *
52
-     * @param WP_REST_Request $request
53
-     * @param string          $version
54
-     * @param string          $model_name
55
-     * @return WP_REST_Response|\WP_Error
56
-     */
57
-    public static function handleRequestInsert(WP_REST_Request $request, $version, $model_name)
58
-    {
59
-        $controller = new Write();
60
-        try {
61
-            $controller->setRequestedVersion($version);
62
-            return $controller->sendResponse(
63
-                $controller->insert(
64
-                    $controller->getModelVersionInfo()->loadModel($model_name),
65
-                    $request
66
-                )
67
-            );
68
-        } catch (Exception $e) {
69
-            return $controller->sendResponse($e);
70
-        }
71
-    }
49
+	/**
50
+	 * Handles requests to get all (or a filtered subset) of entities for a particular model
51
+	 *
52
+	 * @param WP_REST_Request $request
53
+	 * @param string          $version
54
+	 * @param string          $model_name
55
+	 * @return WP_REST_Response|\WP_Error
56
+	 */
57
+	public static function handleRequestInsert(WP_REST_Request $request, $version, $model_name)
58
+	{
59
+		$controller = new Write();
60
+		try {
61
+			$controller->setRequestedVersion($version);
62
+			return $controller->sendResponse(
63
+				$controller->insert(
64
+					$controller->getModelVersionInfo()->loadModel($model_name),
65
+					$request
66
+				)
67
+			);
68
+		} catch (Exception $e) {
69
+			return $controller->sendResponse($e);
70
+		}
71
+	}
72 72
 
73 73
 
74
-    /**
75
-     * Handles a request from \WP_REST_Server to update an EE model
76
-     *
77
-     * @param WP_REST_Request $request
78
-     * @param string          $version
79
-     * @param string          $model_name
80
-     * @return WP_REST_Response|\WP_Error
81
-     */
82
-    public static function handleRequestUpdate(WP_REST_Request $request, $version, $model_name)
83
-    {
84
-        $controller = new Write();
85
-        try {
86
-            $controller->setRequestedVersion($version);
87
-            return $controller->sendResponse(
88
-                $controller->update(
89
-                    $controller->getModelVersionInfo()->loadModel($model_name),
90
-                    $request
91
-                )
92
-            );
93
-        } catch (Exception $e) {
94
-            return $controller->sendResponse($e);
95
-        }
96
-    }
74
+	/**
75
+	 * Handles a request from \WP_REST_Server to update an EE model
76
+	 *
77
+	 * @param WP_REST_Request $request
78
+	 * @param string          $version
79
+	 * @param string          $model_name
80
+	 * @return WP_REST_Response|\WP_Error
81
+	 */
82
+	public static function handleRequestUpdate(WP_REST_Request $request, $version, $model_name)
83
+	{
84
+		$controller = new Write();
85
+		try {
86
+			$controller->setRequestedVersion($version);
87
+			return $controller->sendResponse(
88
+				$controller->update(
89
+					$controller->getModelVersionInfo()->loadModel($model_name),
90
+					$request
91
+				)
92
+			);
93
+		} catch (Exception $e) {
94
+			return $controller->sendResponse($e);
95
+		}
96
+	}
97 97
 
98 98
 
99
-    /**
100
-     * Deletes a single model object and returns it. Unless
101
-     *
102
-     * @param WP_REST_Request $request
103
-     * @param string          $version
104
-     * @param string          $model_name
105
-     * @return WP_REST_Response|\WP_Error
106
-     */
107
-    public static function handleRequestDelete(WP_REST_Request $request, $version, $model_name)
108
-    {
109
-        $controller = new Write();
110
-        try {
111
-            $controller->setRequestedVersion($version);
112
-            return $controller->sendResponse(
113
-                $controller->delete(
114
-                    $controller->getModelVersionInfo()->loadModel($model_name),
115
-                    $request
116
-                )
117
-            );
118
-        } catch (Exception $e) {
119
-            return $controller->sendResponse($e);
120
-        }
121
-    }
99
+	/**
100
+	 * Deletes a single model object and returns it. Unless
101
+	 *
102
+	 * @param WP_REST_Request $request
103
+	 * @param string          $version
104
+	 * @param string          $model_name
105
+	 * @return WP_REST_Response|\WP_Error
106
+	 */
107
+	public static function handleRequestDelete(WP_REST_Request $request, $version, $model_name)
108
+	{
109
+		$controller = new Write();
110
+		try {
111
+			$controller->setRequestedVersion($version);
112
+			return $controller->sendResponse(
113
+				$controller->delete(
114
+					$controller->getModelVersionInfo()->loadModel($model_name),
115
+					$request
116
+				)
117
+			);
118
+		} catch (Exception $e) {
119
+			return $controller->sendResponse($e);
120
+		}
121
+	}
122 122
 
123 123
 
124
-    /**
125
-     * Inserts a new model object according to the $request
126
-     *
127
-     * @param EEM_Base        $model
128
-     * @param WP_REST_Request $request
129
-     * @return array
130
-     * @throws EE_Error
131
-     * @throws RestException
132
-     */
133
-    public function insert(EEM_Base $model, WP_REST_Request $request)
134
-    {
135
-        Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'create');
136
-        $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
137
-        if (! current_user_can($default_cap_to_check_for)) {
138
-            throw new RestException(
139
-                'rest_cannot_create_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
140
-                sprintf(
141
-                    esc_html__(
142
-                    // @codingStandardsIgnoreStart
143
-                        'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to insert data into Event Espresso.',
144
-                        // @codingStandardsIgnoreEnd
145
-                        'event_espresso'
146
-                    ),
147
-                    $default_cap_to_check_for
148
-                ),
149
-                array('status' => 403)
150
-            );
151
-        }
152
-        $submitted_json_data = array_merge((array) $request->get_body_params(), (array) $request->get_json_params());
153
-        $model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels(
154
-            $submitted_json_data,
155
-            $model,
156
-            $this->getModelVersionInfo()->requestedVersion(),
157
-            true
158
-        );
159
-        $model_obj = EE_Registry::instance()->load_class(
160
-            $model->get_this_model_name(),
161
-            array($model_data, $model->get_timezone()),
162
-            false,
163
-            false
164
-        );
165
-        $model_obj->save();
166
-        $new_id = $model_obj->ID();
167
-        if (! $new_id) {
168
-            throw new RestException(
169
-                'rest_insertion_failed',
170
-                sprintf(esc_html__('Could not insert new %1$s', 'event_espresso'), $model->get_this_model_name())
171
-            );
172
-        }
173
-        return $this->returnModelObjAsJsonResponse($model_obj, $request);
174
-    }
124
+	/**
125
+	 * Inserts a new model object according to the $request
126
+	 *
127
+	 * @param EEM_Base        $model
128
+	 * @param WP_REST_Request $request
129
+	 * @return array
130
+	 * @throws EE_Error
131
+	 * @throws RestException
132
+	 */
133
+	public function insert(EEM_Base $model, WP_REST_Request $request)
134
+	{
135
+		Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'create');
136
+		$default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
137
+		if (! current_user_can($default_cap_to_check_for)) {
138
+			throw new RestException(
139
+				'rest_cannot_create_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
140
+				sprintf(
141
+					esc_html__(
142
+					// @codingStandardsIgnoreStart
143
+						'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to insert data into Event Espresso.',
144
+						// @codingStandardsIgnoreEnd
145
+						'event_espresso'
146
+					),
147
+					$default_cap_to_check_for
148
+				),
149
+				array('status' => 403)
150
+			);
151
+		}
152
+		$submitted_json_data = array_merge((array) $request->get_body_params(), (array) $request->get_json_params());
153
+		$model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels(
154
+			$submitted_json_data,
155
+			$model,
156
+			$this->getModelVersionInfo()->requestedVersion(),
157
+			true
158
+		);
159
+		$model_obj = EE_Registry::instance()->load_class(
160
+			$model->get_this_model_name(),
161
+			array($model_data, $model->get_timezone()),
162
+			false,
163
+			false
164
+		);
165
+		$model_obj->save();
166
+		$new_id = $model_obj->ID();
167
+		if (! $new_id) {
168
+			throw new RestException(
169
+				'rest_insertion_failed',
170
+				sprintf(esc_html__('Could not insert new %1$s', 'event_espresso'), $model->get_this_model_name())
171
+			);
172
+		}
173
+		return $this->returnModelObjAsJsonResponse($model_obj, $request);
174
+	}
175 175
 
176 176
 
177
-    /**
178
-     * Updates an existing model object according to the $request
179
-     *
180
-     * @param EEM_Base        $model
181
-     * @param WP_REST_Request $request
182
-     * @return array
183
-     * @throws EE_Error
184
-     */
185
-    public function update(EEM_Base $model, WP_REST_Request $request)
186
-    {
187
-        Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit');
188
-        $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
189
-        if (! current_user_can($default_cap_to_check_for)) {
190
-            throw new RestException(
191
-                'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
192
-                sprintf(
193
-                    esc_html__(
194
-                    // @codingStandardsIgnoreStart
195
-                        'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to update data into Event Espresso.',
196
-                        // @codingStandardsIgnoreEnd
197
-                        'event_espresso'
198
-                    ),
199
-                    $default_cap_to_check_for
200
-                ),
201
-                array('status' => 403)
202
-            );
203
-        }
204
-        $obj_id = $request->get_param('id');
205
-        if (! $obj_id) {
206
-            throw new RestException(
207
-                'rest_edit_failed',
208
-                sprintf(esc_html__('Could not edit %1$s', 'event_espresso'), $model->get_this_model_name())
209
-            );
210
-        }
211
-        $model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels(
212
-            $this->getBodyParams($request),
213
-            $model,
214
-            $this->getModelVersionInfo()->requestedVersion(),
215
-            true
216
-        );
217
-        $model_obj = $model->get_one_by_ID($obj_id);
218
-        if (! $model_obj instanceof EE_Base_Class) {
219
-            $lowercase_model_name = strtolower($model->get_this_model_name());
220
-            throw new RestException(
221
-                sprintf('rest_%s_invalid_id', $lowercase_model_name),
222
-                sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
223
-                array('status' => 404)
224
-            );
225
-        }
226
-        $model_obj->save($model_data);
227
-        return $this->returnModelObjAsJsonResponse($model_obj, $request);
228
-    }
177
+	/**
178
+	 * Updates an existing model object according to the $request
179
+	 *
180
+	 * @param EEM_Base        $model
181
+	 * @param WP_REST_Request $request
182
+	 * @return array
183
+	 * @throws EE_Error
184
+	 */
185
+	public function update(EEM_Base $model, WP_REST_Request $request)
186
+	{
187
+		Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit');
188
+		$default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
189
+		if (! current_user_can($default_cap_to_check_for)) {
190
+			throw new RestException(
191
+				'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
192
+				sprintf(
193
+					esc_html__(
194
+					// @codingStandardsIgnoreStart
195
+						'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to update data into Event Espresso.',
196
+						// @codingStandardsIgnoreEnd
197
+						'event_espresso'
198
+					),
199
+					$default_cap_to_check_for
200
+				),
201
+				array('status' => 403)
202
+			);
203
+		}
204
+		$obj_id = $request->get_param('id');
205
+		if (! $obj_id) {
206
+			throw new RestException(
207
+				'rest_edit_failed',
208
+				sprintf(esc_html__('Could not edit %1$s', 'event_espresso'), $model->get_this_model_name())
209
+			);
210
+		}
211
+		$model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels(
212
+			$this->getBodyParams($request),
213
+			$model,
214
+			$this->getModelVersionInfo()->requestedVersion(),
215
+			true
216
+		);
217
+		$model_obj = $model->get_one_by_ID($obj_id);
218
+		if (! $model_obj instanceof EE_Base_Class) {
219
+			$lowercase_model_name = strtolower($model->get_this_model_name());
220
+			throw new RestException(
221
+				sprintf('rest_%s_invalid_id', $lowercase_model_name),
222
+				sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
223
+				array('status' => 404)
224
+			);
225
+		}
226
+		$model_obj->save($model_data);
227
+		return $this->returnModelObjAsJsonResponse($model_obj, $request);
228
+	}
229 229
 
230 230
 
231
-    /**
232
-     * Updates an existing model object according to the $request
233
-     *
234
-     * @param EEM_Base        $model
235
-     * @param WP_REST_Request $request
236
-     * @return array of either the soft-deleted item, or
237
-     * @throws EE_Error
238
-     */
239
-    public function delete(EEM_Base $model, WP_REST_Request $request)
240
-    {
241
-        Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_delete, 'delete');
242
-        $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
243
-        if (! current_user_can($default_cap_to_check_for)) {
244
-            throw new RestException(
245
-                'rest_cannot_delete_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
246
-                sprintf(
247
-                    esc_html__(
248
-                    // @codingStandardsIgnoreStart
249
-                        'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to delete data into Event Espresso.',
250
-                        // @codingStandardsIgnoreEnd
251
-                        'event_espresso'
252
-                    ),
253
-                    $default_cap_to_check_for
254
-                ),
255
-                array('status' => 403)
256
-            );
257
-        }
258
-        $obj_id = $request->get_param('id');
259
-        // this is where we would apply more fine-grained caps
260
-        $model_obj = $model->get_one_by_ID($obj_id);
261
-        if (! $model_obj instanceof EE_Base_Class) {
262
-            $lowercase_model_name = strtolower($model->get_this_model_name());
263
-            throw new RestException(
264
-                sprintf('rest_%s_invalid_id', $lowercase_model_name),
265
-                sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
266
-                array('status' => 404)
267
-            );
268
-        }
269
-        $requested_permanent_delete = filter_var($request->get_param('force'), FILTER_VALIDATE_BOOLEAN);
270
-        $requested_allow_blocking = filter_var($request->get_param('allow_blocking'), FILTER_VALIDATE_BOOLEAN);
271
-        if ($requested_permanent_delete) {
272
-            $previous = $this->returnModelObjAsJsonResponse($model_obj, $request);
273
-            $deleted = (bool) $model->delete_permanently_by_ID($obj_id, $requested_allow_blocking);
274
-            return array(
275
-                'deleted'  => $deleted,
276
-                'previous' => $previous,
277
-            );
278
-        } else {
279
-            if ($model instanceof EEM_Soft_Delete_Base) {
280
-                $model->delete_by_ID($obj_id, $requested_allow_blocking);
281
-                return $this->returnModelObjAsJsonResponse($model_obj, $request);
282
-            } else {
283
-                throw new RestException(
284
-                    'rest_trash_not_supported',
285
-                    501,
286
-                    sprintf(
287
-                        esc_html__('%1$s do not support trashing. Set force=1 to delete.', 'event_espresso'),
288
-                        EEH_Inflector::pluralize($model->get_this_model_name())
289
-                    )
290
-                );
291
-            }
292
-        }
293
-    }
231
+	/**
232
+	 * Updates an existing model object according to the $request
233
+	 *
234
+	 * @param EEM_Base        $model
235
+	 * @param WP_REST_Request $request
236
+	 * @return array of either the soft-deleted item, or
237
+	 * @throws EE_Error
238
+	 */
239
+	public function delete(EEM_Base $model, WP_REST_Request $request)
240
+	{
241
+		Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_delete, 'delete');
242
+		$default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
243
+		if (! current_user_can($default_cap_to_check_for)) {
244
+			throw new RestException(
245
+				'rest_cannot_delete_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
246
+				sprintf(
247
+					esc_html__(
248
+					// @codingStandardsIgnoreStart
249
+						'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to delete data into Event Espresso.',
250
+						// @codingStandardsIgnoreEnd
251
+						'event_espresso'
252
+					),
253
+					$default_cap_to_check_for
254
+				),
255
+				array('status' => 403)
256
+			);
257
+		}
258
+		$obj_id = $request->get_param('id');
259
+		// this is where we would apply more fine-grained caps
260
+		$model_obj = $model->get_one_by_ID($obj_id);
261
+		if (! $model_obj instanceof EE_Base_Class) {
262
+			$lowercase_model_name = strtolower($model->get_this_model_name());
263
+			throw new RestException(
264
+				sprintf('rest_%s_invalid_id', $lowercase_model_name),
265
+				sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
266
+				array('status' => 404)
267
+			);
268
+		}
269
+		$requested_permanent_delete = filter_var($request->get_param('force'), FILTER_VALIDATE_BOOLEAN);
270
+		$requested_allow_blocking = filter_var($request->get_param('allow_blocking'), FILTER_VALIDATE_BOOLEAN);
271
+		if ($requested_permanent_delete) {
272
+			$previous = $this->returnModelObjAsJsonResponse($model_obj, $request);
273
+			$deleted = (bool) $model->delete_permanently_by_ID($obj_id, $requested_allow_blocking);
274
+			return array(
275
+				'deleted'  => $deleted,
276
+				'previous' => $previous,
277
+			);
278
+		} else {
279
+			if ($model instanceof EEM_Soft_Delete_Base) {
280
+				$model->delete_by_ID($obj_id, $requested_allow_blocking);
281
+				return $this->returnModelObjAsJsonResponse($model_obj, $request);
282
+			} else {
283
+				throw new RestException(
284
+					'rest_trash_not_supported',
285
+					501,
286
+					sprintf(
287
+						esc_html__('%1$s do not support trashing. Set force=1 to delete.', 'event_espresso'),
288
+						EEH_Inflector::pluralize($model->get_this_model_name())
289
+					)
290
+				);
291
+			}
292
+		}
293
+	}
294 294
 
295 295
 
296
-    /**
297
-     * Returns an array ready to be converted into a JSON response, based solely on the model object
298
-     *
299
-     * @param EE_Base_Class   $model_obj
300
-     * @param WP_REST_Request $request
301
-     * @return array ready for a response
302
-     */
303
-    protected function returnModelObjAsJsonResponse(EE_Base_Class $model_obj, WP_REST_Request $request)
304
-    {
305
-        $model = $model_obj->get_model();
306
-        // create an array exactly like the wpdb results row,
307
-        // so we can pass it to controllers/model/Read::create_entity_from_wpdb_result()
308
-        $simulated_db_row = array();
309
-        foreach ($model->field_settings(true) as $field_name => $field_obj) {
310
-            // we need to reconstruct the normal wpdb results, including the db-only fields
311
-            // like a secondary table's primary key. The models expect those (but don't care what value they have)
312
-            if ($field_obj instanceof EE_DB_Only_Field_Base) {
313
-                $raw_value = true;
314
-            } elseif ($field_obj instanceof EE_Datetime_Field) {
315
-                $raw_value = $model_obj->get_DateTime_object($field_name);
316
-            } else {
317
-                $raw_value = $model_obj->get_raw($field_name);
318
-            }
319
-            $simulated_db_row[ $field_obj->get_qualified_column() ] = $field_obj->prepare_for_use_in_db($raw_value);
320
-        }
321
-        $read_controller = LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
322
-        $read_controller->setRequestedVersion($this->getRequestedVersion());
323
-        // the simulates request really doesn't need any info downstream
324
-        $simulated_request = new WP_REST_Request('GET');
325
-        // set the caps context on the simulated according to the original request.
326
-        switch ($request->get_method()) {
327
-            case 'POST':
328
-            case 'PUT':
329
-                $caps_context = EEM_Base::caps_edit;
330
-                break;
331
-            case 'DELETE':
332
-                $caps_context = EEM_Base::caps_delete;
333
-                break;
334
-            default:
335
-                $caps_context = EEM_Base::caps_read_admin;
336
-        }
337
-        $simulated_request->set_param('caps', $caps_context);
338
-        return $read_controller->createEntityFromWpdbResult(
339
-            $model_obj->get_model(),
340
-            $simulated_db_row,
341
-            $simulated_request
342
-        );
343
-    }
296
+	/**
297
+	 * Returns an array ready to be converted into a JSON response, based solely on the model object
298
+	 *
299
+	 * @param EE_Base_Class   $model_obj
300
+	 * @param WP_REST_Request $request
301
+	 * @return array ready for a response
302
+	 */
303
+	protected function returnModelObjAsJsonResponse(EE_Base_Class $model_obj, WP_REST_Request $request)
304
+	{
305
+		$model = $model_obj->get_model();
306
+		// create an array exactly like the wpdb results row,
307
+		// so we can pass it to controllers/model/Read::create_entity_from_wpdb_result()
308
+		$simulated_db_row = array();
309
+		foreach ($model->field_settings(true) as $field_name => $field_obj) {
310
+			// we need to reconstruct the normal wpdb results, including the db-only fields
311
+			// like a secondary table's primary key. The models expect those (but don't care what value they have)
312
+			if ($field_obj instanceof EE_DB_Only_Field_Base) {
313
+				$raw_value = true;
314
+			} elseif ($field_obj instanceof EE_Datetime_Field) {
315
+				$raw_value = $model_obj->get_DateTime_object($field_name);
316
+			} else {
317
+				$raw_value = $model_obj->get_raw($field_name);
318
+			}
319
+			$simulated_db_row[ $field_obj->get_qualified_column() ] = $field_obj->prepare_for_use_in_db($raw_value);
320
+		}
321
+		$read_controller = LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
322
+		$read_controller->setRequestedVersion($this->getRequestedVersion());
323
+		// the simulates request really doesn't need any info downstream
324
+		$simulated_request = new WP_REST_Request('GET');
325
+		// set the caps context on the simulated according to the original request.
326
+		switch ($request->get_method()) {
327
+			case 'POST':
328
+			case 'PUT':
329
+				$caps_context = EEM_Base::caps_edit;
330
+				break;
331
+			case 'DELETE':
332
+				$caps_context = EEM_Base::caps_delete;
333
+				break;
334
+			default:
335
+				$caps_context = EEM_Base::caps_read_admin;
336
+		}
337
+		$simulated_request->set_param('caps', $caps_context);
338
+		return $read_controller->createEntityFromWpdbResult(
339
+			$model_obj->get_model(),
340
+			$simulated_db_row,
341
+			$simulated_request
342
+		);
343
+	}
344 344
 
345 345
 
346
-    /**
347
-     * Gets the item affected by this request
348
-     *
349
-     * @param EEM_Base        $model
350
-     * @param WP_REST_Request $request
351
-     * @param  int|string     $obj_id
352
-     * @return \WP_Error|array
353
-     */
354
-    protected function getOneBasedOnRequest(EEM_Base $model, WP_REST_Request $request, $obj_id)
355
-    {
356
-        $requested_version = $this->getRequestedVersion($request->get_route());
357
-        $get_request = new WP_REST_Request(
358
-            'GET',
359
-            EED_Core_Rest_Api::ee_api_namespace
360
-            . $requested_version
361
-            . '/'
362
-            . EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
363
-            . '/'
364
-            . $obj_id
365
-        );
366
-        $get_request->set_url_params(
367
-            array(
368
-                'id'      => $obj_id,
369
-                'include' => $request->get_param('include'),
370
-            )
371
-        );
372
-        $read_controller = new Read();
373
-        $read_controller->setRequestedVersion($this->getRequestedVersion());
374
-        return $read_controller->getEntityFromModel($model, $get_request);
375
-    }
346
+	/**
347
+	 * Gets the item affected by this request
348
+	 *
349
+	 * @param EEM_Base        $model
350
+	 * @param WP_REST_Request $request
351
+	 * @param  int|string     $obj_id
352
+	 * @return \WP_Error|array
353
+	 */
354
+	protected function getOneBasedOnRequest(EEM_Base $model, WP_REST_Request $request, $obj_id)
355
+	{
356
+		$requested_version = $this->getRequestedVersion($request->get_route());
357
+		$get_request = new WP_REST_Request(
358
+			'GET',
359
+			EED_Core_Rest_Api::ee_api_namespace
360
+			. $requested_version
361
+			. '/'
362
+			. EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
363
+			. '/'
364
+			. $obj_id
365
+		);
366
+		$get_request->set_url_params(
367
+			array(
368
+				'id'      => $obj_id,
369
+				'include' => $request->get_param('include'),
370
+			)
371
+		);
372
+		$read_controller = new Read();
373
+		$read_controller->setRequestedVersion($this->getRequestedVersion());
374
+		return $read_controller->getEntityFromModel($model, $get_request);
375
+	}
376 376
 
377
-    /**
378
-     * Adds a relation between the specified models (if it doesn't already exist.)
379
-     * @since 4.9.76.p
380
-     * @param WP_REST_Request $request
381
-     * @return WP_REST_Response
382
-     */
383
-    public static function handleRequestAddRelation(WP_REST_Request $request, $version, $model_name, $related_model_name)
384
-    {
385
-        $controller = new Write();
386
-        try {
387
-            $controller->setRequestedVersion($version);
388
-            $main_model = $controller->validateModel($model_name);
389
-            $controller->validateModel($related_model_name);
390
-            return $controller->sendResponse(
391
-                $controller->addRelation(
392
-                    $main_model,
393
-                    $main_model->related_settings_for($related_model_name),
394
-                    $request
395
-                )
396
-            );
397
-        } catch (Exception $e) {
398
-            return $controller->sendResponse($e);
399
-        }
400
-    }
377
+	/**
378
+	 * Adds a relation between the specified models (if it doesn't already exist.)
379
+	 * @since 4.9.76.p
380
+	 * @param WP_REST_Request $request
381
+	 * @return WP_REST_Response
382
+	 */
383
+	public static function handleRequestAddRelation(WP_REST_Request $request, $version, $model_name, $related_model_name)
384
+	{
385
+		$controller = new Write();
386
+		try {
387
+			$controller->setRequestedVersion($version);
388
+			$main_model = $controller->validateModel($model_name);
389
+			$controller->validateModel($related_model_name);
390
+			return $controller->sendResponse(
391
+				$controller->addRelation(
392
+					$main_model,
393
+					$main_model->related_settings_for($related_model_name),
394
+					$request
395
+				)
396
+			);
397
+		} catch (Exception $e) {
398
+			return $controller->sendResponse($e);
399
+		}
400
+	}
401 401
 
402
-    /**
403
-     * Adds a relation between the two model specified model objects.
404
-     * @since 4.9.76.p
405
-     * @param EEM_Base $model
406
-     * @param EE_Model_Relation_Base $relation
407
-     * @param WP_REST_Request $request
408
-     * @return array
409
-     * @throws EE_Error
410
-     * @throws InvalidArgumentException
411
-     * @throws InvalidDataTypeException
412
-     * @throws InvalidInterfaceException
413
-     * @throws RestException
414
-     * @throws DomainException
415
-     */
416
-    public function addRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request)
417
-    {
418
-        list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request);
419
-        $extra_params = array();
420
-        if ($relation instanceof EE_HABTM_Relation) {
421
-            $extra_params = array_intersect_key(
422
-                ModelDataTranslator::prepareConditionsQueryParamsForModels(
423
-                    $request->get_body_params(),
424
-                    $relation->get_join_model(),
425
-                    $this->getModelVersionInfo()->requestedVersion(),
426
-                    true
427
-                ),
428
-                $relation->getNonKeyFields()
429
-            );
430
-        }
431
-        // Add a relation.
432
-        $related_obj = $model_obj->_add_relation_to(
433
-            $other_obj,
434
-            $relation->get_other_model()->get_this_model_name(),
435
-            $extra_params
436
-        );
437
-        $response = array(
438
-            strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request),
439
-            strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request),
440
-        );
441
-        if ($relation instanceof EE_HABTM_Relation) {
442
-            $join_model_obj = $relation->get_join_model()->get_one(
443
-                array(
444
-                    array(
445
-                        $relation->get_join_model()->get_foreign_key_to($model->get_this_model_name())->get_name() => $model_obj->ID(),
446
-                        $relation->get_join_model()->get_foreign_key_to($relation->get_other_model()->get_this_model_name())->get_name() => $related_obj->ID()
447
-                    )
448
-                )
449
-            );
450
-            $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
451
-        }
452
-        return $response;
453
-    }
402
+	/**
403
+	 * Adds a relation between the two model specified model objects.
404
+	 * @since 4.9.76.p
405
+	 * @param EEM_Base $model
406
+	 * @param EE_Model_Relation_Base $relation
407
+	 * @param WP_REST_Request $request
408
+	 * @return array
409
+	 * @throws EE_Error
410
+	 * @throws InvalidArgumentException
411
+	 * @throws InvalidDataTypeException
412
+	 * @throws InvalidInterfaceException
413
+	 * @throws RestException
414
+	 * @throws DomainException
415
+	 */
416
+	public function addRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request)
417
+	{
418
+		list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request);
419
+		$extra_params = array();
420
+		if ($relation instanceof EE_HABTM_Relation) {
421
+			$extra_params = array_intersect_key(
422
+				ModelDataTranslator::prepareConditionsQueryParamsForModels(
423
+					$request->get_body_params(),
424
+					$relation->get_join_model(),
425
+					$this->getModelVersionInfo()->requestedVersion(),
426
+					true
427
+				),
428
+				$relation->getNonKeyFields()
429
+			);
430
+		}
431
+		// Add a relation.
432
+		$related_obj = $model_obj->_add_relation_to(
433
+			$other_obj,
434
+			$relation->get_other_model()->get_this_model_name(),
435
+			$extra_params
436
+		);
437
+		$response = array(
438
+			strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request),
439
+			strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request),
440
+		);
441
+		if ($relation instanceof EE_HABTM_Relation) {
442
+			$join_model_obj = $relation->get_join_model()->get_one(
443
+				array(
444
+					array(
445
+						$relation->get_join_model()->get_foreign_key_to($model->get_this_model_name())->get_name() => $model_obj->ID(),
446
+						$relation->get_join_model()->get_foreign_key_to($relation->get_other_model()->get_this_model_name())->get_name() => $related_obj->ID()
447
+					)
448
+				)
449
+			);
450
+			$response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
451
+		}
452
+		return $response;
453
+	}
454 454
 
455 455
 
456
-    /**
457
-     * Removes the relation between the specified models (if it exists).
458
-     * @since 4.9.76.p
459
-     * @param WP_REST_Request $request
460
-     * @return WP_REST_Response
461
-     */
462
-    public static function handleRequestRemoveRelation(WP_REST_Request $request, $version, $model_name, $related_model_name)
463
-    {
464
-        $controller = new Write();
465
-        try {
466
-            $controller->setRequestedVersion($version);
467
-            $main_model = $controller->getModelVersionInfo()->loadModel($model_name);
468
-            return $controller->sendResponse(
469
-                $controller->removeRelation(
470
-                    $main_model,
471
-                    $main_model->related_settings_for($related_model_name),
472
-                    $request
473
-                )
474
-            );
475
-        } catch (Exception $e) {
476
-            return $controller->sendResponse($e);
477
-        }
478
-    }
456
+	/**
457
+	 * Removes the relation between the specified models (if it exists).
458
+	 * @since 4.9.76.p
459
+	 * @param WP_REST_Request $request
460
+	 * @return WP_REST_Response
461
+	 */
462
+	public static function handleRequestRemoveRelation(WP_REST_Request $request, $version, $model_name, $related_model_name)
463
+	{
464
+		$controller = new Write();
465
+		try {
466
+			$controller->setRequestedVersion($version);
467
+			$main_model = $controller->getModelVersionInfo()->loadModel($model_name);
468
+			return $controller->sendResponse(
469
+				$controller->removeRelation(
470
+					$main_model,
471
+					$main_model->related_settings_for($related_model_name),
472
+					$request
473
+				)
474
+			);
475
+		} catch (Exception $e) {
476
+			return $controller->sendResponse($e);
477
+		}
478
+	}
479 479
 
480
-    /**
481
-     * Adds a relation between the two model specified model objects.
482
-     * @since 4.9.76.p
483
-     * @param EEM_Base $model
484
-     * @param EE_Model_Relation_Base $relation
485
-     * @param WP_REST_Request $request
486
-     * @return array
487
-     * @throws DomainException
488
-     * @throws EE_Error
489
-     * @throws InvalidArgumentException
490
-     * @throws InvalidDataTypeException
491
-     * @throws InvalidInterfaceException
492
-     * @throws RestException
493
-     */
494
-    public function removeRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request)
495
-    {
496
-        // This endpoint doesn't accept body parameters (it's understandable to think it might, so let developers know
497
-        // up-front that it doesn't.)
498
-        if (!empty($request->get_body_params())) {
499
-            $body_params = $request->get_body_params();
500
-            throw new RestException(
501
-                'invalid_field',
502
-                sprintf(
503
-                    esc_html__('This endpoint doesn\'t accept post body arguments, you sent in %1$s', 'event_espresso'),
504
-                    implode(array_keys($body_params))
505
-                )
506
-            );
507
-        }
508
-        list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request);
509
-        // Remember the old relation, if it used a join entry.
510
-        $join_model_obj = null;
511
-        if ($relation instanceof EE_HABTM_Relation) {
512
-            $join_model_obj = $relation->get_join_model()->get_one(
513
-                array(
514
-                    array(
515
-                        $model->primary_key_name() => $model_obj->ID(),
516
-                        $relation->get_other_model()->primary_key_name() => $other_obj->ID()
517
-                    )
518
-                )
519
-            );
520
-        }
521
-        // Remove the relation.
522
-        $related_obj = $model_obj->_remove_relation_to(
523
-            $other_obj,
524
-            $relation->get_other_model()->get_this_model_name()
525
-        );
526
-        $response = array(
527
-            strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request),
528
-            strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request),
529
-        );
530
-        if ($relation instanceof EE_HABTM_Relation) {
531
-            $join_model_obj_after_removal = $relation->get_join_model()->get_one(
532
-                array(
533
-                    array(
534
-                        $model->primary_key_name() => $model_obj->ID(),
535
-                        $relation->get_other_model()->primary_key_name() => $other_obj->ID()
536
-                    )
537
-                )
538
-            );
539
-            if ($join_model_obj instanceof EE_Base_Class) {
540
-                $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
541
-            } else {
542
-                $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = null;
543
-            }
544
-        }
545
-        return $response;
546
-    }
480
+	/**
481
+	 * Adds a relation between the two model specified model objects.
482
+	 * @since 4.9.76.p
483
+	 * @param EEM_Base $model
484
+	 * @param EE_Model_Relation_Base $relation
485
+	 * @param WP_REST_Request $request
486
+	 * @return array
487
+	 * @throws DomainException
488
+	 * @throws EE_Error
489
+	 * @throws InvalidArgumentException
490
+	 * @throws InvalidDataTypeException
491
+	 * @throws InvalidInterfaceException
492
+	 * @throws RestException
493
+	 */
494
+	public function removeRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request)
495
+	{
496
+		// This endpoint doesn't accept body parameters (it's understandable to think it might, so let developers know
497
+		// up-front that it doesn't.)
498
+		if (!empty($request->get_body_params())) {
499
+			$body_params = $request->get_body_params();
500
+			throw new RestException(
501
+				'invalid_field',
502
+				sprintf(
503
+					esc_html__('This endpoint doesn\'t accept post body arguments, you sent in %1$s', 'event_espresso'),
504
+					implode(array_keys($body_params))
505
+				)
506
+			);
507
+		}
508
+		list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request);
509
+		// Remember the old relation, if it used a join entry.
510
+		$join_model_obj = null;
511
+		if ($relation instanceof EE_HABTM_Relation) {
512
+			$join_model_obj = $relation->get_join_model()->get_one(
513
+				array(
514
+					array(
515
+						$model->primary_key_name() => $model_obj->ID(),
516
+						$relation->get_other_model()->primary_key_name() => $other_obj->ID()
517
+					)
518
+				)
519
+			);
520
+		}
521
+		// Remove the relation.
522
+		$related_obj = $model_obj->_remove_relation_to(
523
+			$other_obj,
524
+			$relation->get_other_model()->get_this_model_name()
525
+		);
526
+		$response = array(
527
+			strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request),
528
+			strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request),
529
+		);
530
+		if ($relation instanceof EE_HABTM_Relation) {
531
+			$join_model_obj_after_removal = $relation->get_join_model()->get_one(
532
+				array(
533
+					array(
534
+						$model->primary_key_name() => $model_obj->ID(),
535
+						$relation->get_other_model()->primary_key_name() => $other_obj->ID()
536
+					)
537
+				)
538
+			);
539
+			if ($join_model_obj instanceof EE_Base_Class) {
540
+				$response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
541
+			} else {
542
+				$response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = null;
543
+			}
544
+		}
545
+		return $response;
546
+	}
547 547
 
548
-    /**
549
-     * Gets the model objects indicated by the model, relation object, and request.
550
-     * Throws an exception if the first object doesn't exist, and currently if the related object also doesn't exist.
551
-     * However, this behaviour may change, as we may add support for simultaneously creating and relating data.
552
-     * @since 4.9.76.p
553
-     * @param EEM_Base $model
554
-     * @param EE_Model_Relation_Base $relation
555
-     * @param WP_REST_Request $request
556
-     * @return array {
557
-     * @type EE_Base_Class $model_obj
558
-     * @type EE_Base_Class|null $other_model_obj
559
-     * }
560
-     * @throws RestException
561
-     */
562
-    protected function getBothModelObjects(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request)
563
-    {
564
-        // Check generic caps. For now, we're only allowing access to this endpoint to full admins.
565
-        Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit');
566
-        $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
567
-        if (! current_user_can($default_cap_to_check_for)) {
568
-            throw new RestException(
569
-                'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
570
-                sprintf(
571
-                    esc_html__(
572
-                        // @codingStandardsIgnoreStart
573
-                        'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to add relations in Event Espresso.',
574
-                        // @codingStandardsIgnoreEnd
575
-                        'event_espresso'
576
-                    ),
577
-                    $default_cap_to_check_for
578
-                ),
579
-                array('status' => 403)
580
-            );
581
-        }
582
-        // Get the main model object.
583
-        $model_obj = $this->getOneOrThrowException($model, $request->get_param('id'));
584
-        // For now, we require the other model object to exist too. This might be relaxed later.
585
-        $other_obj = $this->getOneOrThrowException($relation->get_other_model(), $request->get_param('related_id'));
586
-        return array($model_obj,$other_obj);
587
-    }
548
+	/**
549
+	 * Gets the model objects indicated by the model, relation object, and request.
550
+	 * Throws an exception if the first object doesn't exist, and currently if the related object also doesn't exist.
551
+	 * However, this behaviour may change, as we may add support for simultaneously creating and relating data.
552
+	 * @since 4.9.76.p
553
+	 * @param EEM_Base $model
554
+	 * @param EE_Model_Relation_Base $relation
555
+	 * @param WP_REST_Request $request
556
+	 * @return array {
557
+	 * @type EE_Base_Class $model_obj
558
+	 * @type EE_Base_Class|null $other_model_obj
559
+	 * }
560
+	 * @throws RestException
561
+	 */
562
+	protected function getBothModelObjects(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request)
563
+	{
564
+		// Check generic caps. For now, we're only allowing access to this endpoint to full admins.
565
+		Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit');
566
+		$default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
567
+		if (! current_user_can($default_cap_to_check_for)) {
568
+			throw new RestException(
569
+				'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
570
+				sprintf(
571
+					esc_html__(
572
+						// @codingStandardsIgnoreStart
573
+						'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to add relations in Event Espresso.',
574
+						// @codingStandardsIgnoreEnd
575
+						'event_espresso'
576
+					),
577
+					$default_cap_to_check_for
578
+				),
579
+				array('status' => 403)
580
+			);
581
+		}
582
+		// Get the main model object.
583
+		$model_obj = $this->getOneOrThrowException($model, $request->get_param('id'));
584
+		// For now, we require the other model object to exist too. This might be relaxed later.
585
+		$other_obj = $this->getOneOrThrowException($relation->get_other_model(), $request->get_param('related_id'));
586
+		return array($model_obj,$other_obj);
587
+	}
588 588
 
589
-    /**
590
-     * Gets the model with that ID or throws a REST exception.
591
-     * @since 4.9.76.p
592
-     * @param EEM_Base $model
593
-     * @param $id
594
-     * @return EE_Base_Class
595
-     * @throws RestException
596
-     */
597
-    protected function getOneOrThrowException(EEM_Base $model, $id)
598
-    {
599
-        $model_obj = $model->get_one_by_ID($id);
600
-        // @todo: check they can permission for it. For now unnecessary because only full admins can use this endpoint.
601
-        if ($model_obj instanceof EE_Base_Class) {
602
-            return $model_obj;
603
-        }
604
-        $lowercase_model_name = strtolower($model->get_this_model_name());
605
-        throw new RestException(
606
-            sprintf('rest_%s_invalid_id', $lowercase_model_name),
607
-            sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
608
-            array('status' => 404)
609
-        );
610
-    }
589
+	/**
590
+	 * Gets the model with that ID or throws a REST exception.
591
+	 * @since 4.9.76.p
592
+	 * @param EEM_Base $model
593
+	 * @param $id
594
+	 * @return EE_Base_Class
595
+	 * @throws RestException
596
+	 */
597
+	protected function getOneOrThrowException(EEM_Base $model, $id)
598
+	{
599
+		$model_obj = $model->get_one_by_ID($id);
600
+		// @todo: check they can permission for it. For now unnecessary because only full admins can use this endpoint.
601
+		if ($model_obj instanceof EE_Base_Class) {
602
+			return $model_obj;
603
+		}
604
+		$lowercase_model_name = strtolower($model->get_this_model_name());
605
+		throw new RestException(
606
+			sprintf('rest_%s_invalid_id', $lowercase_model_name),
607
+			sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
608
+			array('status' => 404)
609
+		);
610
+	}
611 611
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -134,9 +134,9 @@  discard block
 block discarded – undo
134 134
     {
135 135
         Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'create');
136 136
         $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
137
-        if (! current_user_can($default_cap_to_check_for)) {
137
+        if ( ! current_user_can($default_cap_to_check_for)) {
138 138
             throw new RestException(
139
-                'rest_cannot_create_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
139
+                'rest_cannot_create_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
140 140
                 sprintf(
141 141
                     esc_html__(
142 142
                     // @codingStandardsIgnoreStart
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
         );
165 165
         $model_obj->save();
166 166
         $new_id = $model_obj->ID();
167
-        if (! $new_id) {
167
+        if ( ! $new_id) {
168 168
             throw new RestException(
169 169
                 'rest_insertion_failed',
170 170
                 sprintf(esc_html__('Could not insert new %1$s', 'event_espresso'), $model->get_this_model_name())
@@ -186,9 +186,9 @@  discard block
 block discarded – undo
186 186
     {
187 187
         Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit');
188 188
         $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
189
-        if (! current_user_can($default_cap_to_check_for)) {
189
+        if ( ! current_user_can($default_cap_to_check_for)) {
190 190
             throw new RestException(
191
-                'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
191
+                'rest_cannot_edit_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
192 192
                 sprintf(
193 193
                     esc_html__(
194 194
                     // @codingStandardsIgnoreStart
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
             );
203 203
         }
204 204
         $obj_id = $request->get_param('id');
205
-        if (! $obj_id) {
205
+        if ( ! $obj_id) {
206 206
             throw new RestException(
207 207
                 'rest_edit_failed',
208 208
                 sprintf(esc_html__('Could not edit %1$s', 'event_espresso'), $model->get_this_model_name())
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
             true
216 216
         );
217 217
         $model_obj = $model->get_one_by_ID($obj_id);
218
-        if (! $model_obj instanceof EE_Base_Class) {
218
+        if ( ! $model_obj instanceof EE_Base_Class) {
219 219
             $lowercase_model_name = strtolower($model->get_this_model_name());
220 220
             throw new RestException(
221 221
                 sprintf('rest_%s_invalid_id', $lowercase_model_name),
@@ -240,9 +240,9 @@  discard block
 block discarded – undo
240 240
     {
241 241
         Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_delete, 'delete');
242 242
         $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
243
-        if (! current_user_can($default_cap_to_check_for)) {
243
+        if ( ! current_user_can($default_cap_to_check_for)) {
244 244
             throw new RestException(
245
-                'rest_cannot_delete_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
245
+                'rest_cannot_delete_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
246 246
                 sprintf(
247 247
                     esc_html__(
248 248
                     // @codingStandardsIgnoreStart
@@ -258,7 +258,7 @@  discard block
 block discarded – undo
258 258
         $obj_id = $request->get_param('id');
259 259
         // this is where we would apply more fine-grained caps
260 260
         $model_obj = $model->get_one_by_ID($obj_id);
261
-        if (! $model_obj instanceof EE_Base_Class) {
261
+        if ( ! $model_obj instanceof EE_Base_Class) {
262 262
             $lowercase_model_name = strtolower($model->get_this_model_name());
263 263
             throw new RestException(
264 264
                 sprintf('rest_%s_invalid_id', $lowercase_model_name),
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
             } else {
317 317
                 $raw_value = $model_obj->get_raw($field_name);
318 318
             }
319
-            $simulated_db_row[ $field_obj->get_qualified_column() ] = $field_obj->prepare_for_use_in_db($raw_value);
319
+            $simulated_db_row[$field_obj->get_qualified_column()] = $field_obj->prepare_for_use_in_db($raw_value);
320 320
         }
321 321
         $read_controller = LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read');
322 322
         $read_controller->setRequestedVersion($this->getRequestedVersion());
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
                     )
448 448
                 )
449 449
             );
450
-            $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
450
+            $response['join'][strtolower($relation->get_join_model()->get_this_model_name())] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
451 451
         }
452 452
         return $response;
453 453
     }
@@ -495,7 +495,7 @@  discard block
 block discarded – undo
495 495
     {
496 496
         // This endpoint doesn't accept body parameters (it's understandable to think it might, so let developers know
497 497
         // up-front that it doesn't.)
498
-        if (!empty($request->get_body_params())) {
498
+        if ( ! empty($request->get_body_params())) {
499 499
             $body_params = $request->get_body_params();
500 500
             throw new RestException(
501 501
                 'invalid_field',
@@ -537,9 +537,9 @@  discard block
 block discarded – undo
537 537
                 )
538 538
             );
539 539
             if ($join_model_obj instanceof EE_Base_Class) {
540
-                $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
540
+                $response['join'][strtolower($relation->get_join_model()->get_this_model_name())] = $this->returnModelObjAsJsonResponse($join_model_obj, $request);
541 541
             } else {
542
-                $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = null;
542
+                $response['join'][strtolower($relation->get_join_model()->get_this_model_name())] = null;
543 543
             }
544 544
         }
545 545
         return $response;
@@ -564,9 +564,9 @@  discard block
 block discarded – undo
564 564
         // Check generic caps. For now, we're only allowing access to this endpoint to full admins.
565 565
         Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit');
566 566
         $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap();
567
-        if (! current_user_can($default_cap_to_check_for)) {
567
+        if ( ! current_user_can($default_cap_to_check_for)) {
568 568
             throw new RestException(
569
-                'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
569
+                'rest_cannot_edit_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())),
570 570
                 sprintf(
571 571
                     esc_html__(
572 572
                         // @codingStandardsIgnoreStart
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
         $model_obj = $this->getOneOrThrowException($model, $request->get_param('id'));
584 584
         // For now, we require the other model object to exist too. This might be relaxed later.
585 585
         $other_obj = $this->getOneOrThrowException($relation->get_other_model(), $request->get_param('related_id'));
586
-        return array($model_obj,$other_obj);
586
+        return array($model_obj, $other_obj);
587 587
     }
588 588
 
589 589
     /**
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/Base.php 2 patches
Indentation   +334 added lines, -334 removed lines patch added patch discarded remove patch
@@ -21,338 +21,338 @@
 block discarded – undo
21 21
 class Base
22 22
 {
23 23
 
24
-    /**
25
-     * @deprecated use all-caps version
26
-     */
27
-    // @codingStandardsIgnoreStart
28
-    const header_prefix_for_ee = 'X-EE-';
29
-    // @codingStandardsIgnoreEnd
30
-
31
-    const HEADER_PREFIX_FOR_EE = 'X-EE-';
32
-
33
-    /**
34
-     * @deprecated use all-caps version instead
35
-     */
36
-    // @codingStandardsIgnoreStart
37
-    const header_prefix_for_wp = 'X-WP-';
38
-    // @codingStandardsIgnoreEnd
39
-
40
-    const HEADER_PREFIX_FOR_WP = 'X-WP-';
41
-
42
-    /**
43
-     * Contains debug info we'll send back in the response headers
44
-     *
45
-     * @var array
46
-     */
47
-    protected $debug_info = array();
48
-
49
-    /**
50
-     * Indicates whether or not the API is in debug mode
51
-     *
52
-     * @var boolean
53
-     */
54
-    protected $debug_mode = false;
55
-
56
-    /**
57
-     * Indicates the version that was requested
58
-     *
59
-     * @var string
60
-     */
61
-    protected $requested_version;
62
-
63
-    /**
64
-     * flat array of headers to send in the response
65
-     *
66
-     * @var array
67
-     */
68
-    protected $response_headers = array();
69
-
70
-
71
-    public function __construct()
72
-    {
73
-        $this->debug_mode = EED_Core_Rest_Api::debugMode();
74
-        // we are handling a REST request. Don't show a fancy HTML error message is any error comes up
75
-        add_filter('FHEE__EE_Error__get_error__show_normal_exceptions', '__return_true');
76
-    }
77
-
78
-
79
-    /**
80
-     * Sets the version the user requested
81
-     *
82
-     * @param string $version eg '4.8'
83
-     */
84
-    public function setRequestedVersion($version)
85
-    {
86
-        $this->requested_version = $version;
87
-    }
88
-
89
-
90
-    /**
91
-     * Sets some debug info that we'll send back in headers
92
-     *
93
-     * @param string       $key
94
-     * @param string|array $info
95
-     */
96
-    protected function setDebugInfo($key, $info)
97
-    {
98
-        $this->debug_info[ $key ] = $info;
99
-    }
100
-
101
-
102
-    /**
103
-     * Sets headers for the response
104
-     *
105
-     * @param string       $header_key    , excluding the "X-EE-" part
106
-     * @param array|string $value         if an array, multiple headers will be added, one
107
-     *                                    for each key in the array
108
-     * @param boolean      $use_ee_prefix whether to use the EE prefix on the header, or fallback to
109
-     *                                    the standard WP one
110
-     */
111
-    protected function setResponseHeader($header_key, $value, $use_ee_prefix = true)
112
-    {
113
-        if (is_array($value)) {
114
-            foreach ($value as $value_key => $value_value) {
115
-                $this->setResponseHeader($header_key . '[' . $value_key . ']', $value_value);
116
-            }
117
-        } else {
118
-            $prefix = $use_ee_prefix ? Base::HEADER_PREFIX_FOR_EE : Base::HEADER_PREFIX_FOR_WP;
119
-            $this->response_headers[ $prefix . $header_key ] = $value;
120
-        }
121
-    }
122
-
123
-
124
-    /**
125
-     * Returns a flat array of headers to be added to the response
126
-     *
127
-     * @return array
128
-     */
129
-    protected function getResponseHeaders()
130
-    {
131
-        return apply_filters(
132
-            'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_response_headers',
133
-            $this->response_headers,
134
-            $this,
135
-            $this->requested_version
136
-        );
137
-    }
138
-
139
-
140
-    /**
141
-     * Adds error notices from EE_Error onto the provided \WP_Error
142
-     *
143
-     * @param WP_Error $wp_error_response
144
-     * @return WP_Error
145
-     */
146
-    protected function addEeErrorsToResponse(WP_Error $wp_error_response)
147
-    {
148
-        $notices_during_checkin = EE_Error::get_raw_notices();
149
-        if (! empty($notices_during_checkin['errors'])) {
150
-            foreach ($notices_during_checkin['errors'] as $error_code => $error_message) {
151
-                $wp_error_response->add(
152
-                    sanitize_key($error_code),
153
-                    strip_tags($error_message)
154
-                );
155
-            }
156
-        }
157
-        return $wp_error_response;
158
-    }
159
-
160
-
161
-    /**
162
-     * Sends a response, but also makes sure to attach headers that
163
-     * are handy for debugging.
164
-     * Specifically, we assume folks will want to know what exactly was the DB query that got run,
165
-     * what exactly was the Models query that got run, what capabilities came into play, what fields were omitted from
166
-     * the response, others?
167
-     *
168
-     * @param array|WP_Error|Exception|RestException $response
169
-     * @return WP_REST_Response
170
-     */
171
-    public function sendResponse($response)
172
-    {
173
-        if ($response instanceof RestException) {
174
-            $response = new WP_Error($response->getStringCode(), $response->getMessage(), $response->getData());
175
-        }
176
-        if ($response instanceof Exception) {
177
-            $code = $response->getCode() ? $response->getCode() : 'error_occurred';
178
-            $response = new WP_Error($code, $response->getMessage());
179
-        }
180
-        if ($response instanceof WP_Error) {
181
-            $response = $this->addEeErrorsToResponse($response);
182
-            $rest_response = $this->createRestResponseFromWpError($response);
183
-        } else {
184
-            $rest_response = new WP_REST_Response($response, 200);
185
-        }
186
-        $headers = array();
187
-        if ($this->debug_mode && is_array($this->debug_info)) {
188
-            foreach ($this->debug_info as $debug_key => $debug_info) {
189
-                if (is_array($debug_info)) {
190
-                    $debug_info = wp_json_encode($debug_info);
191
-                }
192
-                $headers[ 'X-EE4-Debug-' . ucwords($debug_key) ] = $debug_info;
193
-            }
194
-        }
195
-        $headers = array_merge(
196
-            $headers,
197
-            $this->getResponseHeaders(),
198
-            $this->getHeadersFromEeNotices()
199
-        );
200
-        $rest_response->set_headers($headers);
201
-        return $rest_response;
202
-    }
203
-
204
-
205
-    /**
206
-     * Converts the \WP_Error into `WP_REST_Response.
207
-     * Mostly this is just a copy-and-paste from \WP_REST_Server::error_to_response
208
-     * (which is protected)
209
-     *
210
-     * @param WP_Error $wp_error
211
-     * @return WP_REST_Response
212
-     */
213
-    protected function createRestResponseFromWpError(WP_Error $wp_error)
214
-    {
215
-        $error_data = $wp_error->get_error_data();
216
-        if (is_array($error_data) && isset($error_data['status'])) {
217
-            $status = $error_data['status'];
218
-        } else {
219
-            $status = 500;
220
-        }
221
-        $errors = array();
222
-        foreach ((array) $wp_error->errors as $code => $messages) {
223
-            foreach ((array) $messages as $message) {
224
-                $errors[] = array(
225
-                    'code'    => $code,
226
-                    'message' => $message,
227
-                    'data'    => $wp_error->get_error_data($code),
228
-                );
229
-            }
230
-        }
231
-        $data = isset($errors[0]) ? $errors[0] : array();
232
-        if (count($errors) > 1) {
233
-            // Remove the primary error.
234
-            array_shift($errors);
235
-            $data['additional_errors'] = $errors;
236
-        }
237
-        return new WP_REST_Response($data, $status);
238
-    }
239
-
240
-
241
-    /**
242
-     * Array of headers derived from EE success, attention, and error messages
243
-     *
244
-     * @return array
245
-     */
246
-    protected function getHeadersFromEeNotices()
247
-    {
248
-        $headers = array();
249
-        $notices = EE_Error::get_raw_notices();
250
-        foreach ($notices as $notice_type => $sub_notices) {
251
-            if (! is_array($sub_notices)) {
252
-                continue;
253
-            }
254
-            foreach ($sub_notices as $notice_code => $sub_notice) {
255
-                $headers[ 'X-EE4-Notices-'
256
-                          . EEH_Inflector::humanize($notice_type)
257
-                          . '['
258
-                          . $notice_code
259
-                          . ']' ] = strip_tags($sub_notice);
260
-            }
261
-        }
262
-        return apply_filters(
263
-            'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_headers_from_ee_notices__return',
264
-            $headers,
265
-            $this->requested_version,
266
-            $notices
267
-        );
268
-    }
269
-
270
-
271
-    /**
272
-     * Finds which version of the API was requested given the route, and returns it.
273
-     * eg in a request to "mysite.com/wp-json/ee/v4.8.29/events/123" this would return
274
-     * "4.8.29".
275
-     * We should know hte requested version in this model though, so if no route is
276
-     * provided just use what we set earlier
277
-     *
278
-     * @param string $route
279
-     * @return string
280
-     */
281
-    public function getRequestedVersion($route = null)
282
-    {
283
-        if ($route === null) {
284
-            return $this->requested_version;
285
-        }
286
-        $matches = $this->parseRoute(
287
-            $route,
288
-            '~' . EED_Core_Rest_Api::ee_api_namespace_for_regex . '~',
289
-            array('version')
290
-        );
291
-        if (isset($matches['version'])) {
292
-            return $matches['version'];
293
-        } else {
294
-            return EED_Core_Rest_Api::latest_rest_api_version();
295
-        }
296
-    }
297
-
298
-
299
-    /**
300
-     * Applies the regex to the route, then creates an array using the values of
301
-     * $match_keys as keys (but ignores the full pattern match). Returns the array of matches.
302
-     * For example, if you call
303
-     * parse_route( '/ee/v4.8/events', '~\/ee\/v([^/]*)\/(.*)~', array( 'version', 'model' ) )
304
-     * it will return array( 'version' => '4.8', 'model' => 'events' )
305
-     *
306
-     * @param string $route
307
-     * @param string $regex
308
-     * @param array  $match_keys EXCLUDING matching the entire regex
309
-     * @return array where  $match_keys are the keys (the first value of $match_keys
310
-     *                           becomes the first key of the return value, etc. Eg passing in $match_keys of
311
-     *                           array( 'model', 'id' ), will, if the regex is successful, will return
312
-     *                           array( 'model' => 'foo', 'id' => 'bar' )
313
-     * @throws EE_Error if it couldn't be parsed
314
-     */
315
-    public function parseRoute($route, $regex, $match_keys)
316
-    {
317
-        $indexed_matches = array();
318
-        $success = preg_match($regex, $route, $matches);
319
-        if (is_array($matches)) {
320
-            // skip the overall regex match. Who cares
321
-            for ($i = 1; $i <= count($match_keys); $i++) {
322
-                if (! isset($matches[ $i ])) {
323
-                    $success = false;
324
-                } else {
325
-                    $indexed_matches[ $match_keys[ $i - 1 ] ] = $matches[ $i ];
326
-                }
327
-            }
328
-        }
329
-        if (! $success) {
330
-            throw new EE_Error(
331
-                esc_html__('We could not parse the URL. Please contact Event Espresso Support', 'event_espresso'),
332
-                'endpoint_parsing_error'
333
-            );
334
-        }
335
-        return $indexed_matches;
336
-    }
337
-
338
-
339
-    /**
340
-     * Gets the body's params (either from JSON or parsed body), which EXCLUDES the GET params and URL params
341
-     *
342
-     * @param \WP_REST_Request $request
343
-     * @return array
344
-     */
345
-    protected function getBodyParams(\WP_REST_Request $request)
346
-    {
347
-        // $request->get_params();
348
-        return array_merge(
349
-            (array) $request->get_body_params(),
350
-            (array) $request->get_json_params()
351
-        );
352
-        // return array_diff_key(
353
-        //    $request->get_params(),
354
-        //     $request->get_url_params(),
355
-        //     $request->get_query_params()
356
-        // );
357
-    }
24
+	/**
25
+	 * @deprecated use all-caps version
26
+	 */
27
+	// @codingStandardsIgnoreStart
28
+	const header_prefix_for_ee = 'X-EE-';
29
+	// @codingStandardsIgnoreEnd
30
+
31
+	const HEADER_PREFIX_FOR_EE = 'X-EE-';
32
+
33
+	/**
34
+	 * @deprecated use all-caps version instead
35
+	 */
36
+	// @codingStandardsIgnoreStart
37
+	const header_prefix_for_wp = 'X-WP-';
38
+	// @codingStandardsIgnoreEnd
39
+
40
+	const HEADER_PREFIX_FOR_WP = 'X-WP-';
41
+
42
+	/**
43
+	 * Contains debug info we'll send back in the response headers
44
+	 *
45
+	 * @var array
46
+	 */
47
+	protected $debug_info = array();
48
+
49
+	/**
50
+	 * Indicates whether or not the API is in debug mode
51
+	 *
52
+	 * @var boolean
53
+	 */
54
+	protected $debug_mode = false;
55
+
56
+	/**
57
+	 * Indicates the version that was requested
58
+	 *
59
+	 * @var string
60
+	 */
61
+	protected $requested_version;
62
+
63
+	/**
64
+	 * flat array of headers to send in the response
65
+	 *
66
+	 * @var array
67
+	 */
68
+	protected $response_headers = array();
69
+
70
+
71
+	public function __construct()
72
+	{
73
+		$this->debug_mode = EED_Core_Rest_Api::debugMode();
74
+		// we are handling a REST request. Don't show a fancy HTML error message is any error comes up
75
+		add_filter('FHEE__EE_Error__get_error__show_normal_exceptions', '__return_true');
76
+	}
77
+
78
+
79
+	/**
80
+	 * Sets the version the user requested
81
+	 *
82
+	 * @param string $version eg '4.8'
83
+	 */
84
+	public function setRequestedVersion($version)
85
+	{
86
+		$this->requested_version = $version;
87
+	}
88
+
89
+
90
+	/**
91
+	 * Sets some debug info that we'll send back in headers
92
+	 *
93
+	 * @param string       $key
94
+	 * @param string|array $info
95
+	 */
96
+	protected function setDebugInfo($key, $info)
97
+	{
98
+		$this->debug_info[ $key ] = $info;
99
+	}
100
+
101
+
102
+	/**
103
+	 * Sets headers for the response
104
+	 *
105
+	 * @param string       $header_key    , excluding the "X-EE-" part
106
+	 * @param array|string $value         if an array, multiple headers will be added, one
107
+	 *                                    for each key in the array
108
+	 * @param boolean      $use_ee_prefix whether to use the EE prefix on the header, or fallback to
109
+	 *                                    the standard WP one
110
+	 */
111
+	protected function setResponseHeader($header_key, $value, $use_ee_prefix = true)
112
+	{
113
+		if (is_array($value)) {
114
+			foreach ($value as $value_key => $value_value) {
115
+				$this->setResponseHeader($header_key . '[' . $value_key . ']', $value_value);
116
+			}
117
+		} else {
118
+			$prefix = $use_ee_prefix ? Base::HEADER_PREFIX_FOR_EE : Base::HEADER_PREFIX_FOR_WP;
119
+			$this->response_headers[ $prefix . $header_key ] = $value;
120
+		}
121
+	}
122
+
123
+
124
+	/**
125
+	 * Returns a flat array of headers to be added to the response
126
+	 *
127
+	 * @return array
128
+	 */
129
+	protected function getResponseHeaders()
130
+	{
131
+		return apply_filters(
132
+			'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_response_headers',
133
+			$this->response_headers,
134
+			$this,
135
+			$this->requested_version
136
+		);
137
+	}
138
+
139
+
140
+	/**
141
+	 * Adds error notices from EE_Error onto the provided \WP_Error
142
+	 *
143
+	 * @param WP_Error $wp_error_response
144
+	 * @return WP_Error
145
+	 */
146
+	protected function addEeErrorsToResponse(WP_Error $wp_error_response)
147
+	{
148
+		$notices_during_checkin = EE_Error::get_raw_notices();
149
+		if (! empty($notices_during_checkin['errors'])) {
150
+			foreach ($notices_during_checkin['errors'] as $error_code => $error_message) {
151
+				$wp_error_response->add(
152
+					sanitize_key($error_code),
153
+					strip_tags($error_message)
154
+				);
155
+			}
156
+		}
157
+		return $wp_error_response;
158
+	}
159
+
160
+
161
+	/**
162
+	 * Sends a response, but also makes sure to attach headers that
163
+	 * are handy for debugging.
164
+	 * Specifically, we assume folks will want to know what exactly was the DB query that got run,
165
+	 * what exactly was the Models query that got run, what capabilities came into play, what fields were omitted from
166
+	 * the response, others?
167
+	 *
168
+	 * @param array|WP_Error|Exception|RestException $response
169
+	 * @return WP_REST_Response
170
+	 */
171
+	public function sendResponse($response)
172
+	{
173
+		if ($response instanceof RestException) {
174
+			$response = new WP_Error($response->getStringCode(), $response->getMessage(), $response->getData());
175
+		}
176
+		if ($response instanceof Exception) {
177
+			$code = $response->getCode() ? $response->getCode() : 'error_occurred';
178
+			$response = new WP_Error($code, $response->getMessage());
179
+		}
180
+		if ($response instanceof WP_Error) {
181
+			$response = $this->addEeErrorsToResponse($response);
182
+			$rest_response = $this->createRestResponseFromWpError($response);
183
+		} else {
184
+			$rest_response = new WP_REST_Response($response, 200);
185
+		}
186
+		$headers = array();
187
+		if ($this->debug_mode && is_array($this->debug_info)) {
188
+			foreach ($this->debug_info as $debug_key => $debug_info) {
189
+				if (is_array($debug_info)) {
190
+					$debug_info = wp_json_encode($debug_info);
191
+				}
192
+				$headers[ 'X-EE4-Debug-' . ucwords($debug_key) ] = $debug_info;
193
+			}
194
+		}
195
+		$headers = array_merge(
196
+			$headers,
197
+			$this->getResponseHeaders(),
198
+			$this->getHeadersFromEeNotices()
199
+		);
200
+		$rest_response->set_headers($headers);
201
+		return $rest_response;
202
+	}
203
+
204
+
205
+	/**
206
+	 * Converts the \WP_Error into `WP_REST_Response.
207
+	 * Mostly this is just a copy-and-paste from \WP_REST_Server::error_to_response
208
+	 * (which is protected)
209
+	 *
210
+	 * @param WP_Error $wp_error
211
+	 * @return WP_REST_Response
212
+	 */
213
+	protected function createRestResponseFromWpError(WP_Error $wp_error)
214
+	{
215
+		$error_data = $wp_error->get_error_data();
216
+		if (is_array($error_data) && isset($error_data['status'])) {
217
+			$status = $error_data['status'];
218
+		} else {
219
+			$status = 500;
220
+		}
221
+		$errors = array();
222
+		foreach ((array) $wp_error->errors as $code => $messages) {
223
+			foreach ((array) $messages as $message) {
224
+				$errors[] = array(
225
+					'code'    => $code,
226
+					'message' => $message,
227
+					'data'    => $wp_error->get_error_data($code),
228
+				);
229
+			}
230
+		}
231
+		$data = isset($errors[0]) ? $errors[0] : array();
232
+		if (count($errors) > 1) {
233
+			// Remove the primary error.
234
+			array_shift($errors);
235
+			$data['additional_errors'] = $errors;
236
+		}
237
+		return new WP_REST_Response($data, $status);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Array of headers derived from EE success, attention, and error messages
243
+	 *
244
+	 * @return array
245
+	 */
246
+	protected function getHeadersFromEeNotices()
247
+	{
248
+		$headers = array();
249
+		$notices = EE_Error::get_raw_notices();
250
+		foreach ($notices as $notice_type => $sub_notices) {
251
+			if (! is_array($sub_notices)) {
252
+				continue;
253
+			}
254
+			foreach ($sub_notices as $notice_code => $sub_notice) {
255
+				$headers[ 'X-EE4-Notices-'
256
+						  . EEH_Inflector::humanize($notice_type)
257
+						  . '['
258
+						  . $notice_code
259
+						  . ']' ] = strip_tags($sub_notice);
260
+			}
261
+		}
262
+		return apply_filters(
263
+			'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_headers_from_ee_notices__return',
264
+			$headers,
265
+			$this->requested_version,
266
+			$notices
267
+		);
268
+	}
269
+
270
+
271
+	/**
272
+	 * Finds which version of the API was requested given the route, and returns it.
273
+	 * eg in a request to "mysite.com/wp-json/ee/v4.8.29/events/123" this would return
274
+	 * "4.8.29".
275
+	 * We should know hte requested version in this model though, so if no route is
276
+	 * provided just use what we set earlier
277
+	 *
278
+	 * @param string $route
279
+	 * @return string
280
+	 */
281
+	public function getRequestedVersion($route = null)
282
+	{
283
+		if ($route === null) {
284
+			return $this->requested_version;
285
+		}
286
+		$matches = $this->parseRoute(
287
+			$route,
288
+			'~' . EED_Core_Rest_Api::ee_api_namespace_for_regex . '~',
289
+			array('version')
290
+		);
291
+		if (isset($matches['version'])) {
292
+			return $matches['version'];
293
+		} else {
294
+			return EED_Core_Rest_Api::latest_rest_api_version();
295
+		}
296
+	}
297
+
298
+
299
+	/**
300
+	 * Applies the regex to the route, then creates an array using the values of
301
+	 * $match_keys as keys (but ignores the full pattern match). Returns the array of matches.
302
+	 * For example, if you call
303
+	 * parse_route( '/ee/v4.8/events', '~\/ee\/v([^/]*)\/(.*)~', array( 'version', 'model' ) )
304
+	 * it will return array( 'version' => '4.8', 'model' => 'events' )
305
+	 *
306
+	 * @param string $route
307
+	 * @param string $regex
308
+	 * @param array  $match_keys EXCLUDING matching the entire regex
309
+	 * @return array where  $match_keys are the keys (the first value of $match_keys
310
+	 *                           becomes the first key of the return value, etc. Eg passing in $match_keys of
311
+	 *                           array( 'model', 'id' ), will, if the regex is successful, will return
312
+	 *                           array( 'model' => 'foo', 'id' => 'bar' )
313
+	 * @throws EE_Error if it couldn't be parsed
314
+	 */
315
+	public function parseRoute($route, $regex, $match_keys)
316
+	{
317
+		$indexed_matches = array();
318
+		$success = preg_match($regex, $route, $matches);
319
+		if (is_array($matches)) {
320
+			// skip the overall regex match. Who cares
321
+			for ($i = 1; $i <= count($match_keys); $i++) {
322
+				if (! isset($matches[ $i ])) {
323
+					$success = false;
324
+				} else {
325
+					$indexed_matches[ $match_keys[ $i - 1 ] ] = $matches[ $i ];
326
+				}
327
+			}
328
+		}
329
+		if (! $success) {
330
+			throw new EE_Error(
331
+				esc_html__('We could not parse the URL. Please contact Event Espresso Support', 'event_espresso'),
332
+				'endpoint_parsing_error'
333
+			);
334
+		}
335
+		return $indexed_matches;
336
+	}
337
+
338
+
339
+	/**
340
+	 * Gets the body's params (either from JSON or parsed body), which EXCLUDES the GET params and URL params
341
+	 *
342
+	 * @param \WP_REST_Request $request
343
+	 * @return array
344
+	 */
345
+	protected function getBodyParams(\WP_REST_Request $request)
346
+	{
347
+		// $request->get_params();
348
+		return array_merge(
349
+			(array) $request->get_body_params(),
350
+			(array) $request->get_json_params()
351
+		);
352
+		// return array_diff_key(
353
+		//    $request->get_params(),
354
+		//     $request->get_url_params(),
355
+		//     $request->get_query_params()
356
+		// );
357
+	}
358 358
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
      */
96 96
     protected function setDebugInfo($key, $info)
97 97
     {
98
-        $this->debug_info[ $key ] = $info;
98
+        $this->debug_info[$key] = $info;
99 99
     }
100 100
 
101 101
 
@@ -112,11 +112,11 @@  discard block
 block discarded – undo
112 112
     {
113 113
         if (is_array($value)) {
114 114
             foreach ($value as $value_key => $value_value) {
115
-                $this->setResponseHeader($header_key . '[' . $value_key . ']', $value_value);
115
+                $this->setResponseHeader($header_key.'['.$value_key.']', $value_value);
116 116
             }
117 117
         } else {
118 118
             $prefix = $use_ee_prefix ? Base::HEADER_PREFIX_FOR_EE : Base::HEADER_PREFIX_FOR_WP;
119
-            $this->response_headers[ $prefix . $header_key ] = $value;
119
+            $this->response_headers[$prefix.$header_key] = $value;
120 120
         }
121 121
     }
122 122
 
@@ -146,7 +146,7 @@  discard block
 block discarded – undo
146 146
     protected function addEeErrorsToResponse(WP_Error $wp_error_response)
147 147
     {
148 148
         $notices_during_checkin = EE_Error::get_raw_notices();
149
-        if (! empty($notices_during_checkin['errors'])) {
149
+        if ( ! empty($notices_during_checkin['errors'])) {
150 150
             foreach ($notices_during_checkin['errors'] as $error_code => $error_message) {
151 151
                 $wp_error_response->add(
152 152
                     sanitize_key($error_code),
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
                 if (is_array($debug_info)) {
190 190
                     $debug_info = wp_json_encode($debug_info);
191 191
                 }
192
-                $headers[ 'X-EE4-Debug-' . ucwords($debug_key) ] = $debug_info;
192
+                $headers['X-EE4-Debug-'.ucwords($debug_key)] = $debug_info;
193 193
             }
194 194
         }
195 195
         $headers = array_merge(
@@ -248,15 +248,15 @@  discard block
 block discarded – undo
248 248
         $headers = array();
249 249
         $notices = EE_Error::get_raw_notices();
250 250
         foreach ($notices as $notice_type => $sub_notices) {
251
-            if (! is_array($sub_notices)) {
251
+            if ( ! is_array($sub_notices)) {
252 252
                 continue;
253 253
             }
254 254
             foreach ($sub_notices as $notice_code => $sub_notice) {
255
-                $headers[ 'X-EE4-Notices-'
255
+                $headers['X-EE4-Notices-'
256 256
                           . EEH_Inflector::humanize($notice_type)
257 257
                           . '['
258 258
                           . $notice_code
259
-                          . ']' ] = strip_tags($sub_notice);
259
+                          . ']'] = strip_tags($sub_notice);
260 260
             }
261 261
         }
262 262
         return apply_filters(
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
         }
286 286
         $matches = $this->parseRoute(
287 287
             $route,
288
-            '~' . EED_Core_Rest_Api::ee_api_namespace_for_regex . '~',
288
+            '~'.EED_Core_Rest_Api::ee_api_namespace_for_regex.'~',
289 289
             array('version')
290 290
         );
291 291
         if (isset($matches['version'])) {
@@ -319,14 +319,14 @@  discard block
 block discarded – undo
319 319
         if (is_array($matches)) {
320 320
             // skip the overall regex match. Who cares
321 321
             for ($i = 1; $i <= count($match_keys); $i++) {
322
-                if (! isset($matches[ $i ])) {
322
+                if ( ! isset($matches[$i])) {
323 323
                     $success = false;
324 324
                 } else {
325
-                    $indexed_matches[ $match_keys[ $i - 1 ] ] = $matches[ $i ];
325
+                    $indexed_matches[$match_keys[$i - 1]] = $matches[$i];
326 326
                 }
327 327
             }
328 328
         }
329
-        if (! $success) {
329
+        if ( ! $success) {
330 330
             throw new EE_Error(
331 331
                 esc_html__('We could not parse the URL. Please contact Event Espresso Support', 'event_espresso'),
332 332
                 'endpoint_parsing_error'
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/config/Read.php 1 patch
Indentation   +77 added lines, -77 removed lines patch added patch discarded remove patch
@@ -20,85 +20,85 @@
 block discarded – undo
20 20
 class Read
21 21
 {
22 22
 
23
-    /**
24
-     * @param WP_REST_Request $request
25
-     * @param string          $version
26
-     * @return EE_Config|WP_Error
27
-     */
28
-    public static function handleRequest(WP_REST_Request $request, $version)
29
-    {
30
-        $cap = EE_Restriction_Generator_Base::get_default_restrictions_cap();
31
-        if (EE_Capabilities::instance()->current_user_can($cap, 'read_over_api')) {
32
-            return EE_Config::instance();
33
-        } else {
34
-            return new WP_Error(
35
-                'cannot_read_config',
36
-                sprintf(
37
-                    esc_html__(
38
-                        'You do not have the necessary capabilities (%s) to read Event Espresso Configuration data',
39
-                        'event_espresso'
40
-                    ),
41
-                    $cap
42
-                ),
43
-                array('status' => 403)
44
-            );
45
-        }
46
-    }
23
+	/**
24
+	 * @param WP_REST_Request $request
25
+	 * @param string          $version
26
+	 * @return EE_Config|WP_Error
27
+	 */
28
+	public static function handleRequest(WP_REST_Request $request, $version)
29
+	{
30
+		$cap = EE_Restriction_Generator_Base::get_default_restrictions_cap();
31
+		if (EE_Capabilities::instance()->current_user_can($cap, 'read_over_api')) {
32
+			return EE_Config::instance();
33
+		} else {
34
+			return new WP_Error(
35
+				'cannot_read_config',
36
+				sprintf(
37
+					esc_html__(
38
+						'You do not have the necessary capabilities (%s) to read Event Espresso Configuration data',
39
+						'event_espresso'
40
+					),
41
+					$cap
42
+				),
43
+				array('status' => 403)
44
+			);
45
+		}
46
+	}
47 47
 
48 48
 
49
-    /**
50
-     * Handles the request for public site info
51
-     *
52
-     * @global                 $wp_json_basic_auth_success       boolean set by the basic auth plugin, indicates if the
53
-     *                                                           current user could be authenticated using basic auth
54
-     *                                                           data
55
-     * @global                 $wp_json_basic_auth_received_data boolean set by the basic auth plugin, indicates if
56
-     *                                                           basic auth data was somehow received
57
-     * @param WP_REST_Request  $request
58
-     * @param string           $version
59
-     * @return array|WP_Error
60
-     */
61
-    public static function handleRequestSiteInfo(WP_REST_Request $request, $version)
62
-    {
63
-        global $wp_json_basic_auth_success, $wp_json_basic_auth_received_data;
64
-        $insecure_usage_of_basic_auth = apply_filters(
65
-        // @codingStandardsIgnoreStart
66
-            'EventEspresso__core__libraries__rest_api__controllers__config__handle_request_site_info__insecure_usage_of_basic_auth',
67
-            // @codingStandardsIgnoreEnd
68
-            $wp_json_basic_auth_success && ! is_ssl(),
69
-            $request
70
-        );
71
-        if ($insecure_usage_of_basic_auth) {
72
-            $warning = sprintf(
73
-                esc_html__(
74
-                // @codingStandardsIgnoreStart
75
-                    'Notice: We strongly recommend installing an SSL Certificate on your website to keep your data secure. %1$sPlease see our recommendations.%2$s',
76
-                    // @codingStandardsIgnoreEnd
77
-                    'event_espresso'
78
-                ),
79
-                '<a href="https://eventespresso.com/wiki/rest-api-security-recommendations/">',
80
-                '</a>'
81
-            );
82
-        } else {
83
-            $warning = '';
84
-        }
85
-        return apply_filters(
86
-            'FHEE__EventEspresso_core_libraries_rest_api_controllers_config__handleRequestSiteInfo__return_val',
87
-            array(
88
-                'default_timezone' => array(
89
-                    'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
90
-                    'string' => get_option('timezone_string'),
91
-                    'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
92
-                ),
93
-                'default_currency' => EE_Config::instance()->currency,
94
-                'authentication'   => array(
95
-                    'received_basic_auth_data'     => (bool) $wp_json_basic_auth_received_data,
96
-                    'insecure_usage_of_basic_auth' => (bool) $insecure_usage_of_basic_auth,
97
-                    'warning'                      => $warning,
98
-                ),
99
-            )
100
-        );
101
-    }
49
+	/**
50
+	 * Handles the request for public site info
51
+	 *
52
+	 * @global                 $wp_json_basic_auth_success       boolean set by the basic auth plugin, indicates if the
53
+	 *                                                           current user could be authenticated using basic auth
54
+	 *                                                           data
55
+	 * @global                 $wp_json_basic_auth_received_data boolean set by the basic auth plugin, indicates if
56
+	 *                                                           basic auth data was somehow received
57
+	 * @param WP_REST_Request  $request
58
+	 * @param string           $version
59
+	 * @return array|WP_Error
60
+	 */
61
+	public static function handleRequestSiteInfo(WP_REST_Request $request, $version)
62
+	{
63
+		global $wp_json_basic_auth_success, $wp_json_basic_auth_received_data;
64
+		$insecure_usage_of_basic_auth = apply_filters(
65
+		// @codingStandardsIgnoreStart
66
+			'EventEspresso__core__libraries__rest_api__controllers__config__handle_request_site_info__insecure_usage_of_basic_auth',
67
+			// @codingStandardsIgnoreEnd
68
+			$wp_json_basic_auth_success && ! is_ssl(),
69
+			$request
70
+		);
71
+		if ($insecure_usage_of_basic_auth) {
72
+			$warning = sprintf(
73
+				esc_html__(
74
+				// @codingStandardsIgnoreStart
75
+					'Notice: We strongly recommend installing an SSL Certificate on your website to keep your data secure. %1$sPlease see our recommendations.%2$s',
76
+					// @codingStandardsIgnoreEnd
77
+					'event_espresso'
78
+				),
79
+				'<a href="https://eventespresso.com/wiki/rest-api-security-recommendations/">',
80
+				'</a>'
81
+			);
82
+		} else {
83
+			$warning = '';
84
+		}
85
+		return apply_filters(
86
+			'FHEE__EventEspresso_core_libraries_rest_api_controllers_config__handleRequestSiteInfo__return_val',
87
+			array(
88
+				'default_timezone' => array(
89
+					'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
90
+					'string' => get_option('timezone_string'),
91
+					'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
92
+				),
93
+				'default_currency' => EE_Config::instance()->currency,
94
+				'authentication'   => array(
95
+					'received_basic_auth_data'     => (bool) $wp_json_basic_auth_received_data,
96
+					'insecure_usage_of_basic_auth' => (bool) $insecure_usage_of_basic_auth,
97
+					'warning'                      => $warning,
98
+				),
99
+			)
100
+		);
101
+	}
102 102
 }
103 103
 
104 104
 // End of file Read.php
Please login to merge, or discard this patch.
core/libraries/rest_api/changes/ChangesInBase.php 2 patches
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -37,74 +37,74 @@
 block discarded – undo
37 37
 abstract class ChangesInBase
38 38
 {
39 39
 
40
-    /**
41
-     * The version that these changes happened
42
-     *
43
-     * @var string
44
-     */
45
-    protected $version = null;
40
+	/**
41
+	 * The version that these changes happened
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $version = null;
46 46
 
47 47
 
48
-    /**
49
-     * Called when an EE4 REST API request is made to an earlier version than
50
-     * what is indicated in this class' name.
51
-     * Uses WordPress' add_filter and add_action to modify the EE4 REST API's response
52
-     * so that regardless of what version of EE4 core is running, API clients
53
-     * will have a consistent response
54
-     *
55
-     * @return void
56
-     */
57
-    abstract public function setHooks();
48
+	/**
49
+	 * Called when an EE4 REST API request is made to an earlier version than
50
+	 * what is indicated in this class' name.
51
+	 * Uses WordPress' add_filter and add_action to modify the EE4 REST API's response
52
+	 * so that regardless of what version of EE4 core is running, API clients
53
+	 * will have a consistent response
54
+	 *
55
+	 * @return void
56
+	 */
57
+	abstract public function setHooks();
58 58
 
59 59
 
60
-    /**
61
-     * Returns whether or not this class' name indicates its hooks should
62
-     * apply when a request comes in for $requested_version. A class can use
63
-     * other conditions when determining whether to perform their callbacks or not,
64
-     * but this will typically be enough
65
-     *
66
-     * @param string $requested_version eg "4.8.33"
67
-     * @return boolean true: this class' name indicates its filters and actions
68
-     *                                  should take effect. False: this class' name indicates it shouldn't do anything
69
-     */
70
-    public function appliesToVersion($requested_version)
71
-    {
72
-        if ($this->version() > $requested_version) {
73
-            return true;
74
-        }
75
-        return false;
76
-    }
60
+	/**
61
+	 * Returns whether or not this class' name indicates its hooks should
62
+	 * apply when a request comes in for $requested_version. A class can use
63
+	 * other conditions when determining whether to perform their callbacks or not,
64
+	 * but this will typically be enough
65
+	 *
66
+	 * @param string $requested_version eg "4.8.33"
67
+	 * @return boolean true: this class' name indicates its filters and actions
68
+	 *                                  should take effect. False: this class' name indicates it shouldn't do anything
69
+	 */
70
+	public function appliesToVersion($requested_version)
71
+	{
72
+		if ($this->version() > $requested_version) {
73
+			return true;
74
+		}
75
+		return false;
76
+	}
77 77
 
78 78
 
79
-    /**
80
-     * Gets the EE core version when this changes were made to the rest api.
81
-     * Any requests to earlier versions should have modifications made to them
82
-     * by the callbacks of this class.
83
-     *
84
-     * @return string eg "4.8.33"
85
-     * @throws EE_Error
86
-     */
87
-    public function version()
88
-    {
89
-        if ($this->version === null) {
90
-            $matches = array();
91
-            $regex = '~ChangesIn(\d)(\d\d)(\d\d)$~';
92
-            $success = preg_match(
93
-                $regex,
94
-                get_class($this),
95
-                $matches
96
-            );
97
-            if (! $success) {
98
-                throw new EE_Error(
99
-                    sprintf(
100
-                        esc_html__('The class %1$s was misnamed. It name should match the regex "%2$s"', 'event_espresso'),
101
-                        get_class($this),
102
-                        $regex
103
-                    )
104
-                );
105
-            }
106
-            $this->version = (int) $matches[1] . '.' . (int) $matches[2] . '.' . (int) $matches[3];
107
-        }
108
-        return $this->version;
109
-    }
79
+	/**
80
+	 * Gets the EE core version when this changes were made to the rest api.
81
+	 * Any requests to earlier versions should have modifications made to them
82
+	 * by the callbacks of this class.
83
+	 *
84
+	 * @return string eg "4.8.33"
85
+	 * @throws EE_Error
86
+	 */
87
+	public function version()
88
+	{
89
+		if ($this->version === null) {
90
+			$matches = array();
91
+			$regex = '~ChangesIn(\d)(\d\d)(\d\d)$~';
92
+			$success = preg_match(
93
+				$regex,
94
+				get_class($this),
95
+				$matches
96
+			);
97
+			if (! $success) {
98
+				throw new EE_Error(
99
+					sprintf(
100
+						esc_html__('The class %1$s was misnamed. It name should match the regex "%2$s"', 'event_espresso'),
101
+						get_class($this),
102
+						$regex
103
+					)
104
+				);
105
+			}
106
+			$this->version = (int) $matches[1] . '.' . (int) $matches[2] . '.' . (int) $matches[3];
107
+		}
108
+		return $this->version;
109
+	}
110 110
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -94,7 +94,7 @@  discard block
 block discarded – undo
94 94
                 get_class($this),
95 95
                 $matches
96 96
             );
97
-            if (! $success) {
97
+            if ( ! $success) {
98 98
                 throw new EE_Error(
99 99
                     sprintf(
100 100
                         esc_html__('The class %1$s was misnamed. It name should match the regex "%2$s"', 'event_espresso'),
@@ -103,7 +103,7 @@  discard block
 block discarded – undo
103 103
                     )
104 104
                 );
105 105
             }
106
-            $this->version = (int) $matches[1] . '.' . (int) $matches[2] . '.' . (int) $matches[3];
106
+            $this->version = (int) $matches[1].'.'.(int) $matches[2].'.'.(int) $matches[3];
107 107
         }
108 108
         return $this->version;
109 109
     }
Please login to merge, or discard this patch.
core/libraries/rest_api/calculations/Datetime.php 2 patches
Indentation   +200 added lines, -200 removed lines patch added patch discarded remove patch
@@ -17,214 +17,214 @@
 block discarded – undo
17 17
 
18 18
 class Datetime extends DatetimeCalculationBase
19 19
 {
20
-    /**
21
-     * @var EEM_Datetime
22
-     */
23
-    protected $datetime_model;
20
+	/**
21
+	 * @var EEM_Datetime
22
+	 */
23
+	protected $datetime_model;
24 24
 
25
-    /**
26
-     * @var EEM_Registration
27
-     */
28
-    protected $registration_model;
29
-    public function __construct(EEM_Datetime $datetime_model, EEM_Registration $registration_model)
30
-    {
31
-        $this->datetime_model = $datetime_model;
32
-        $this->registration_model = $registration_model;
33
-    }
25
+	/**
26
+	 * @var EEM_Registration
27
+	 */
28
+	protected $registration_model;
29
+	public function __construct(EEM_Datetime $datetime_model, EEM_Registration $registration_model)
30
+	{
31
+		$this->datetime_model = $datetime_model;
32
+		$this->registration_model = $registration_model;
33
+	}
34 34
 
35
-    /**
36
-     * Calculates the total spaces available on the datetime, taking into account
37
-     * ticket limits too.
38
-     *
39
-     * @see EE_Datetime::spaces_remaining( true )
40
-     * @param array            $wpdb_row
41
-     * @param WP_REST_Request $request
42
-     * @param DatetimeControllerBase  $controller
43
-     * @return int
44
-     * @throws EE_Error
45
-     * @throws InvalidDataTypeException
46
-     * @throws InvalidInterfaceException
47
-     * @throws InvalidArgumentException
48
-     * @throws ReflectionException
49
-     */
50
-    public function spacesRemainingConsideringTickets($wpdb_row, $request, $controller)
51
-    {
52
-        if (is_array($wpdb_row) && isset($wpdb_row['Datetime.DTT_ID'])) {
53
-            $dtt_obj = $this->datetime_model->get_one_by_ID($wpdb_row['Datetime.DTT_ID']);
54
-        } else {
55
-            $dtt_obj = null;
56
-        }
57
-        if ($dtt_obj instanceof EE_Datetime) {
58
-            return $dtt_obj->spaces_remaining(true);
59
-        }
60
-        throw new EE_Error(
61
-            sprintf(
62
-                esc_html__(
63
-                // @codingStandardsIgnoreStart
64
-                    'Cannot calculate spaces_remaining_considering_tickets because the datetime with ID %1$s (from database row %2$s) was not found',
65
-                    // @codingStandardsIgnoreEnd
66
-                    'event_espresso'
67
-                ),
68
-                $wpdb_row['Datetime.DTT_ID'],
69
-                print_r($wpdb_row, true)
70
-            )
71
-        );
72
-    }
35
+	/**
36
+	 * Calculates the total spaces available on the datetime, taking into account
37
+	 * ticket limits too.
38
+	 *
39
+	 * @see EE_Datetime::spaces_remaining( true )
40
+	 * @param array            $wpdb_row
41
+	 * @param WP_REST_Request $request
42
+	 * @param DatetimeControllerBase  $controller
43
+	 * @return int
44
+	 * @throws EE_Error
45
+	 * @throws InvalidDataTypeException
46
+	 * @throws InvalidInterfaceException
47
+	 * @throws InvalidArgumentException
48
+	 * @throws ReflectionException
49
+	 */
50
+	public function spacesRemainingConsideringTickets($wpdb_row, $request, $controller)
51
+	{
52
+		if (is_array($wpdb_row) && isset($wpdb_row['Datetime.DTT_ID'])) {
53
+			$dtt_obj = $this->datetime_model->get_one_by_ID($wpdb_row['Datetime.DTT_ID']);
54
+		} else {
55
+			$dtt_obj = null;
56
+		}
57
+		if ($dtt_obj instanceof EE_Datetime) {
58
+			return $dtt_obj->spaces_remaining(true);
59
+		}
60
+		throw new EE_Error(
61
+			sprintf(
62
+				esc_html__(
63
+				// @codingStandardsIgnoreStart
64
+					'Cannot calculate spaces_remaining_considering_tickets because the datetime with ID %1$s (from database row %2$s) was not found',
65
+					// @codingStandardsIgnoreEnd
66
+					'event_espresso'
67
+				),
68
+				$wpdb_row['Datetime.DTT_ID'],
69
+				print_r($wpdb_row, true)
70
+			)
71
+		);
72
+	}
73 73
 
74 74
 
75
-    /**
76
-     * Counts registrations who have checked into this datetime
77
-     *
78
-     * @param array           $wpdb_row
79
-     * @param WP_REST_Request $request
80
-     * @param DatetimeControllerBase $controller
81
-     * @return int
82
-     * @throws EE_Error
83
-     * @throws InvalidArgumentException
84
-     * @throws InvalidDataTypeException
85
-     * @throws InvalidInterfaceException
86
-     * @throws RestException
87
-     */
88
-    public function registrationsCheckedInCount($wpdb_row, $request, $controller)
89
-    {
90
-        if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
91
-            throw new EE_Error(
92
-                sprintf(
93
-                    esc_html__(
94
-                    // @codingStandardsIgnoreStart
95
-                        'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"',
96
-                        // @codingStandardsIgnoreEnd
97
-                        'event_espresso'
98
-                    ),
99
-                    print_r($wpdb_row, true)
100
-                )
101
-            );
102
-        }
103
-        $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count');
104
-        return $this->registration_model
105
-                               ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], true);
106
-    }
75
+	/**
76
+	 * Counts registrations who have checked into this datetime
77
+	 *
78
+	 * @param array           $wpdb_row
79
+	 * @param WP_REST_Request $request
80
+	 * @param DatetimeControllerBase $controller
81
+	 * @return int
82
+	 * @throws EE_Error
83
+	 * @throws InvalidArgumentException
84
+	 * @throws InvalidDataTypeException
85
+	 * @throws InvalidInterfaceException
86
+	 * @throws RestException
87
+	 */
88
+	public function registrationsCheckedInCount($wpdb_row, $request, $controller)
89
+	{
90
+		if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
91
+			throw new EE_Error(
92
+				sprintf(
93
+					esc_html__(
94
+					// @codingStandardsIgnoreStart
95
+						'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"',
96
+						// @codingStandardsIgnoreEnd
97
+						'event_espresso'
98
+					),
99
+					print_r($wpdb_row, true)
100
+				)
101
+			);
102
+		}
103
+		$this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count');
104
+		return $this->registration_model
105
+							   ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], true);
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * Counts registrations who have checked out of this datetime
111
-     *
112
-     * @param array           $wpdb_row
113
-     * @param WP_REST_Request $request
114
-     * @param DatetimeControllerBase $controller
115
-     * @return int
116
-     * @throws EE_Error
117
-     * @throws InvalidArgumentException
118
-     * @throws InvalidDataTypeException
119
-     * @throws InvalidInterfaceException
120
-     * @throws RestException
121
-     */
122
-    public function registrationsCheckedOutCount($wpdb_row, $request, $controller)
123
-    {
124
-        if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
125
-            throw new EE_Error(
126
-                sprintf(
127
-                    esc_html__(
128
-                    // @codingStandardsIgnoreStart
129
-                        'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"',
130
-                        // @codingStandardsIgnoreEnd
131
-                        'event_espresso'
132
-                    ),
133
-                    print_r($wpdb_row, true)
134
-                )
135
-            );
136
-        }
137
-        $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count');
138
-        return $this->registration_model
139
-                               ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], false);
140
-    }
109
+	/**
110
+	 * Counts registrations who have checked out of this datetime
111
+	 *
112
+	 * @param array           $wpdb_row
113
+	 * @param WP_REST_Request $request
114
+	 * @param DatetimeControllerBase $controller
115
+	 * @return int
116
+	 * @throws EE_Error
117
+	 * @throws InvalidArgumentException
118
+	 * @throws InvalidDataTypeException
119
+	 * @throws InvalidInterfaceException
120
+	 * @throws RestException
121
+	 */
122
+	public function registrationsCheckedOutCount($wpdb_row, $request, $controller)
123
+	{
124
+		if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
125
+			throw new EE_Error(
126
+				sprintf(
127
+					esc_html__(
128
+					// @codingStandardsIgnoreStart
129
+						'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"',
130
+						// @codingStandardsIgnoreEnd
131
+						'event_espresso'
132
+					),
133
+					print_r($wpdb_row, true)
134
+				)
135
+			);
136
+		}
137
+		$this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count');
138
+		return $this->registration_model
139
+							   ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], false);
140
+	}
141 141
 
142 142
 
143
-    /**
144
-     * Counts the number of pending-payment registrations for this event (regardless
145
-     * of how many datetimes each registrations' ticket purchase is for)
146
-     *
147
-     * @param array           $wpdb_row
148
-     * @param WP_REST_Request $request
149
-     * @param DatetimeControllerBase $controller
150
-     * @return int
151
-     * @throws EE_Error
152
-     * @throws InvalidArgumentException
153
-     * @throws InvalidDataTypeException
154
-     * @throws InvalidInterfaceException
155
-     * @throws RestException
156
-     */
157
-    public function spotsTakenPendingPayment($wpdb_row, $request, $controller)
158
-    {
159
-        if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
160
-            throw new EE_Error(
161
-                sprintf(
162
-                    esc_html__(
163
-                    // @codingStandardsIgnoreStart
164
-                        'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Datetime.DTT_ID"',
165
-                        // @codingStandardsIgnoreEnd
166
-                        'event_espresso'
167
-                    ),
168
-                    print_r($wpdb_row, true)
169
-                )
170
-            );
171
-        }
172
-        $this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment');
173
-        return $this->registration_model->count(
174
-            array(
175
-                array(
176
-                    'Ticket.Datetime.DTT_ID' => $wpdb_row['Datetime.DTT_ID'],
177
-                    'STS_ID'                 => EEM_Registration::status_id_pending_payment,
178
-                ),
179
-            ),
180
-            'REG_ID',
181
-            true
182
-        );
183
-    }
143
+	/**
144
+	 * Counts the number of pending-payment registrations for this event (regardless
145
+	 * of how many datetimes each registrations' ticket purchase is for)
146
+	 *
147
+	 * @param array           $wpdb_row
148
+	 * @param WP_REST_Request $request
149
+	 * @param DatetimeControllerBase $controller
150
+	 * @return int
151
+	 * @throws EE_Error
152
+	 * @throws InvalidArgumentException
153
+	 * @throws InvalidDataTypeException
154
+	 * @throws InvalidInterfaceException
155
+	 * @throws RestException
156
+	 */
157
+	public function spotsTakenPendingPayment($wpdb_row, $request, $controller)
158
+	{
159
+		if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
160
+			throw new EE_Error(
161
+				sprintf(
162
+					esc_html__(
163
+					// @codingStandardsIgnoreStart
164
+						'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Datetime.DTT_ID"',
165
+						// @codingStandardsIgnoreEnd
166
+						'event_espresso'
167
+					),
168
+					print_r($wpdb_row, true)
169
+				)
170
+			);
171
+		}
172
+		$this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment');
173
+		return $this->registration_model->count(
174
+			array(
175
+				array(
176
+					'Ticket.Datetime.DTT_ID' => $wpdb_row['Datetime.DTT_ID'],
177
+					'STS_ID'                 => EEM_Registration::status_id_pending_payment,
178
+				),
179
+			),
180
+			'REG_ID',
181
+			true
182
+		);
183
+	}
184 184
 
185 185
 
186
-    /**
187
-     * Provides an array for all the calculations possible that outlines a json schema for those calculations.
188
-     * Array is indexed by calculation (snake case) and value is the schema for that calculation.
189
-     *
190
-     * @since 4.9.68.p
191
-     * @return array
192
-     */
193
-    public function schemaForCalculations()
194
-    {
195
-        return array(
196
-            'spaces_remaining_considering_tickets' => array(
197
-                'description' => esc_html__(
198
-                    'Calculates the total spaces available on the datetime, taking into account ticket limits too.',
199
-                    'event_espresso'
200
-                ),
201
-                'type' => 'number',
202
-                'protected' => true,
203
-            ),
204
-            'registrations_checked_in_count' => array(
205
-                'description' => esc_html__(
206
-                    'Counts registrations who have checked into this datetime.',
207
-                    'event_espresso'
208
-                ),
209
-                'type' => 'number',
210
-                'protected' => true,
211
-            ),
212
-            'registrations_checked_out_count' => array(
213
-                'description' => esc_html__(
214
-                    'Counts registrations who have checked out of this datetime.',
215
-                    'event_espresso'
216
-                ),
217
-                'type' => 'number',
218
-                'protected' => true,
219
-            ),
220
-            'spots_taken_pending_payment' => array(
221
-                'description' => esc_html__(
222
-                    'The count of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for',
223
-                    'event_espresso'
224
-                ),
225
-                'type' => 'number',
226
-                'protected' => true,
227
-            ),
228
-        );
229
-    }
186
+	/**
187
+	 * Provides an array for all the calculations possible that outlines a json schema for those calculations.
188
+	 * Array is indexed by calculation (snake case) and value is the schema for that calculation.
189
+	 *
190
+	 * @since 4.9.68.p
191
+	 * @return array
192
+	 */
193
+	public function schemaForCalculations()
194
+	{
195
+		return array(
196
+			'spaces_remaining_considering_tickets' => array(
197
+				'description' => esc_html__(
198
+					'Calculates the total spaces available on the datetime, taking into account ticket limits too.',
199
+					'event_espresso'
200
+				),
201
+				'type' => 'number',
202
+				'protected' => true,
203
+			),
204
+			'registrations_checked_in_count' => array(
205
+				'description' => esc_html__(
206
+					'Counts registrations who have checked into this datetime.',
207
+					'event_espresso'
208
+				),
209
+				'type' => 'number',
210
+				'protected' => true,
211
+			),
212
+			'registrations_checked_out_count' => array(
213
+				'description' => esc_html__(
214
+					'Counts registrations who have checked out of this datetime.',
215
+					'event_espresso'
216
+				),
217
+				'type' => 'number',
218
+				'protected' => true,
219
+			),
220
+			'spots_taken_pending_payment' => array(
221
+				'description' => esc_html__(
222
+					'The count of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for',
223
+					'event_espresso'
224
+				),
225
+				'type' => 'number',
226
+				'protected' => true,
227
+			),
228
+		);
229
+	}
230 230
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
      */
88 88
     public function registrationsCheckedInCount($wpdb_row, $request, $controller)
89 89
     {
90
-        if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
90
+        if ( ! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
91 91
             throw new EE_Error(
92 92
                 sprintf(
93 93
                     esc_html__(
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
      */
122 122
     public function registrationsCheckedOutCount($wpdb_row, $request, $controller)
123 123
     {
124
-        if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
124
+        if ( ! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
125 125
             throw new EE_Error(
126 126
                 sprintf(
127 127
                     esc_html__(
@@ -156,7 +156,7 @@  discard block
 block discarded – undo
156 156
      */
157 157
     public function spotsTakenPendingPayment($wpdb_row, $request, $controller)
158 158
     {
159
-        if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
159
+        if ( ! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) {
160 160
             throw new EE_Error(
161 161
                 sprintf(
162 162
                     esc_html__(
Please login to merge, or discard this patch.
core/libraries/rest_api/calculations/Event.php 2 patches
Indentation   +567 added lines, -567 removed lines patch added patch discarded remove patch
@@ -26,571 +26,571 @@
 block discarded – undo
26 26
  */
27 27
 class Event extends EventCalculationBase
28 28
 {
29
-    /**
30
-     * @var EEM_Event
31
-     */
32
-    protected $event_model;
33
-
34
-    /**
35
-     * @var EEM_Registration
36
-     */
37
-    protected $registration_model;
38
-    public function __construct(EEM_Event $event_model, EEM_Registration $registration_model)
39
-    {
40
-        $this->event_model = $event_model;
41
-        $this->registration_model = $registration_model;
42
-    }
43
-
44
-    /**
45
-     * Calculates the total spaces on the event (not subtracting sales, but taking
46
-     * sales into account; so this is the optimum sales that CAN still be achieved)
47
-     * See EE_Event::total_available_spaces( true );
48
-     *
49
-     * @param array               $wpdb_row
50
-     * @param WP_REST_Request     $request
51
-     * @param EventControllerBase $controller
52
-     * @return int
53
-     * @throws EE_Error
54
-     * @throws DomainException
55
-     * @throws InvalidDataTypeException
56
-     * @throws InvalidInterfaceException
57
-     * @throws UnexpectedEntityException
58
-     * @throws InvalidArgumentException
59
-     */
60
-    public function optimumSalesAtStart($wpdb_row, $request, $controller)
61
-    {
62
-        $event_obj = null;
63
-        if (Event::wpdbRowHasEventId($wpdb_row)) {
64
-            $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']);
65
-        }
66
-        if ($event_obj instanceof EE_Event) {
67
-            return $event_obj->total_available_spaces();
68
-        }
69
-        throw new EE_Error(
70
-            sprintf(
71
-                esc_html__(
72
-                // @codingStandardsIgnoreStart
73
-                    'Cannot calculate optimum_sales_at_start because the event with ID %1$s (from database row %2$s) was not found',
74
-                    // @codingStandardsIgnoreEnd
75
-                    'event_espresso'
76
-                ),
77
-                $wpdb_row['Event_CPT.ID'],
78
-                print_r($wpdb_row, true)
79
-            )
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * Calculates the total spaces on the event (ignoring all sales; so this is the optimum
86
-     * sales that COULD have been achieved)
87
-     * See EE_Event::total_available_spaces( true );
88
-     *
89
-     * @param array               $wpdb_row
90
-     * @param WP_REST_Request     $request
91
-     * @param EventControllerBase $controller
92
-     * @return int
93
-     * @throws DomainException
94
-     * @throws EE_Error
95
-     * @throws InvalidArgumentException
96
-     * @throws InvalidDataTypeException
97
-     * @throws InvalidInterfaceException
98
-     * @throws UnexpectedEntityException
99
-     */
100
-    public function optimumSalesNow($wpdb_row, $request, $controller)
101
-    {
102
-        $event_obj = null;
103
-        if (Event::wpdbRowHasEventId($wpdb_row)) {
104
-            $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']);
105
-        }
106
-        if ($event_obj instanceof EE_Event) {
107
-            return $event_obj->total_available_spaces(true);
108
-        }
109
-        throw new EE_Error(
110
-            sprintf(
111
-                esc_html__(
112
-                // @codingStandardsIgnoreStart
113
-                    'Cannot calculate optimum_sales_now because the event with ID %1$s (from database row %2$s) was not found',
114
-                    // @codingStandardsIgnoreEnd
115
-                    'event_espresso'
116
-                ),
117
-                $wpdb_row['Event_CPT.ID'],
118
-                print_r($wpdb_row, true)
119
-            )
120
-        );
121
-    }
122
-
123
-
124
-    /**
125
-     * Like optimum_sales_now, but minus total sales so far.
126
-     * See EE_Event::spaces_remaining_for_sale( true );
127
-     *
128
-     * @param array               $wpdb_row
129
-     * @param WP_REST_Request     $request
130
-     * @param EventControllerBase $controller
131
-     * @return int
132
-     * @throws DomainException
133
-     * @throws EE_Error
134
-     * @throws InvalidArgumentException
135
-     * @throws InvalidDataTypeException
136
-     * @throws InvalidInterfaceException
137
-     * @throws UnexpectedEntityException
138
-     */
139
-    public function spacesRemaining($wpdb_row, $request, $controller)
140
-    {
141
-        $event_obj = null;
142
-        if (Event::wpdbRowHasEventId($wpdb_row)) {
143
-            $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']);
144
-        }
145
-        if ($event_obj instanceof EE_Event) {
146
-            return $event_obj->spaces_remaining_for_sale();
147
-        }
148
-        throw new EE_Error(
149
-            sprintf(
150
-                esc_html__(
151
-                // @codingStandardsIgnoreStart
152
-                    'Cannot calculate spaces_remaining because the event with ID %1$s (from database row %2$s) was not found',
153
-                    // @codingStandardsIgnoreEnd
154
-                    'event_espresso'
155
-                ),
156
-                $wpdb_row['Event_CPT.ID'],
157
-                print_r($wpdb_row, true)
158
-            )
159
-        );
160
-    }
161
-
162
-
163
-    /**
164
-     * Counts the number of approved registrations for this event (regardless
165
-     * of how many datetimes each registrations' ticket purchase is for)
166
-     *
167
-     * @param array               $wpdb_row
168
-     * @param WP_REST_Request     $request
169
-     * @param EventControllerBase $controller
170
-     * @return int
171
-     * @throws EE_Error
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     */
176
-    public function spotsTaken($wpdb_row, $request, $controller)
177
-    {
178
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
179
-            throw new EE_Error(
180
-                sprintf(
181
-                    esc_html__(
182
-                    // @codingStandardsIgnoreStart
183
-                        'Cannot calculate spots_taken because the database row %1$s does not have a valid entry for "Event_CPT.ID"',
184
-                        // @codingStandardsIgnoreEnd
185
-                        'event_espresso'
186
-                    ),
187
-                    print_r($wpdb_row, true)
188
-                )
189
-            );
190
-        }
191
-        return $this->registration_model->count(
192
-            array(
193
-                array(
194
-                    'EVT_ID' => $wpdb_row['Event_CPT.ID'],
195
-                    'STS_ID' => EEM_Registration::status_id_approved,
196
-                ),
197
-            ),
198
-            'REG_ID',
199
-            true
200
-        );
201
-    }
202
-
203
-
204
-    /**
205
-     * Counts the number of pending-payment registrations for this event (regardless
206
-     * of how many datetimes each registrations' ticket purchase is for)
207
-     *
208
-     * @param array               $wpdb_row
209
-     * @param WP_REST_Request     $request
210
-     * @param EventControllerBase $controller
211
-     * @return int
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws InvalidDataTypeException
215
-     * @throws InvalidInterfaceException
216
-     * @throws RestException
217
-     */
218
-    public function spotsTakenPendingPayment($wpdb_row, $request, $controller)
219
-    {
220
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
221
-            throw new EE_Error(
222
-                sprintf(
223
-                    esc_html__(
224
-                    // @codingStandardsIgnoreStart
225
-                        'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Event_CPT.ID"',
226
-                        // @codingStandardsIgnoreEnd
227
-                        'event_espresso'
228
-                    ),
229
-                    print_r($wpdb_row, true)
230
-                )
231
-            );
232
-        }
233
-        $this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment');
234
-        return $this->registration_model->count(
235
-            array(
236
-                array(
237
-                    'EVT_ID' => $wpdb_row['Event_CPT.ID'],
238
-                    'STS_ID' => EEM_Registration::status_id_pending_payment,
239
-                ),
240
-            ),
241
-            'REG_ID',
242
-            true
243
-        );
244
-    }
245
-
246
-
247
-    /**
248
-     * Counts all the registrations who have checked into one of this events' datetimes
249
-     * See EE_Event::total_available_spaces( false );
250
-     *
251
-     * @param array               $wpdb_row
252
-     * @param WP_REST_Request     $request
253
-     * @param EventControllerBase $controller
254
-     * @return int|null if permission denied
255
-     * @throws EE_Error
256
-     * @throws InvalidArgumentException
257
-     * @throws InvalidDataTypeException
258
-     * @throws InvalidInterfaceException
259
-     * @throws RestException
260
-     */
261
-    public function registrationsCheckedInCount($wpdb_row, $request, $controller)
262
-    {
263
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
264
-            throw new EE_Error(
265
-                sprintf(
266
-                    esc_html__(
267
-                    // @codingStandardsIgnoreStart
268
-                        'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Event_CPT.ID"',
269
-                        // @codingStandardsIgnoreEnd
270
-                        'event_espresso'
271
-                    ),
272
-                    print_r($wpdb_row, true)
273
-                )
274
-            );
275
-        }
276
-        $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count');
277
-        return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], true);
278
-    }
279
-
280
-
281
-    /**
282
-     * Counts all the registrations who have checked out of one of this events' datetimes
283
-     * See EE_Event::total_available_spaces( false );
284
-     *
285
-     * @param array               $wpdb_row
286
-     * @param WP_REST_Request     $request
287
-     * @param EventControllerBase $controller
288
-     * @return int
289
-     * @throws EE_Error
290
-     * @throws InvalidArgumentException
291
-     * @throws InvalidDataTypeException
292
-     * @throws InvalidInterfaceException
293
-     * @throws RestException
294
-     */
295
-    public function registrationsCheckedOutCount($wpdb_row, $request, $controller)
296
-    {
297
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
298
-            throw new EE_Error(
299
-                sprintf(
300
-                    esc_html__(
301
-                    // @codingStandardsIgnoreStart
302
-                        'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Event_CPT.ID"',
303
-                        // @codingStandardsIgnoreEnd
304
-                        'event_espresso'
305
-                    ),
306
-                    print_r($wpdb_row, true)
307
-                )
308
-            );
309
-        }
310
-        $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count');
311
-        return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], false);
312
-    }
313
-
314
-
315
-    /**
316
-     * Gets the thumbnail image
317
-     *
318
-     * @param array               $wpdb_row
319
-     * @param WP_REST_Request     $request
320
-     * @param EventControllerBase $controller
321
-     * @return array
322
-     * @throws EE_Error
323
-     */
324
-    public function imageThumbnail($wpdb_row, $request, $controller)
325
-    {
326
-        return self::calculateImageData($wpdb_row, 'thumbnail');
327
-    }
328
-
329
-
330
-    /**
331
-     * Gets the medium image
332
-     *
333
-     * @param array               $wpdb_row
334
-     * @param WP_REST_Request     $request
335
-     * @param EventControllerBase $controller
336
-     * @return array
337
-     * @throws EE_Error
338
-     */
339
-    public function imageMedium($wpdb_row, $request, $controller)
340
-    {
341
-        return self::calculateImageData($wpdb_row, 'medium');
342
-    }
343
-
344
-
345
-    /**
346
-     * Gets the medium-large image
347
-     *
348
-     * @param array               $wpdb_row
349
-     * @param WP_REST_Request     $request
350
-     * @param EventControllerBase $controller
351
-     * @return array
352
-     * @throws EE_Error
353
-     */
354
-    public function imageMediumLarge($wpdb_row, $request, $controller)
355
-    {
356
-        return self::calculateImageData($wpdb_row, 'medium_large');
357
-    }
358
-
359
-
360
-    /**
361
-     * Gets the large image
362
-     *
363
-     * @param array               $wpdb_row
364
-     * @param WP_REST_Request     $request
365
-     * @param EventControllerBase $controller
366
-     * @return array
367
-     * @throws EE_Error
368
-     */
369
-    public function imageLarge($wpdb_row, $request, $controller)
370
-    {
371
-        return self::calculateImageData($wpdb_row, 'large');
372
-    }
373
-
374
-
375
-    /**
376
-     * Gets the post-thumbnail image
377
-     *
378
-     * @param array               $wpdb_row
379
-     * @param WP_REST_Request     $request
380
-     * @param EventControllerBase $controller
381
-     * @return array
382
-     * @throws EE_Error
383
-     */
384
-    public function imagePostThumbnail($wpdb_row, $request, $controller)
385
-    {
386
-        return self::calculateImageData($wpdb_row, 'post-thumbnail');
387
-    }
388
-
389
-
390
-    /**
391
-     * Gets the full size image
392
-     *
393
-     * @param array               $wpdb_row
394
-     * @param WP_REST_Request     $request
395
-     * @param EventControllerBase $controller
396
-     * @return array
397
-     * @throws EE_Error
398
-     */
399
-    public function imageFull($wpdb_row, $request, $controller)
400
-    {
401
-        return self::calculateImageData($wpdb_row, 'full');
402
-    }
403
-
404
-
405
-    /**
406
-     * Gets image specs and formats them for the display in the API,
407
-     * according to the image size requested
408
-     *
409
-     * @param array  $wpdb_row
410
-     * @param string $image_size one of these: thumbnail, medium, medium_large, large, post-thumbnail, full
411
-     * @return array|false if no such image exists. If array it will have keys 'url', 'width', 'height' and 'original'
412
-     * @throws EE_Error
413
-     */
414
-    protected function calculateImageData($wpdb_row, $image_size)
415
-    {
416
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
417
-            throw new EE_Error(
418
-                sprintf(
419
-                    esc_html__(
420
-                    // @codingStandardsIgnoreStart
421
-                        'Cannot calculate image because the database row %1$s does not have an entry for "Event_CPT.ID"',
422
-                        // @codingStandardsIgnoreEnd
423
-                        'event_espresso'
424
-                    ),
425
-                    print_r($wpdb_row, true)
426
-                )
427
-            );
428
-        }
429
-        $EVT_ID = $wpdb_row['Event_CPT.ID'];
430
-        $attachment_id = get_post_thumbnail_id($EVT_ID);
431
-        $data = wp_get_attachment_image_src($attachment_id, $image_size);
432
-        if (! $data) {
433
-            return null;
434
-        }
435
-        $generated = true;
436
-        if (isset($data[3])) {
437
-            $generated = $data[3];
438
-        }
439
-        return array(
440
-            'url'       => $data[0],
441
-            'width'     => $data[1],
442
-            'height'    => $data[2],
443
-            'generated' => $generated,
444
-        );
445
-    }
446
-
447
-
448
-    /**
449
-     * Returns true if the array of data contains 'Event_CPT.ID'. False otherwise
450
-     *
451
-     * @param array $wpdb_row
452
-     * @return bool
453
-     */
454
-    protected function wpdbRowHasEventId($wpdb_row)
455
-    {
456
-        return (is_array($wpdb_row) && isset($wpdb_row['Event_CPT.ID']) && absint($wpdb_row['Event_CPT.ID']));
457
-    }
458
-
459
-
460
-    /**
461
-     * Provides an array for all the calculations possible that outlines a json schema for those calculations.
462
-     * Array is indexed by calculation (snake case) and value is the schema for that calculation.
463
-     *
464
-     * @since 4.9.68.p
465
-     * @return array
466
-     */
467
-    public function schemaForCalculations()
468
-    {
469
-        $image_object_properties = array(
470
-            'url'       => array(
471
-                'type' => 'string',
472
-            ),
473
-            'width'     => array(
474
-                'type' => 'number',
475
-            ),
476
-            'height'    => array(
477
-                'type' => 'number',
478
-            ),
479
-            'generated' => array(
480
-                'type' => 'boolean',
481
-            ),
482
-        );
483
-        return array(
484
-            'optimum_sales_at_start'          => array(
485
-                'description' => esc_html__(
486
-                    'The total spaces on the event (not subtracting sales, but taking sales into account; so this is the optimum sales that CAN still be achieved.',
487
-                    'event_espresso'
488
-                ),
489
-                'type'        => 'number',
490
-                'protected' => true,
491
-            ),
492
-            'optimum_sales_now'               => array(
493
-                'description' => esc_html__(
494
-                    'The total spaces on the event (ignoring all sales; so this is the optimum sales that could have been achieved.',
495
-                    'event_espresso'
496
-                ),
497
-                'type'        => 'number',
498
-                'protected' => true,
499
-            ),
500
-            'spaces_remaining'                => array(
501
-                'description' => esc_html__(
502
-                    'The optimum_sales_number result, minus total sales so far.',
503
-                    'event_espresso'
504
-                ),
505
-                'type'        => 'number',
506
-                'protected' => true,
507
-            ),
508
-            'spots_taken'                     => array(
509
-                'description' => esc_html__(
510
-                    'The number of approved registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)',
511
-                    'event_espresso'
512
-                ),
513
-                'type'        => 'number',
514
-                'protected' => true,
515
-            ),
516
-            'spots_taken_pending_payment'     => array(
517
-                'description' => esc_html__(
518
-                    'The number of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)',
519
-                    'event_espresso'
520
-                ),
521
-                'type'        => 'number',
522
-                'protected' => true,
523
-            ),
524
-            'registrations_checked_in_count'  => array(
525
-                'description' => esc_html__(
526
-                    'The count of all the registrations who have checked into one of this event\'s datetimes.',
527
-                    'event_espresso'
528
-                ),
529
-                'type'        => 'number',
530
-                'protected' => true,
531
-            ),
532
-            'registrations_checked_out_count' => array(
533
-                'description' => esc_html__(
534
-                    'The count of all registrations who have checked out of one of this event\'s datetimes.',
535
-                    'event_espresso'
536
-                ),
537
-                'type'        => 'number',
538
-                'protected' => true,
539
-            ),
540
-            'image_thumbnail'                 => array(
541
-                'description'          => esc_html__(
542
-                    'The thumbnail image data.',
543
-                    'event_espresso'
544
-                ),
545
-                'type'                 => 'object',
546
-                'properties'           => $image_object_properties,
547
-                'additionalProperties' => false,
548
-            ),
549
-            'image_medium'                    => array(
550
-                'description'          => esc_html__(
551
-                    'The medium image data.',
552
-                    'event_espresso'
553
-                ),
554
-                'type'                 => 'object',
555
-                'properties'           => $image_object_properties,
556
-                'additionalProperties' => false,
557
-            ),
558
-            'image_medium_large'              => array(
559
-                'description'          => esc_html__(
560
-                    'The medium-large image data.',
561
-                    'event_espresso'
562
-                ),
563
-                'type'                 => 'object',
564
-                'properties'           => $image_object_properties,
565
-                'additionalProperties' => false,
566
-            ),
567
-            'image_large'                     => array(
568
-                'description'          => esc_html__(
569
-                    'The large image data.',
570
-                    'event_espresso'
571
-                ),
572
-                'type'                 => 'object',
573
-                'properties'           => $image_object_properties,
574
-                'additionalProperties' => false,
575
-            ),
576
-            'image_post_thumbnail'            => array(
577
-                'description'          => esc_html__(
578
-                    'The post-thumbnail image data.',
579
-                    'event_espresso'
580
-                ),
581
-                'type'                 => 'object',
582
-                'properties'           => $image_object_properties,
583
-                'additionalProperties' => false,
584
-            ),
585
-            'image_full'                      => array(
586
-                'description'          => esc_html__(
587
-                    'The full size image data',
588
-                    'event_espresso'
589
-                ),
590
-                'type'                 => 'object',
591
-                'properties'           => $image_object_properties,
592
-                'additionalProperties' => false,
593
-            ),
594
-        );
595
-    }
29
+	/**
30
+	 * @var EEM_Event
31
+	 */
32
+	protected $event_model;
33
+
34
+	/**
35
+	 * @var EEM_Registration
36
+	 */
37
+	protected $registration_model;
38
+	public function __construct(EEM_Event $event_model, EEM_Registration $registration_model)
39
+	{
40
+		$this->event_model = $event_model;
41
+		$this->registration_model = $registration_model;
42
+	}
43
+
44
+	/**
45
+	 * Calculates the total spaces on the event (not subtracting sales, but taking
46
+	 * sales into account; so this is the optimum sales that CAN still be achieved)
47
+	 * See EE_Event::total_available_spaces( true );
48
+	 *
49
+	 * @param array               $wpdb_row
50
+	 * @param WP_REST_Request     $request
51
+	 * @param EventControllerBase $controller
52
+	 * @return int
53
+	 * @throws EE_Error
54
+	 * @throws DomainException
55
+	 * @throws InvalidDataTypeException
56
+	 * @throws InvalidInterfaceException
57
+	 * @throws UnexpectedEntityException
58
+	 * @throws InvalidArgumentException
59
+	 */
60
+	public function optimumSalesAtStart($wpdb_row, $request, $controller)
61
+	{
62
+		$event_obj = null;
63
+		if (Event::wpdbRowHasEventId($wpdb_row)) {
64
+			$event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']);
65
+		}
66
+		if ($event_obj instanceof EE_Event) {
67
+			return $event_obj->total_available_spaces();
68
+		}
69
+		throw new EE_Error(
70
+			sprintf(
71
+				esc_html__(
72
+				// @codingStandardsIgnoreStart
73
+					'Cannot calculate optimum_sales_at_start because the event with ID %1$s (from database row %2$s) was not found',
74
+					// @codingStandardsIgnoreEnd
75
+					'event_espresso'
76
+				),
77
+				$wpdb_row['Event_CPT.ID'],
78
+				print_r($wpdb_row, true)
79
+			)
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * Calculates the total spaces on the event (ignoring all sales; so this is the optimum
86
+	 * sales that COULD have been achieved)
87
+	 * See EE_Event::total_available_spaces( true );
88
+	 *
89
+	 * @param array               $wpdb_row
90
+	 * @param WP_REST_Request     $request
91
+	 * @param EventControllerBase $controller
92
+	 * @return int
93
+	 * @throws DomainException
94
+	 * @throws EE_Error
95
+	 * @throws InvalidArgumentException
96
+	 * @throws InvalidDataTypeException
97
+	 * @throws InvalidInterfaceException
98
+	 * @throws UnexpectedEntityException
99
+	 */
100
+	public function optimumSalesNow($wpdb_row, $request, $controller)
101
+	{
102
+		$event_obj = null;
103
+		if (Event::wpdbRowHasEventId($wpdb_row)) {
104
+			$event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']);
105
+		}
106
+		if ($event_obj instanceof EE_Event) {
107
+			return $event_obj->total_available_spaces(true);
108
+		}
109
+		throw new EE_Error(
110
+			sprintf(
111
+				esc_html__(
112
+				// @codingStandardsIgnoreStart
113
+					'Cannot calculate optimum_sales_now because the event with ID %1$s (from database row %2$s) was not found',
114
+					// @codingStandardsIgnoreEnd
115
+					'event_espresso'
116
+				),
117
+				$wpdb_row['Event_CPT.ID'],
118
+				print_r($wpdb_row, true)
119
+			)
120
+		);
121
+	}
122
+
123
+
124
+	/**
125
+	 * Like optimum_sales_now, but minus total sales so far.
126
+	 * See EE_Event::spaces_remaining_for_sale( true );
127
+	 *
128
+	 * @param array               $wpdb_row
129
+	 * @param WP_REST_Request     $request
130
+	 * @param EventControllerBase $controller
131
+	 * @return int
132
+	 * @throws DomainException
133
+	 * @throws EE_Error
134
+	 * @throws InvalidArgumentException
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws InvalidInterfaceException
137
+	 * @throws UnexpectedEntityException
138
+	 */
139
+	public function spacesRemaining($wpdb_row, $request, $controller)
140
+	{
141
+		$event_obj = null;
142
+		if (Event::wpdbRowHasEventId($wpdb_row)) {
143
+			$event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']);
144
+		}
145
+		if ($event_obj instanceof EE_Event) {
146
+			return $event_obj->spaces_remaining_for_sale();
147
+		}
148
+		throw new EE_Error(
149
+			sprintf(
150
+				esc_html__(
151
+				// @codingStandardsIgnoreStart
152
+					'Cannot calculate spaces_remaining because the event with ID %1$s (from database row %2$s) was not found',
153
+					// @codingStandardsIgnoreEnd
154
+					'event_espresso'
155
+				),
156
+				$wpdb_row['Event_CPT.ID'],
157
+				print_r($wpdb_row, true)
158
+			)
159
+		);
160
+	}
161
+
162
+
163
+	/**
164
+	 * Counts the number of approved registrations for this event (regardless
165
+	 * of how many datetimes each registrations' ticket purchase is for)
166
+	 *
167
+	 * @param array               $wpdb_row
168
+	 * @param WP_REST_Request     $request
169
+	 * @param EventControllerBase $controller
170
+	 * @return int
171
+	 * @throws EE_Error
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 */
176
+	public function spotsTaken($wpdb_row, $request, $controller)
177
+	{
178
+		if (! Event::wpdbRowHasEventId($wpdb_row)) {
179
+			throw new EE_Error(
180
+				sprintf(
181
+					esc_html__(
182
+					// @codingStandardsIgnoreStart
183
+						'Cannot calculate spots_taken because the database row %1$s does not have a valid entry for "Event_CPT.ID"',
184
+						// @codingStandardsIgnoreEnd
185
+						'event_espresso'
186
+					),
187
+					print_r($wpdb_row, true)
188
+				)
189
+			);
190
+		}
191
+		return $this->registration_model->count(
192
+			array(
193
+				array(
194
+					'EVT_ID' => $wpdb_row['Event_CPT.ID'],
195
+					'STS_ID' => EEM_Registration::status_id_approved,
196
+				),
197
+			),
198
+			'REG_ID',
199
+			true
200
+		);
201
+	}
202
+
203
+
204
+	/**
205
+	 * Counts the number of pending-payment registrations for this event (regardless
206
+	 * of how many datetimes each registrations' ticket purchase is for)
207
+	 *
208
+	 * @param array               $wpdb_row
209
+	 * @param WP_REST_Request     $request
210
+	 * @param EventControllerBase $controller
211
+	 * @return int
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws InvalidDataTypeException
215
+	 * @throws InvalidInterfaceException
216
+	 * @throws RestException
217
+	 */
218
+	public function spotsTakenPendingPayment($wpdb_row, $request, $controller)
219
+	{
220
+		if (! Event::wpdbRowHasEventId($wpdb_row)) {
221
+			throw new EE_Error(
222
+				sprintf(
223
+					esc_html__(
224
+					// @codingStandardsIgnoreStart
225
+						'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Event_CPT.ID"',
226
+						// @codingStandardsIgnoreEnd
227
+						'event_espresso'
228
+					),
229
+					print_r($wpdb_row, true)
230
+				)
231
+			);
232
+		}
233
+		$this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment');
234
+		return $this->registration_model->count(
235
+			array(
236
+				array(
237
+					'EVT_ID' => $wpdb_row['Event_CPT.ID'],
238
+					'STS_ID' => EEM_Registration::status_id_pending_payment,
239
+				),
240
+			),
241
+			'REG_ID',
242
+			true
243
+		);
244
+	}
245
+
246
+
247
+	/**
248
+	 * Counts all the registrations who have checked into one of this events' datetimes
249
+	 * See EE_Event::total_available_spaces( false );
250
+	 *
251
+	 * @param array               $wpdb_row
252
+	 * @param WP_REST_Request     $request
253
+	 * @param EventControllerBase $controller
254
+	 * @return int|null if permission denied
255
+	 * @throws EE_Error
256
+	 * @throws InvalidArgumentException
257
+	 * @throws InvalidDataTypeException
258
+	 * @throws InvalidInterfaceException
259
+	 * @throws RestException
260
+	 */
261
+	public function registrationsCheckedInCount($wpdb_row, $request, $controller)
262
+	{
263
+		if (! Event::wpdbRowHasEventId($wpdb_row)) {
264
+			throw new EE_Error(
265
+				sprintf(
266
+					esc_html__(
267
+					// @codingStandardsIgnoreStart
268
+						'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Event_CPT.ID"',
269
+						// @codingStandardsIgnoreEnd
270
+						'event_espresso'
271
+					),
272
+					print_r($wpdb_row, true)
273
+				)
274
+			);
275
+		}
276
+		$this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count');
277
+		return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], true);
278
+	}
279
+
280
+
281
+	/**
282
+	 * Counts all the registrations who have checked out of one of this events' datetimes
283
+	 * See EE_Event::total_available_spaces( false );
284
+	 *
285
+	 * @param array               $wpdb_row
286
+	 * @param WP_REST_Request     $request
287
+	 * @param EventControllerBase $controller
288
+	 * @return int
289
+	 * @throws EE_Error
290
+	 * @throws InvalidArgumentException
291
+	 * @throws InvalidDataTypeException
292
+	 * @throws InvalidInterfaceException
293
+	 * @throws RestException
294
+	 */
295
+	public function registrationsCheckedOutCount($wpdb_row, $request, $controller)
296
+	{
297
+		if (! Event::wpdbRowHasEventId($wpdb_row)) {
298
+			throw new EE_Error(
299
+				sprintf(
300
+					esc_html__(
301
+					// @codingStandardsIgnoreStart
302
+						'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Event_CPT.ID"',
303
+						// @codingStandardsIgnoreEnd
304
+						'event_espresso'
305
+					),
306
+					print_r($wpdb_row, true)
307
+				)
308
+			);
309
+		}
310
+		$this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count');
311
+		return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], false);
312
+	}
313
+
314
+
315
+	/**
316
+	 * Gets the thumbnail image
317
+	 *
318
+	 * @param array               $wpdb_row
319
+	 * @param WP_REST_Request     $request
320
+	 * @param EventControllerBase $controller
321
+	 * @return array
322
+	 * @throws EE_Error
323
+	 */
324
+	public function imageThumbnail($wpdb_row, $request, $controller)
325
+	{
326
+		return self::calculateImageData($wpdb_row, 'thumbnail');
327
+	}
328
+
329
+
330
+	/**
331
+	 * Gets the medium image
332
+	 *
333
+	 * @param array               $wpdb_row
334
+	 * @param WP_REST_Request     $request
335
+	 * @param EventControllerBase $controller
336
+	 * @return array
337
+	 * @throws EE_Error
338
+	 */
339
+	public function imageMedium($wpdb_row, $request, $controller)
340
+	{
341
+		return self::calculateImageData($wpdb_row, 'medium');
342
+	}
343
+
344
+
345
+	/**
346
+	 * Gets the medium-large image
347
+	 *
348
+	 * @param array               $wpdb_row
349
+	 * @param WP_REST_Request     $request
350
+	 * @param EventControllerBase $controller
351
+	 * @return array
352
+	 * @throws EE_Error
353
+	 */
354
+	public function imageMediumLarge($wpdb_row, $request, $controller)
355
+	{
356
+		return self::calculateImageData($wpdb_row, 'medium_large');
357
+	}
358
+
359
+
360
+	/**
361
+	 * Gets the large image
362
+	 *
363
+	 * @param array               $wpdb_row
364
+	 * @param WP_REST_Request     $request
365
+	 * @param EventControllerBase $controller
366
+	 * @return array
367
+	 * @throws EE_Error
368
+	 */
369
+	public function imageLarge($wpdb_row, $request, $controller)
370
+	{
371
+		return self::calculateImageData($wpdb_row, 'large');
372
+	}
373
+
374
+
375
+	/**
376
+	 * Gets the post-thumbnail image
377
+	 *
378
+	 * @param array               $wpdb_row
379
+	 * @param WP_REST_Request     $request
380
+	 * @param EventControllerBase $controller
381
+	 * @return array
382
+	 * @throws EE_Error
383
+	 */
384
+	public function imagePostThumbnail($wpdb_row, $request, $controller)
385
+	{
386
+		return self::calculateImageData($wpdb_row, 'post-thumbnail');
387
+	}
388
+
389
+
390
+	/**
391
+	 * Gets the full size image
392
+	 *
393
+	 * @param array               $wpdb_row
394
+	 * @param WP_REST_Request     $request
395
+	 * @param EventControllerBase $controller
396
+	 * @return array
397
+	 * @throws EE_Error
398
+	 */
399
+	public function imageFull($wpdb_row, $request, $controller)
400
+	{
401
+		return self::calculateImageData($wpdb_row, 'full');
402
+	}
403
+
404
+
405
+	/**
406
+	 * Gets image specs and formats them for the display in the API,
407
+	 * according to the image size requested
408
+	 *
409
+	 * @param array  $wpdb_row
410
+	 * @param string $image_size one of these: thumbnail, medium, medium_large, large, post-thumbnail, full
411
+	 * @return array|false if no such image exists. If array it will have keys 'url', 'width', 'height' and 'original'
412
+	 * @throws EE_Error
413
+	 */
414
+	protected function calculateImageData($wpdb_row, $image_size)
415
+	{
416
+		if (! Event::wpdbRowHasEventId($wpdb_row)) {
417
+			throw new EE_Error(
418
+				sprintf(
419
+					esc_html__(
420
+					// @codingStandardsIgnoreStart
421
+						'Cannot calculate image because the database row %1$s does not have an entry for "Event_CPT.ID"',
422
+						// @codingStandardsIgnoreEnd
423
+						'event_espresso'
424
+					),
425
+					print_r($wpdb_row, true)
426
+				)
427
+			);
428
+		}
429
+		$EVT_ID = $wpdb_row['Event_CPT.ID'];
430
+		$attachment_id = get_post_thumbnail_id($EVT_ID);
431
+		$data = wp_get_attachment_image_src($attachment_id, $image_size);
432
+		if (! $data) {
433
+			return null;
434
+		}
435
+		$generated = true;
436
+		if (isset($data[3])) {
437
+			$generated = $data[3];
438
+		}
439
+		return array(
440
+			'url'       => $data[0],
441
+			'width'     => $data[1],
442
+			'height'    => $data[2],
443
+			'generated' => $generated,
444
+		);
445
+	}
446
+
447
+
448
+	/**
449
+	 * Returns true if the array of data contains 'Event_CPT.ID'. False otherwise
450
+	 *
451
+	 * @param array $wpdb_row
452
+	 * @return bool
453
+	 */
454
+	protected function wpdbRowHasEventId($wpdb_row)
455
+	{
456
+		return (is_array($wpdb_row) && isset($wpdb_row['Event_CPT.ID']) && absint($wpdb_row['Event_CPT.ID']));
457
+	}
458
+
459
+
460
+	/**
461
+	 * Provides an array for all the calculations possible that outlines a json schema for those calculations.
462
+	 * Array is indexed by calculation (snake case) and value is the schema for that calculation.
463
+	 *
464
+	 * @since 4.9.68.p
465
+	 * @return array
466
+	 */
467
+	public function schemaForCalculations()
468
+	{
469
+		$image_object_properties = array(
470
+			'url'       => array(
471
+				'type' => 'string',
472
+			),
473
+			'width'     => array(
474
+				'type' => 'number',
475
+			),
476
+			'height'    => array(
477
+				'type' => 'number',
478
+			),
479
+			'generated' => array(
480
+				'type' => 'boolean',
481
+			),
482
+		);
483
+		return array(
484
+			'optimum_sales_at_start'          => array(
485
+				'description' => esc_html__(
486
+					'The total spaces on the event (not subtracting sales, but taking sales into account; so this is the optimum sales that CAN still be achieved.',
487
+					'event_espresso'
488
+				),
489
+				'type'        => 'number',
490
+				'protected' => true,
491
+			),
492
+			'optimum_sales_now'               => array(
493
+				'description' => esc_html__(
494
+					'The total spaces on the event (ignoring all sales; so this is the optimum sales that could have been achieved.',
495
+					'event_espresso'
496
+				),
497
+				'type'        => 'number',
498
+				'protected' => true,
499
+			),
500
+			'spaces_remaining'                => array(
501
+				'description' => esc_html__(
502
+					'The optimum_sales_number result, minus total sales so far.',
503
+					'event_espresso'
504
+				),
505
+				'type'        => 'number',
506
+				'protected' => true,
507
+			),
508
+			'spots_taken'                     => array(
509
+				'description' => esc_html__(
510
+					'The number of approved registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)',
511
+					'event_espresso'
512
+				),
513
+				'type'        => 'number',
514
+				'protected' => true,
515
+			),
516
+			'spots_taken_pending_payment'     => array(
517
+				'description' => esc_html__(
518
+					'The number of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)',
519
+					'event_espresso'
520
+				),
521
+				'type'        => 'number',
522
+				'protected' => true,
523
+			),
524
+			'registrations_checked_in_count'  => array(
525
+				'description' => esc_html__(
526
+					'The count of all the registrations who have checked into one of this event\'s datetimes.',
527
+					'event_espresso'
528
+				),
529
+				'type'        => 'number',
530
+				'protected' => true,
531
+			),
532
+			'registrations_checked_out_count' => array(
533
+				'description' => esc_html__(
534
+					'The count of all registrations who have checked out of one of this event\'s datetimes.',
535
+					'event_espresso'
536
+				),
537
+				'type'        => 'number',
538
+				'protected' => true,
539
+			),
540
+			'image_thumbnail'                 => array(
541
+				'description'          => esc_html__(
542
+					'The thumbnail image data.',
543
+					'event_espresso'
544
+				),
545
+				'type'                 => 'object',
546
+				'properties'           => $image_object_properties,
547
+				'additionalProperties' => false,
548
+			),
549
+			'image_medium'                    => array(
550
+				'description'          => esc_html__(
551
+					'The medium image data.',
552
+					'event_espresso'
553
+				),
554
+				'type'                 => 'object',
555
+				'properties'           => $image_object_properties,
556
+				'additionalProperties' => false,
557
+			),
558
+			'image_medium_large'              => array(
559
+				'description'          => esc_html__(
560
+					'The medium-large image data.',
561
+					'event_espresso'
562
+				),
563
+				'type'                 => 'object',
564
+				'properties'           => $image_object_properties,
565
+				'additionalProperties' => false,
566
+			),
567
+			'image_large'                     => array(
568
+				'description'          => esc_html__(
569
+					'The large image data.',
570
+					'event_espresso'
571
+				),
572
+				'type'                 => 'object',
573
+				'properties'           => $image_object_properties,
574
+				'additionalProperties' => false,
575
+			),
576
+			'image_post_thumbnail'            => array(
577
+				'description'          => esc_html__(
578
+					'The post-thumbnail image data.',
579
+					'event_espresso'
580
+				),
581
+				'type'                 => 'object',
582
+				'properties'           => $image_object_properties,
583
+				'additionalProperties' => false,
584
+			),
585
+			'image_full'                      => array(
586
+				'description'          => esc_html__(
587
+					'The full size image data',
588
+					'event_espresso'
589
+				),
590
+				'type'                 => 'object',
591
+				'properties'           => $image_object_properties,
592
+				'additionalProperties' => false,
593
+			),
594
+		);
595
+	}
596 596
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
      */
176 176
     public function spotsTaken($wpdb_row, $request, $controller)
177 177
     {
178
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
178
+        if ( ! Event::wpdbRowHasEventId($wpdb_row)) {
179 179
             throw new EE_Error(
180 180
                 sprintf(
181 181
                     esc_html__(
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
      */
218 218
     public function spotsTakenPendingPayment($wpdb_row, $request, $controller)
219 219
     {
220
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
220
+        if ( ! Event::wpdbRowHasEventId($wpdb_row)) {
221 221
             throw new EE_Error(
222 222
                 sprintf(
223 223
                     esc_html__(
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
      */
261 261
     public function registrationsCheckedInCount($wpdb_row, $request, $controller)
262 262
     {
263
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
263
+        if ( ! Event::wpdbRowHasEventId($wpdb_row)) {
264 264
             throw new EE_Error(
265 265
                 sprintf(
266 266
                     esc_html__(
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
      */
295 295
     public function registrationsCheckedOutCount($wpdb_row, $request, $controller)
296 296
     {
297
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
297
+        if ( ! Event::wpdbRowHasEventId($wpdb_row)) {
298 298
             throw new EE_Error(
299 299
                 sprintf(
300 300
                     esc_html__(
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
      */
414 414
     protected function calculateImageData($wpdb_row, $image_size)
415 415
     {
416
-        if (! Event::wpdbRowHasEventId($wpdb_row)) {
416
+        if ( ! Event::wpdbRowHasEventId($wpdb_row)) {
417 417
             throw new EE_Error(
418 418
                 sprintf(
419 419
                     esc_html__(
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
         $EVT_ID = $wpdb_row['Event_CPT.ID'];
430 430
         $attachment_id = get_post_thumbnail_id($EVT_ID);
431 431
         $data = wp_get_attachment_image_src($attachment_id, $image_size);
432
-        if (! $data) {
432
+        if ( ! $data) {
433 433
             return null;
434 434
         }
435 435
         $generated = true;
Please login to merge, or discard this patch.
line_item_display/EE_Receipt_Line_Item_Display_Strategy.strategy.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -15,88 +15,88 @@
 block discarded – undo
15 15
  * ------------------------------------------------------------------------
16 16
  */
17 17
  /**
18
- *
19
- * Class EE_Receipt_Line_Item_Display_Strategy
20
- *
21
- * Description
22
- *
23
- * @package         Event Espresso
24
- * @subpackage    core
25
- * @author              Brent Christensen
26
- *
27
- *
28
- */
18
+  *
19
+  * Class EE_Receipt_Line_Item_Display_Strategy
20
+  *
21
+  * Description
22
+  *
23
+  * @package         Event Espresso
24
+  * @subpackage    core
25
+  * @author              Brent Christensen
26
+  *
27
+  *
28
+  */
29 29
 
30 30
 class EE_Receipt_Line_Item_Display_Strategy implements EEI_Line_Item_Display
31 31
 {
32 32
 
33
-    /**
34
-     * @param EE_Line_Item $line_item
35
-     * @param array        $options
36
-     * @return mixed
37
-     */
38
-    public function display_line_item(EE_Line_Item $line_item, $options = array())
39
-    {
33
+	/**
34
+	 * @param EE_Line_Item $line_item
35
+	 * @param array        $options
36
+	 * @return mixed
37
+	 */
38
+	public function display_line_item(EE_Line_Item $line_item, $options = array())
39
+	{
40 40
 
41
-        $html = '';
42
-        // set some default options and merge with incoming
43
-        $default_options = array(
44
-            'show_desc' => true,
45
-            'odd' => false
46
-        );
47
-        $options = array_merge($default_options, (array) $options);
48
-        switch ($line_item->type()) {
49
-            case EEM_Line_Item::type_total:
50
-                // loop thru children
51
-                foreach ($line_item->children() as $child_line_item) {
52
-                    // recursively feed children back into this method
41
+		$html = '';
42
+		// set some default options and merge with incoming
43
+		$default_options = array(
44
+			'show_desc' => true,
45
+			'odd' => false
46
+		);
47
+		$options = array_merge($default_options, (array) $options);
48
+		switch ($line_item->type()) {
49
+			case EEM_Line_Item::type_total:
50
+				// loop thru children
51
+				foreach ($line_item->children() as $child_line_item) {
52
+					// recursively feed children back into this method
53 53
 //                  $html .= $this->display_line_item( $child_line_item, $options );
54
-                }
54
+				}
55 55
 //              $html .= $this->_separator_row( $options );
56 56
 //              $html .= $this->_total_row( $line_item, esc_html__('Total', 'event_espresso'), $options );
57
-                break;
57
+				break;
58 58
 
59 59
 
60
-            case EEM_Line_Item::type_sub_total:
61
-                // loop thru children
62
-                foreach ($line_item->children() as $child_line_item) {
63
-                    // recursively feed children back into this method
60
+			case EEM_Line_Item::type_sub_total:
61
+				// loop thru children
62
+				foreach ($line_item->children() as $child_line_item) {
63
+					// recursively feed children back into this method
64 64
 //                  $html .= $this->display_line_item( $child_line_item, $options );
65
-                }
65
+				}
66 66
 //              $html .= $this->_total_row( $line_item, esc_html__('Sub-Total', 'event_espresso'), $options );
67
-                break;
67
+				break;
68 68
 
69 69
 
70
-            case EEM_Line_Item::type_tax_sub_total:
71
-                // loop thru children
72
-                foreach ($line_item->children() as $child_line_item) {
73
-                    // recursively feed children back into this method
70
+			case EEM_Line_Item::type_tax_sub_total:
71
+				// loop thru children
72
+				foreach ($line_item->children() as $child_line_item) {
73
+					// recursively feed children back into this method
74 74
 //                  $html .= $this->display_line_item( $child_line_item, $options );
75
-                }
75
+				}
76 76
 //              $html .= $this->_total_row( $line_item, esc_html__('Tax Total', 'event_espresso'), $options );
77
-                break;
77
+				break;
78 78
 
79 79
 
80
-            case EEM_Line_Item::type_line_item:
81
-                // item row
80
+			case EEM_Line_Item::type_line_item:
81
+				// item row
82 82
 //              $html .= $this->_item_row( $line_item, $options );
83
-                // got any kids?
84
-                foreach ($line_item->children() as $child_line_item) {
83
+				// got any kids?
84
+				foreach ($line_item->children() as $child_line_item) {
85 85
 //                  $this->display_line_item( $child_line_item, $options );
86
-                }
87
-                break;
86
+				}
87
+				break;
88 88
 
89 89
 
90
-            case EEM_Line_Item::type_sub_line_item:
90
+			case EEM_Line_Item::type_sub_line_item:
91 91
 //              $html .= $this->_sub_item_row( $line_item, $options );
92
-                break;
92
+				break;
93 93
 
94 94
 
95
-            case EEM_Line_Item::type_tax:
95
+			case EEM_Line_Item::type_tax:
96 96
 //              $html .= $this->_tax_row( $line_item, $options );
97
-                break;
98
-        }
97
+				break;
98
+		}
99 99
 
100
-        return $html;
101
-    }
100
+		return $html;
101
+	}
102 102
 }
Please login to merge, or discard this patch.
line_item_display/EE_Admin_Table_Line_Item_Display_Strategy.strategy.php 2 patches
Indentation   +328 added lines, -328 removed lines patch added patch discarded remove patch
@@ -15,332 +15,332 @@
 block discarded – undo
15 15
 {
16 16
 
17 17
 
18
-    /**
19
-     * whether to display the taxes row or not
20
-     * @type bool $_show_taxes
21
-     */
22
-    protected $_show_taxes = false;
23
-
24
-    /**
25
-     * html for any tax rows
26
-     * @type string $_show_taxes
27
-     */
28
-    protected $_taxes_html = '';
29
-
30
-
31
-    /**
32
-     * total amount including tax we can bill for at this time
33
-     * @type float $_grand_total
34
-     */
35
-    protected $_grand_total = 0.00;
36
-
37
-
38
-
39
-    /**
40
-     * @return float
41
-     */
42
-    public function grand_total()
43
-    {
44
-        return $this->_grand_total;
45
-    }
46
-
47
-
48
-
49
-    /**
50
-     * This is used to output a single
51
-     * @param EE_Line_Item $line_item
52
-     * @param array        $options
53
-     * @return mixed
54
-     */
55
-    public function display_line_item(EE_Line_Item $line_item, $options = array())
56
-    {
57
-
58
-        $html = '';
59
-        // set some default options and merge with incoming
60
-        $default_options = array(
61
-            'odd' => true,
62
-            'use_table_wrapper' => true,
63
-            'table_css_class' => 'admin-primary-mbox-tbl',
64
-            'taxes_tr_css_class' => 'admin-primary-mbox-taxes-tr',
65
-            'total_tr_css_class' => 'admin-primary-mbox-total-tr'
66
-        );
67
-        $options = array_merge($default_options, (array) $options);
68
-
69
-        switch ($line_item->type()) {
70
-            case EEM_Line_Item::type_line_item:
71
-                // item row
72
-                $html .= $this->_item_row($line_item, $options);
73
-                break;
74
-
75
-            case EEM_Line_Item::type_sub_line_item:
76
-                $html .= $this->_sub_item_row($line_item, $options);
77
-                break;
78
-
79
-            case EEM_Line_Item::type_sub_total:
80
-                if ($line_item->quantity() === 0) {
81
-                    return $html;
82
-                }
83
-                // loop through children
84
-                $child_line_items = $line_item->children();
85
-                // loop through children
86
-                foreach ($child_line_items as $child_line_item) {
87
-                    // recursively feed children back into this method
88
-                    $html .= $this->display_line_item($child_line_item, $options);
89
-                }
90
-                $html .= $this->_sub_total_row($line_item, $options);
91
-                break;
92
-
93
-            case EEM_Line_Item::type_tax:
94
-                if ($this->_show_taxes) {
95
-                    $this->_taxes_html .= $this->_tax_row($line_item, $options);
96
-                }
97
-                break;
98
-
99
-            case EEM_Line_Item::type_tax_sub_total:
100
-                foreach ($line_item->children() as $child_line_item) {
101
-                    if ($child_line_item->type() == EEM_Line_Item::type_tax) {
102
-                        $this->display_line_item($child_line_item, $options);
103
-                    }
104
-                }
105
-                break;
106
-
107
-            case EEM_Line_Item::type_total:
108
-                // determine whether to display taxes or not
109
-                $this->_show_taxes = $line_item->get_total_tax() > 0 ? true : false;
110
-                // get all child line items
111
-                $children = $line_item->children();
112
-
113
-                // loop thru all non-tax child line items
114
-                foreach ($children as $child_line_item) {
115
-                        $html .= $this->display_line_item($child_line_item, $options);
116
-                }
117
-
118
-                $html .= $this->_taxes_html;
119
-                $html .= $this->_total_row($line_item, $options);
120
-                if ($options['use_table_wrapper']) {
121
-                    $html = $this->_table_header($options) . $html . $this->_table_footer($options);
122
-                }
123
-                break;
124
-        }
125
-
126
-        return $html;
127
-    }
128
-
129
-
130
-
131
-    /**
132
-     * Table header for display.
133
-     * @since   4.8
134
-     * @param array $options
135
-     * @return string
136
-     */
137
-    protected function _table_header($options)
138
-    {
139
-        $html = EEH_HTML::table('', '', $options['table_css_class']);
140
-        $html .= EEH_HTML::thead();
141
-        $html .= EEH_HTML::tr();
142
-        $html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left');
143
-        $html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left');
144
-        $html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr');
145
-        $html .= EEH_HTML::th(esc_html__('Qty', 'event_espresso'), '', 'jst-cntr');
146
-        $html .= EEH_HTML::th(esc_html__('Line Total', 'event_espresso'), '', 'jst-cntr');
147
-        $html .= EEH_HTML::tbody();
148
-        return $html;
149
-    }
150
-
151
-
152
-    /**
153
-     * Table footer for display
154
-     * @since 4.8
155
-     * @param array $options array of options for the table.
156
-     * @return string
157
-     */
158
-    protected function _table_footer($options)
159
-    {
160
-        return EEH_HTML::tbodyx() .  EEH_HTML::tablex();
161
-    }
162
-
163
-
164
-
165
-    /**
166
-     *    _item_row
167
-     *
168
-     * @param EE_Line_Item $line_item
169
-     * @param array        $options
170
-     * @return mixed
171
-     */
172
-    protected function _item_row(EE_Line_Item $line_item, $options = array())
173
-    {
174
-        $line_item_related_object = $line_item->get_object();
175
-        $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->get_object() : null;
176
-        // start of row
177
-        $row_class = $options['odd'] ? 'item odd' : 'item';
178
-        $html = EEH_HTML::tr('', '', $row_class);
179
-
180
-
181
-        // Name Column
182
-        $name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : '';
183
-
184
-        // related object scope.
185
-        $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object ? $parent_line_item_related_object->name() : '';
186
-        $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->name() : $parent_related_object_name;
187
-        $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links ? $parent_line_item_related_object->get_admin_details_link() : '';
188
-
189
-
190
-        $name_html = $line_item_related_object instanceof EEI_Line_Item_Object ? $line_item_related_object->name() : $line_item->name();
191
-        $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' : $name_html;
192
-        $name_html .= $line_item->is_taxable() ? ' *' : '';
193
-        // maybe preface with icon?
194
-        $name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon() . $name_html : $name_html;
195
-        $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>';
196
-        $name_html .=  sprintf(
197
-            _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'),
198
-            '<span class="ee-line-item-related-parent-object">',
199
-            $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->OBJ_type_i18n() : esc_html__('Item:', 'event_espresso'),
200
-            $parent_related_object_link ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' : $parent_related_object_name,
201
-            '</span>'
202
-        );
203
-
204
-        $name_html = apply_filters(
205
-            'FHEE__EE_Admin_Table_Line_Item_Display_Strategy___item_row__name_html',
206
-            $name_html,
207
-            $line_item,
208
-            $options
209
-        );
210
-
211
-        $html .= EEH_HTML::td($name_html, '', 'jst-left');
212
-        // Type Column
213
-        $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : '';
214
-        $type_html .= $this->_get_cancellations($line_item);
215
-        $type_html .= $line_item->OBJ_type() ? '<br />' : '';
216
-        $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : '';
217
-        $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : '';
218
-        $html .= EEH_HTML::td($type_html, '', 'jst-left');
219
-
220
-
221
-        // Amount Column
222
-        if ($line_item->is_percent()) {
223
-            $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght');
224
-        } else {
225
-            $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght');
226
-        }
227
-
228
-        // QTY column
229
-        $html .= EEH_HTML::td($line_item->quantity(), '', 'jst-rght');
230
-
231
-        // total column
232
-        $html .= EEH_HTML::td(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
233
-
234
-        // finish things off and return
235
-        $html .= EEH_HTML::trx();
236
-        return $html;
237
-    }
238
-
239
-
240
-
241
-    /**
242
-     *    _get_cancellations
243
-     *
244
-     * @param EE_Line_Item $line_item
245
-     * @return string
246
-     */
247
-    protected function _get_cancellations(EE_Line_Item $line_item)
248
-    {
249
-        $html = '';
250
-        $cancellations = $line_item->get_cancellations();
251
-        $cancellation = reset($cancellations);
252
-        // \EEH_Debug_Tools::printr( $cancellation, '$cancellation', __FILE__, __LINE__ );
253
-        if ($cancellation instanceof EE_Line_Item) {
254
-            $html .= ' <span class="ee-line-item-id">';
255
-            $html .= sprintf(
256
-                _n(
257
-                    '(%1$s Cancellation)',
258
-                    '(%1$s Cancellations)',
259
-                    $cancellation->quantity(),
260
-                    'event_espresso'
261
-                ),
262
-                $cancellation->quantity()
263
-            );
264
-            $html .= '</span>';
265
-        }
266
-        return $html;
267
-    }
268
-
269
-
270
-
271
-    /**
272
-     *  _sub_item_row
273
-     *
274
-     * @param EE_Line_Item $line_item
275
-     * @param array        $options
276
-     * @return mixed
277
-     */
278
-    protected function _sub_item_row(EE_Line_Item $line_item, $options = array())
279
-    {
280
-        // for now we're not showing sub-items
281
-        return '';
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     *  _tax_row
288
-     *
289
-     * @param EE_Line_Item $line_item
290
-     * @param array        $options
291
-     * @return mixed
292
-     */
293
-    protected function _tax_row(EE_Line_Item $line_item, $options = array())
294
-    {
295
-        // start of row
296
-        $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr');
297
-        // name th
298
-        $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="4"');
299
-        // total th
300
-        $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
301
-        // end of row
302
-        $html .= EEH_HTML::trx();
303
-        return $html;
304
-    }
305
-
306
-
307
-
308
-
309
-    /**
310
-     *  _total_row
311
-     *
312
-     * @param EE_Line_Item $line_item
313
-     * @param string       $text
314
-     * @param array        $options
315
-     * @return mixed
316
-     */
317
-    protected function _sub_total_row(EE_Line_Item $line_item, $text = '', $options = array())
318
-    {
319
-        // currently not showing subtotal row
320
-        return '';
321
-    }
322
-
323
-
324
-
325
-    /**
326
-     *  _total_row
327
-     *
328
-     * @param EE_Line_Item $line_item
329
-     * @param array        $options
330
-     * @return mixed
331
-     */
332
-    protected function _total_row(EE_Line_Item $line_item, $options = array())
333
-    {
334
-        // start of row
335
-        $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr');
336
-        // Total th label
337
-        $total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')');
338
-        $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="4"');
339
-        // total th
340
-
341
-        $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
342
-        // end of row
343
-        $html .= EEH_HTML::trx();
344
-        return $html;
345
-    }
18
+	/**
19
+	 * whether to display the taxes row or not
20
+	 * @type bool $_show_taxes
21
+	 */
22
+	protected $_show_taxes = false;
23
+
24
+	/**
25
+	 * html for any tax rows
26
+	 * @type string $_show_taxes
27
+	 */
28
+	protected $_taxes_html = '';
29
+
30
+
31
+	/**
32
+	 * total amount including tax we can bill for at this time
33
+	 * @type float $_grand_total
34
+	 */
35
+	protected $_grand_total = 0.00;
36
+
37
+
38
+
39
+	/**
40
+	 * @return float
41
+	 */
42
+	public function grand_total()
43
+	{
44
+		return $this->_grand_total;
45
+	}
46
+
47
+
48
+
49
+	/**
50
+	 * This is used to output a single
51
+	 * @param EE_Line_Item $line_item
52
+	 * @param array        $options
53
+	 * @return mixed
54
+	 */
55
+	public function display_line_item(EE_Line_Item $line_item, $options = array())
56
+	{
57
+
58
+		$html = '';
59
+		// set some default options and merge with incoming
60
+		$default_options = array(
61
+			'odd' => true,
62
+			'use_table_wrapper' => true,
63
+			'table_css_class' => 'admin-primary-mbox-tbl',
64
+			'taxes_tr_css_class' => 'admin-primary-mbox-taxes-tr',
65
+			'total_tr_css_class' => 'admin-primary-mbox-total-tr'
66
+		);
67
+		$options = array_merge($default_options, (array) $options);
68
+
69
+		switch ($line_item->type()) {
70
+			case EEM_Line_Item::type_line_item:
71
+				// item row
72
+				$html .= $this->_item_row($line_item, $options);
73
+				break;
74
+
75
+			case EEM_Line_Item::type_sub_line_item:
76
+				$html .= $this->_sub_item_row($line_item, $options);
77
+				break;
78
+
79
+			case EEM_Line_Item::type_sub_total:
80
+				if ($line_item->quantity() === 0) {
81
+					return $html;
82
+				}
83
+				// loop through children
84
+				$child_line_items = $line_item->children();
85
+				// loop through children
86
+				foreach ($child_line_items as $child_line_item) {
87
+					// recursively feed children back into this method
88
+					$html .= $this->display_line_item($child_line_item, $options);
89
+				}
90
+				$html .= $this->_sub_total_row($line_item, $options);
91
+				break;
92
+
93
+			case EEM_Line_Item::type_tax:
94
+				if ($this->_show_taxes) {
95
+					$this->_taxes_html .= $this->_tax_row($line_item, $options);
96
+				}
97
+				break;
98
+
99
+			case EEM_Line_Item::type_tax_sub_total:
100
+				foreach ($line_item->children() as $child_line_item) {
101
+					if ($child_line_item->type() == EEM_Line_Item::type_tax) {
102
+						$this->display_line_item($child_line_item, $options);
103
+					}
104
+				}
105
+				break;
106
+
107
+			case EEM_Line_Item::type_total:
108
+				// determine whether to display taxes or not
109
+				$this->_show_taxes = $line_item->get_total_tax() > 0 ? true : false;
110
+				// get all child line items
111
+				$children = $line_item->children();
112
+
113
+				// loop thru all non-tax child line items
114
+				foreach ($children as $child_line_item) {
115
+						$html .= $this->display_line_item($child_line_item, $options);
116
+				}
117
+
118
+				$html .= $this->_taxes_html;
119
+				$html .= $this->_total_row($line_item, $options);
120
+				if ($options['use_table_wrapper']) {
121
+					$html = $this->_table_header($options) . $html . $this->_table_footer($options);
122
+				}
123
+				break;
124
+		}
125
+
126
+		return $html;
127
+	}
128
+
129
+
130
+
131
+	/**
132
+	 * Table header for display.
133
+	 * @since   4.8
134
+	 * @param array $options
135
+	 * @return string
136
+	 */
137
+	protected function _table_header($options)
138
+	{
139
+		$html = EEH_HTML::table('', '', $options['table_css_class']);
140
+		$html .= EEH_HTML::thead();
141
+		$html .= EEH_HTML::tr();
142
+		$html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left');
143
+		$html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left');
144
+		$html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr');
145
+		$html .= EEH_HTML::th(esc_html__('Qty', 'event_espresso'), '', 'jst-cntr');
146
+		$html .= EEH_HTML::th(esc_html__('Line Total', 'event_espresso'), '', 'jst-cntr');
147
+		$html .= EEH_HTML::tbody();
148
+		return $html;
149
+	}
150
+
151
+
152
+	/**
153
+	 * Table footer for display
154
+	 * @since 4.8
155
+	 * @param array $options array of options for the table.
156
+	 * @return string
157
+	 */
158
+	protected function _table_footer($options)
159
+	{
160
+		return EEH_HTML::tbodyx() .  EEH_HTML::tablex();
161
+	}
162
+
163
+
164
+
165
+	/**
166
+	 *    _item_row
167
+	 *
168
+	 * @param EE_Line_Item $line_item
169
+	 * @param array        $options
170
+	 * @return mixed
171
+	 */
172
+	protected function _item_row(EE_Line_Item $line_item, $options = array())
173
+	{
174
+		$line_item_related_object = $line_item->get_object();
175
+		$parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->get_object() : null;
176
+		// start of row
177
+		$row_class = $options['odd'] ? 'item odd' : 'item';
178
+		$html = EEH_HTML::tr('', '', $row_class);
179
+
180
+
181
+		// Name Column
182
+		$name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : '';
183
+
184
+		// related object scope.
185
+		$parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object ? $parent_line_item_related_object->name() : '';
186
+		$parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->name() : $parent_related_object_name;
187
+		$parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links ? $parent_line_item_related_object->get_admin_details_link() : '';
188
+
189
+
190
+		$name_html = $line_item_related_object instanceof EEI_Line_Item_Object ? $line_item_related_object->name() : $line_item->name();
191
+		$name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' : $name_html;
192
+		$name_html .= $line_item->is_taxable() ? ' *' : '';
193
+		// maybe preface with icon?
194
+		$name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon() . $name_html : $name_html;
195
+		$name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>';
196
+		$name_html .=  sprintf(
197
+			_x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'),
198
+			'<span class="ee-line-item-related-parent-object">',
199
+			$line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->OBJ_type_i18n() : esc_html__('Item:', 'event_espresso'),
200
+			$parent_related_object_link ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' : $parent_related_object_name,
201
+			'</span>'
202
+		);
203
+
204
+		$name_html = apply_filters(
205
+			'FHEE__EE_Admin_Table_Line_Item_Display_Strategy___item_row__name_html',
206
+			$name_html,
207
+			$line_item,
208
+			$options
209
+		);
210
+
211
+		$html .= EEH_HTML::td($name_html, '', 'jst-left');
212
+		// Type Column
213
+		$type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : '';
214
+		$type_html .= $this->_get_cancellations($line_item);
215
+		$type_html .= $line_item->OBJ_type() ? '<br />' : '';
216
+		$code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : '';
217
+		$type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : '';
218
+		$html .= EEH_HTML::td($type_html, '', 'jst-left');
219
+
220
+
221
+		// Amount Column
222
+		if ($line_item->is_percent()) {
223
+			$html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght');
224
+		} else {
225
+			$html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght');
226
+		}
227
+
228
+		// QTY column
229
+		$html .= EEH_HTML::td($line_item->quantity(), '', 'jst-rght');
230
+
231
+		// total column
232
+		$html .= EEH_HTML::td(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
233
+
234
+		// finish things off and return
235
+		$html .= EEH_HTML::trx();
236
+		return $html;
237
+	}
238
+
239
+
240
+
241
+	/**
242
+	 *    _get_cancellations
243
+	 *
244
+	 * @param EE_Line_Item $line_item
245
+	 * @return string
246
+	 */
247
+	protected function _get_cancellations(EE_Line_Item $line_item)
248
+	{
249
+		$html = '';
250
+		$cancellations = $line_item->get_cancellations();
251
+		$cancellation = reset($cancellations);
252
+		// \EEH_Debug_Tools::printr( $cancellation, '$cancellation', __FILE__, __LINE__ );
253
+		if ($cancellation instanceof EE_Line_Item) {
254
+			$html .= ' <span class="ee-line-item-id">';
255
+			$html .= sprintf(
256
+				_n(
257
+					'(%1$s Cancellation)',
258
+					'(%1$s Cancellations)',
259
+					$cancellation->quantity(),
260
+					'event_espresso'
261
+				),
262
+				$cancellation->quantity()
263
+			);
264
+			$html .= '</span>';
265
+		}
266
+		return $html;
267
+	}
268
+
269
+
270
+
271
+	/**
272
+	 *  _sub_item_row
273
+	 *
274
+	 * @param EE_Line_Item $line_item
275
+	 * @param array        $options
276
+	 * @return mixed
277
+	 */
278
+	protected function _sub_item_row(EE_Line_Item $line_item, $options = array())
279
+	{
280
+		// for now we're not showing sub-items
281
+		return '';
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 *  _tax_row
288
+	 *
289
+	 * @param EE_Line_Item $line_item
290
+	 * @param array        $options
291
+	 * @return mixed
292
+	 */
293
+	protected function _tax_row(EE_Line_Item $line_item, $options = array())
294
+	{
295
+		// start of row
296
+		$html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr');
297
+		// name th
298
+		$html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="4"');
299
+		// total th
300
+		$html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
301
+		// end of row
302
+		$html .= EEH_HTML::trx();
303
+		return $html;
304
+	}
305
+
306
+
307
+
308
+
309
+	/**
310
+	 *  _total_row
311
+	 *
312
+	 * @param EE_Line_Item $line_item
313
+	 * @param string       $text
314
+	 * @param array        $options
315
+	 * @return mixed
316
+	 */
317
+	protected function _sub_total_row(EE_Line_Item $line_item, $text = '', $options = array())
318
+	{
319
+		// currently not showing subtotal row
320
+		return '';
321
+	}
322
+
323
+
324
+
325
+	/**
326
+	 *  _total_row
327
+	 *
328
+	 * @param EE_Line_Item $line_item
329
+	 * @param array        $options
330
+	 * @return mixed
331
+	 */
332
+	protected function _total_row(EE_Line_Item $line_item, $options = array())
333
+	{
334
+		// start of row
335
+		$html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr');
336
+		// Total th label
337
+		$total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')');
338
+		$html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="4"');
339
+		// total th
340
+
341
+		$html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
342
+		// end of row
343
+		$html .= EEH_HTML::trx();
344
+		return $html;
345
+	}
346 346
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
                 $html .= $this->_taxes_html;
119 119
                 $html .= $this->_total_row($line_item, $options);
120 120
                 if ($options['use_table_wrapper']) {
121
-                    $html = $this->_table_header($options) . $html . $this->_table_footer($options);
121
+                    $html = $this->_table_header($options).$html.$this->_table_footer($options);
122 122
                 }
123 123
                 break;
124 124
         }
@@ -157,7 +157,7 @@  discard block
 block discarded – undo
157 157
      */
158 158
     protected function _table_footer($options)
159 159
     {
160
-        return EEH_HTML::tbodyx() .  EEH_HTML::tablex();
160
+        return EEH_HTML::tbodyx().EEH_HTML::tablex();
161 161
     }
162 162
 
163 163
 
@@ -188,16 +188,16 @@  discard block
 block discarded – undo
188 188
 
189 189
 
190 190
         $name_html = $line_item_related_object instanceof EEI_Line_Item_Object ? $line_item_related_object->name() : $line_item->name();
191
-        $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' : $name_html;
191
+        $name_html = $name_link ? '<a href="'.$name_link.'">'.$name_html.'</a>' : $name_html;
192 192
         $name_html .= $line_item->is_taxable() ? ' *' : '';
193 193
         // maybe preface with icon?
194
-        $name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon() . $name_html : $name_html;
195
-        $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>';
196
-        $name_html .=  sprintf(
194
+        $name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon().$name_html : $name_html;
195
+        $name_html = '<span class="ee-line-item-name linked">'.$name_html.'</span><br>';
196
+        $name_html .= sprintf(
197 197
             _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'),
198 198
             '<span class="ee-line-item-related-parent-object">',
199 199
             $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->OBJ_type_i18n() : esc_html__('Item:', 'event_espresso'),
200
-            $parent_related_object_link ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' : $parent_related_object_name,
200
+            $parent_related_object_link ? '<a href="'.$parent_related_object_link.'">'.$parent_related_object_name.'</a>' : $parent_related_object_name,
201 201
             '</span>'
202 202
         );
203 203
 
@@ -214,13 +214,13 @@  discard block
 block discarded – undo
214 214
         $type_html .= $this->_get_cancellations($line_item);
215 215
         $type_html .= $line_item->OBJ_type() ? '<br />' : '';
216 216
         $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : '';
217
-        $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : '';
217
+        $type_html .= ! empty($code) ? '<span class="ee-line-item-id">'.sprintf(esc_html__('Code: %s', 'event_espresso'), $code).'</span>' : '';
218 218
         $html .= EEH_HTML::td($type_html, '', 'jst-left');
219 219
 
220 220
 
221 221
         // Amount Column
222 222
         if ($line_item->is_percent()) {
223
-            $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght');
223
+            $html .= EEH_HTML::td($line_item->percent().'%', '', 'jst-rght');
224 224
         } else {
225 225
             $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght');
226 226
         }
@@ -295,7 +295,7 @@  discard block
 block discarded – undo
295 295
         // start of row
296 296
         $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr');
297 297
         // name th
298
-        $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="4"');
298
+        $html .= EEH_HTML::th($line_item->name().'('.$line_item->get_pretty('LIN_percent').'%)', '', 'jst-rght', '', ' colspan="4"');
299 299
         // total th
300 300
         $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
301 301
         // end of row
@@ -334,7 +334,7 @@  discard block
 block discarded – undo
334 334
         // start of row
335 335
         $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr');
336 336
         // Total th label
337
-        $total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')');
337
+        $total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '('.EE_Registry::instance()->CFG->currency->code.')');
338 338
         $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="4"');
339 339
         // total th
340 340
 
Please login to merge, or discard this patch.