Completed
Branch FET-10601-new-spco-hooks (b376fb)
by
unknown
115:33 queued 104:16
created
core/libraries/rest_api/controllers/model/Read.php 2 patches
Indentation   +1240 added lines, -1240 removed lines patch added patch discarded remove patch
@@ -9,7 +9,7 @@  discard block
 block discarded – undo
9 9
 use EE_Datetime_Field;
10 10
 
11 11
 if (! defined('EVENT_ESPRESSO_VERSION')) {
12
-    exit('No direct script access allowed');
12
+	exit('No direct script access allowed');
13 13
 }
14 14
 
15 15
 
@@ -27,1245 +27,1245 @@  discard block
 block discarded – undo
27 27
 
28 28
 
29 29
 
30
-    /**
31
-     * @var Calculated_Model_Fields
32
-     */
33
-    protected $_fields_calculator;
34
-
35
-
36
-
37
-    /**
38
-     * Read constructor.
39
-     */
40
-    public function __construct()
41
-    {
42
-        parent::__construct();
43
-        $this->_fields_calculator = new Calculated_Model_Fields();
44
-    }
45
-
46
-
47
-
48
-    /**
49
-     * Handles requests to get all (or a filtered subset) of entities for a particular model
50
-     *
51
-     * @param \WP_REST_Request $request
52
-     * @return \WP_REST_Response|\WP_Error
53
-     */
54
-    public static function handle_request_get_all(\WP_REST_Request $request)
55
-    {
56
-        $controller = new Read();
57
-        try {
58
-            $matches = $controller->parse_route(
59
-                $request->get_route(),
60
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)~',
61
-                array('version', 'model')
62
-            );
63
-            $controller->set_requested_version($matches['version']);
64
-            $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
65
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
66
-                return $controller->send_response(
67
-                    new \WP_Error(
68
-                        'endpoint_parsing_error',
69
-                        sprintf(
70
-                            __('There is no model for endpoint %s. Please contact event espresso support',
71
-                                'event_espresso'),
72
-                            $model_name_singular
73
-                        )
74
-                    )
75
-                );
76
-            }
77
-            return $controller->send_response(
78
-                $controller->get_entities_from_model(
79
-                    $controller->get_model_version_info()->load_model($model_name_singular),
80
-                    $request
81
-                )
82
-            );
83
-        } catch (\Exception $e) {
84
-            return $controller->send_response($e);
85
-        }
86
-    }
87
-
88
-
89
-
90
-    /**
91
-     * Prepares and returns schema for any OPTIONS request.
92
-     *
93
-     * @param string $model_name Something like `Event` or `Registration`
94
-     * @param string $version    The API endpoint version being used.
95
-     * @return array
96
-     */
97
-    public static function handle_schema_request($model_name, $version)
98
-    {
99
-        $controller = new Read();
100
-        try {
101
-            $controller->set_requested_version($version);
102
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name)) {
103
-                return array();
104
-            }
105
-            //get the model for this version
106
-            $model = $controller->get_model_version_info()->load_model($model_name);
107
-            $model_schema = new JsonModelSchema($model);
108
-            return $model_schema->getModelSchemaForRelations(
109
-                $controller->get_model_version_info()->relation_settings($model),
110
-                $controller->_customize_schema_for_rest_response(
111
-                    $model,
112
-                    $model_schema->getModelSchemaForFields(
113
-                        $controller->get_model_version_info()->fields_on_model_in_this_version($model),
114
-                        $model_schema->getInitialSchemaStructure()
115
-                    )
116
-                )
117
-            );
118
-        } catch (\Exception $e) {
119
-            return array();
120
-        }
121
-    }
122
-
123
-
124
-
125
-    /**
126
-     * This loops through each field in the given schema for the model and does the following:
127
-     * - add any extra fields that are REST API specific and related to existing fields.
128
-     * - transform default values into the correct format for a REST API response.
129
-     *
130
-     * @param \EEM_Base $model
131
-     * @param array     $schema
132
-     * @return array  The final schema.
133
-     */
134
-    protected function _customize_schema_for_rest_response(\EEM_Base $model, array $schema)
135
-    {
136
-        foreach ($this->get_model_version_info()->fields_on_model_in_this_version($model) as $field_name => $field) {
137
-            $schema = $this->_translate_defaults_for_rest_response(
138
-                $field_name,
139
-                $field,
140
-                $this->_maybe_add_extra_fields_to_schema($field_name, $field, $schema)
141
-            );
142
-        }
143
-        return $schema;
144
-    }
145
-
146
-
147
-
148
-    /**
149
-     * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
150
-     * response.
151
-     *
152
-     * @param                      $field_name
153
-     * @param \EE_Model_Field_Base $field
154
-     * @param array                $schema
155
-     * @return array
156
-     */
157
-    protected function _translate_defaults_for_rest_response($field_name, \EE_Model_Field_Base $field, array $schema)
158
-    {
159
-        if (isset($schema['properties'][$field_name]['default'])) {
160
-            if (is_array($schema['properties'][$field_name]['default'])) {
161
-                foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) {
162
-                    if ($default_key === 'raw') {
163
-                        $schema['properties'][$field_name]['default'][$default_key] = Model_Data_Translator::prepare_field_value_for_json(
164
-                            $field,
165
-                            $default_value,
166
-                            $this->get_model_version_info()->requested_version()
167
-                        );
168
-                    }
169
-                }
170
-            } else {
171
-                $schema['properties'][$field_name]['default'] = Model_Data_Translator::prepare_field_value_for_json(
172
-                    $field,
173
-                    $schema['properties'][$field_name]['default'],
174
-                    $this->get_model_version_info()->requested_version()
175
-                );
176
-            }
177
-        }
178
-        return $schema;
179
-    }
180
-
181
-
182
-
183
-    /**
184
-     * Adds additional fields to the schema
185
-     * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
186
-     * needs to be added to the schema.
187
-     *
188
-     * @param                      $field_name
189
-     * @param \EE_Model_Field_Base $field
190
-     * @param array                $schema
191
-     * @return array
192
-     */
193
-    protected function _maybe_add_extra_fields_to_schema($field_name, \EE_Model_Field_Base $field, array $schema)
194
-    {
195
-        if ($field instanceof EE_Datetime_Field) {
196
-            $schema['properties'][$field_name . '_gmt'] = $field->getSchema();
197
-            //modify the description
198
-            $schema['properties'][$field_name . '_gmt']['description'] = sprintf(
199
-                esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
200
-                $field->get_nicename()
201
-            );
202
-        }
203
-        return $schema;
204
-    }
205
-
206
-
207
-
208
-    /**
209
-     * Used to figure out the route from the request when a `WP_REST_Request` object is not available
210
-     *
211
-     * @return string
212
-     */
213
-    protected function get_route_from_request()
214
-    {
215
-        if (isset($GLOBALS['wp'])
216
-            && $GLOBALS['wp'] instanceof \WP
217
-            && isset($GLOBALS['wp']->query_vars['rest_route'])
218
-        ) {
219
-            return $GLOBALS['wp']->query_vars['rest_route'];
220
-        } else {
221
-            return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';
222
-        }
223
-    }
224
-
225
-
226
-
227
-    /**
228
-     * Gets a single entity related to the model indicated in the path and its id
229
-     *
230
-     * @param \WP_REST_Request $request
231
-     * @return \WP_REST_Response|\WP_Error
232
-     */
233
-    public static function handle_request_get_one(\WP_REST_Request $request)
234
-    {
235
-        $controller = new Read();
236
-        try {
237
-            $matches = $controller->parse_route(
238
-                $request->get_route(),
239
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)~',
240
-                array('version', 'model', 'id'));
241
-            $controller->set_requested_version($matches['version']);
242
-            $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
243
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
244
-                return $controller->send_response(
245
-                    new \WP_Error(
246
-                        'endpoint_parsing_error',
247
-                        sprintf(
248
-                            __('There is no model for endpoint %s. Please contact event espresso support',
249
-                                'event_espresso'),
250
-                            $model_name_singular
251
-                        )
252
-                    )
253
-                );
254
-            }
255
-            return $controller->send_response(
256
-                $controller->get_entity_from_model(
257
-                    $controller->get_model_version_info()->load_model($model_name_singular),
258
-                    $request
259
-                )
260
-            );
261
-        } catch (\Exception $e) {
262
-            return $controller->send_response($e);
263
-        }
264
-    }
265
-
266
-
267
-
268
-    /**
269
-     * Gets all the related entities (or if its a belongs-to relation just the one)
270
-     * to the item with the given id
271
-     *
272
-     * @param \WP_REST_Request $request
273
-     * @return \WP_REST_Response|\WP_Error
274
-     */
275
-    public static function handle_request_get_related(\WP_REST_Request $request)
276
-    {
277
-        $controller = new Read();
278
-        try {
279
-            $matches = $controller->parse_route(
280
-                $request->get_route(),
281
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)/(.*)~',
282
-                array('version', 'model', 'id', 'related_model')
283
-            );
284
-            $controller->set_requested_version($matches['version']);
285
-            $main_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
286
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
287
-                return $controller->send_response(
288
-                    new \WP_Error(
289
-                        'endpoint_parsing_error',
290
-                        sprintf(
291
-                            __('There is no model for endpoint %s. Please contact event espresso support',
292
-                                'event_espresso'),
293
-                            $main_model_name_singular
294
-                        )
295
-                    )
296
-                );
297
-            }
298
-            $main_model = $controller->get_model_version_info()->load_model($main_model_name_singular);
299
-            //assume the related model name is plural and try to find the model's name
300
-            $related_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['related_model']);
301
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
302
-                //so the word didn't singularize well. Maybe that's just because it's a singular word?
303
-                $related_model_name_singular = \EEH_Inflector::humanize($matches['related_model']);
304
-            }
305
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
306
-                return $controller->send_response(
307
-                    new \WP_Error(
308
-                        'endpoint_parsing_error',
309
-                        sprintf(
310
-                            __('There is no model for endpoint %s. Please contact event espresso support',
311
-                                'event_espresso'),
312
-                            $related_model_name_singular
313
-                        )
314
-                    )
315
-                );
316
-            }
317
-            return $controller->send_response(
318
-                $controller->get_entities_from_relation(
319
-                    $request->get_param('id'),
320
-                    $main_model->related_settings_for($related_model_name_singular),
321
-                    $request
322
-                )
323
-            );
324
-        } catch (\Exception $e) {
325
-            return $controller->send_response($e);
326
-        }
327
-    }
328
-
329
-
330
-
331
-    /**
332
-     * Gets a collection for the given model and filters
333
-     *
334
-     * @param \EEM_Base        $model
335
-     * @param \WP_REST_Request $request
336
-     * @return array|\WP_Error
337
-     */
338
-    public function get_entities_from_model($model, $request)
339
-    {
340
-        $query_params = $this->create_model_query_params($model, $request->get_params());
341
-        if (! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
342
-            $model_name_plural = \EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
343
-            return new \WP_Error(
344
-                sprintf('rest_%s_cannot_list', $model_name_plural),
345
-                sprintf(
346
-                    __('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
347
-                    $model_name_plural,
348
-                    Capabilities::get_missing_permissions_string($model, $query_params['caps'])
349
-                ),
350
-                array('status' => 403)
351
-            );
352
-        }
353
-        if (! $request->get_header('no_rest_headers')) {
354
-            $this->_set_headers_from_query_params($model, $query_params);
355
-        }
356
-        /** @type array $results */
357
-        $results = $model->get_all_wpdb_results($query_params);
358
-        $nice_results = array();
359
-        foreach ($results as $result) {
360
-            $nice_results[] = $this->create_entity_from_wpdb_result(
361
-                $model,
362
-                $result,
363
-                $request
364
-            );
365
-        }
366
-        return $nice_results;
367
-    }
368
-
369
-
370
-
371
-    /**
372
-     * @param array                   $primary_model_query_params query params for finding the item from which
373
-     *                                                            relations will be based
374
-     * @param \EE_Model_Relation_Base $relation
375
-     * @param \WP_REST_Request        $request
376
-     * @return \WP_Error|array
377
-     */
378
-    protected function _get_entities_from_relation($primary_model_query_params, $relation, $request)
379
-    {
380
-        $context = $this->validate_context($request->get_param('caps'));
381
-        $model = $relation->get_this_model();
382
-        $related_model = $relation->get_other_model();
383
-        if (! isset($primary_model_query_params[0])) {
384
-            $primary_model_query_params[0] = array();
385
-        }
386
-        //check if they can access the 1st model object
387
-        $primary_model_query_params = array(
388
-            0       => $primary_model_query_params[0],
389
-            'limit' => 1,
390
-        );
391
-        if ($model instanceof \EEM_Soft_Delete_Base) {
392
-            $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($primary_model_query_params);
393
-        }
394
-        $restricted_query_params = $primary_model_query_params;
395
-        $restricted_query_params['caps'] = $context;
396
-        $this->_set_debug_info('main model query params', $restricted_query_params);
397
-        $this->_set_debug_info('missing caps', Capabilities::get_missing_permissions_string($related_model, $context));
398
-        if (
399
-        ! (
400
-            Capabilities::current_user_has_partial_access_to($related_model, $context)
401
-            && $model->exists($restricted_query_params)
402
-        )
403
-        ) {
404
-            if ($relation instanceof \EE_Belongs_To_Relation) {
405
-                $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
406
-            } else {
407
-                $related_model_name_maybe_plural = \EEH_Inflector::pluralize_and_lower($related_model->get_this_model_name());
408
-            }
409
-            return new \WP_Error(
410
-                sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
411
-                sprintf(
412
-                    __('Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
413
-                        'event_espresso'),
414
-                    $related_model_name_maybe_plural,
415
-                    $relation->get_this_model()->get_this_model_name(),
416
-                    implode(
417
-                        ',',
418
-                        array_keys(
419
-                            Capabilities::get_missing_permissions($related_model, $context)
420
-                        )
421
-                    )
422
-                ),
423
-                array('status' => 403)
424
-            );
425
-        }
426
-        $query_params = $this->create_model_query_params($relation->get_other_model(), $request->get_params());
427
-        foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
428
-            $query_params[0][$relation->get_this_model()->get_this_model_name()
429
-                             . '.'
430
-                             . $where_condition_key] = $where_condition_value;
431
-        }
432
-        $query_params['default_where_conditions'] = 'none';
433
-        $query_params['caps'] = $context;
434
-        if (! $request->get_header('no_rest_headers')) {
435
-            $this->_set_headers_from_query_params($relation->get_other_model(), $query_params);
436
-        }
437
-        /** @type array $results */
438
-        $results = $relation->get_other_model()->get_all_wpdb_results($query_params);
439
-        $nice_results = array();
440
-        foreach ($results as $result) {
441
-            $nice_result = $this->create_entity_from_wpdb_result(
442
-                $relation->get_other_model(),
443
-                $result,
444
-                $request
445
-            );
446
-            if ($relation instanceof \EE_HABTM_Relation) {
447
-                //put the unusual stuff (properties from the HABTM relation) first, and make sure
448
-                //if there are conflicts we prefer the properties from the main model
449
-                $join_model_result = $this->create_entity_from_wpdb_result(
450
-                    $relation->get_join_model(),
451
-                    $result,
452
-                    $request
453
-                );
454
-                $joined_result = array_merge($nice_result, $join_model_result);
455
-                //but keep the meta stuff from the main model
456
-                if (isset($nice_result['meta'])) {
457
-                    $joined_result['meta'] = $nice_result['meta'];
458
-                }
459
-                $nice_result = $joined_result;
460
-            }
461
-            $nice_results[] = $nice_result;
462
-        }
463
-        if ($relation instanceof \EE_Belongs_To_Relation) {
464
-            return array_shift($nice_results);
465
-        } else {
466
-            return $nice_results;
467
-        }
468
-    }
469
-
470
-
471
-
472
-    /**
473
-     * Gets the collection for given relation object
474
-     * The same as Read::get_entities_from_model(), except if the relation
475
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
476
-     * the join-model-object into the results
477
-     *
478
-     * @param string                  $id the ID of the thing we are fetching related stuff from
479
-     * @param \EE_Model_Relation_Base $relation
480
-     * @param \WP_REST_Request        $request
481
-     * @return array|\WP_Error
482
-     * @throws \EE_Error
483
-     */
484
-    public function get_entities_from_relation($id, $relation, $request)
485
-    {
486
-        if (! $relation->get_this_model()->has_primary_key_field()) {
487
-            throw new \EE_Error(
488
-                sprintf(
489
-                    __('Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
490
-                        'event_espresso'),
491
-                    $relation->get_this_model()->get_this_model_name()
492
-                )
493
-            );
494
-        }
495
-        return $this->_get_entities_from_relation(
496
-            array(
497
-                array(
498
-                    $relation->get_this_model()->primary_key_name() => $id,
499
-                ),
500
-            ),
501
-            $relation,
502
-            $request
503
-        );
504
-    }
505
-
506
-
507
-
508
-    /**
509
-     * Sets the headers that are based on the model and query params,
510
-     * like the total records. This should only be called on the original request
511
-     * from the client, not on subsequent internal
512
-     *
513
-     * @param \EEM_Base $model
514
-     * @param array     $query_params
515
-     * @return void
516
-     */
517
-    protected function _set_headers_from_query_params($model, $query_params)
518
-    {
519
-        $this->_set_debug_info('model query params', $query_params);
520
-        $this->_set_debug_info('missing caps',
521
-            Capabilities::get_missing_permissions_string($model, $query_params['caps']));
522
-        //normally the limit to a 2-part array, where the 2nd item is the limit
523
-        if (! isset($query_params['limit'])) {
524
-            $query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
525
-        }
526
-        if (is_array($query_params['limit'])) {
527
-            $limit_parts = $query_params['limit'];
528
-        } else {
529
-            $limit_parts = explode(',', $query_params['limit']);
530
-            if (count($limit_parts) == 1) {
531
-                $limit_parts = array(0, $limit_parts[0]);
532
-            }
533
-        }
534
-        //remove the group by and having parts of the query, as those will
535
-        //make the sql query return an array of values, instead of just a single value
536
-        unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
537
-        $count = $model->count($query_params, null, true);
538
-        $pages = $count / $limit_parts[1];
539
-        $this->_set_response_header('Total', $count, false);
540
-        $this->_set_response_header('PageSize', $limit_parts[1], false);
541
-        $this->_set_response_header('TotalPages', ceil($pages), false);
542
-    }
543
-
544
-
545
-
546
-    /**
547
-     * Changes database results into REST API entities
548
-     *
549
-     * @param \EEM_Base        $model
550
-     * @param array            $db_row     like results from $wpdb->get_results()
551
-     * @param \WP_REST_Request $rest_request
552
-     * @param string           $deprecated no longer used
553
-     * @return array ready for being converted into json for sending to client
554
-     */
555
-    public function create_entity_from_wpdb_result($model, $db_row, $rest_request, $deprecated = null)
556
-    {
557
-        if (! $rest_request instanceof \WP_REST_Request) {
558
-            //ok so this was called in the old style, where the 3rd arg was
559
-            //$include, and the 4th arg was $context
560
-            //now setup the request just to avoid fatal errors, although we won't be able
561
-            //to truly make use of it because it's kinda devoid of info
562
-            $rest_request = new \WP_REST_Request();
563
-            $rest_request->set_param('include', $rest_request);
564
-            $rest_request->set_param('caps', $deprecated);
565
-        }
566
-        if ($rest_request->get_param('caps') == null) {
567
-            $rest_request->set_param('caps', \EEM_Base::caps_read);
568
-        }
569
-        $entity_array = $this->_create_bare_entity_from_wpdb_results($model, $db_row);
570
-        $entity_array = $this->_add_extra_fields($model, $db_row, $entity_array);
571
-        $entity_array['_links'] = $this->_get_entity_links($model, $db_row, $entity_array);
572
-        $entity_array['_calculated_fields'] = $this->_get_entity_calculations($model, $db_row, $rest_request);
573
-        $entity_array = apply_filters('FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
574
-            $entity_array, $model, $rest_request->get_param('caps'), $rest_request, $this);
575
-        $entity_array = $this->_include_requested_models($model, $rest_request, $entity_array, $db_row);
576
-        $entity_array = apply_filters(
577
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
578
-            $entity_array,
579
-            $model,
580
-            $rest_request->get_param('caps'),
581
-            $rest_request,
582
-            $this
583
-        );
584
-        $result_without_inaccessible_fields = Capabilities::filter_out_inaccessible_entity_fields(
585
-            $entity_array,
586
-            $model,
587
-            $rest_request->get_param('caps'),
588
-            $this->get_model_version_info(),
589
-            $model->get_index_primary_key_string(
590
-                $model->deduce_fields_n_values_from_cols_n_values($db_row)
591
-            )
592
-        );
593
-        $this->_set_debug_info(
594
-            'inaccessible fields',
595
-            array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
596
-        );
597
-        return apply_filters(
598
-            'FHEE__Read__create_entity_from_wpdb_results__entity_return',
599
-            $result_without_inaccessible_fields,
600
-            $model,
601
-            $rest_request->get_param('caps')
602
-        );
603
-    }
604
-
605
-
606
-
607
-    /**
608
-     * Creates a REST entity array (JSON object we're going to return in the response, but
609
-     * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
610
-     * from $wpdb->get_row( $sql, ARRAY_A)
611
-     *
612
-     * @param \EEM_Base $model
613
-     * @param array     $db_row
614
-     * @return array entity mostly ready for converting to JSON and sending in the response
615
-     */
616
-    protected function _create_bare_entity_from_wpdb_results(\EEM_Base $model, $db_row)
617
-    {
618
-        $result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
619
-        $result = array_intersect_key($result,
620
-            $this->get_model_version_info()->fields_on_model_in_this_version($model));
621
-        foreach ($result as $field_name => $raw_field_value) {
622
-            $field_obj = $model->field_settings_for($field_name);
623
-            $field_value = $field_obj->prepare_for_set_from_db($raw_field_value);
624
-            if ($this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_ignored())) {
625
-                unset($result[$field_name]);
626
-            } elseif (
627
-            $this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_rendered_format())
628
-            ) {
629
-                $result[$field_name] = array(
630
-                    'raw'      => $field_obj->prepare_for_get($field_value),
631
-                    'rendered' => $field_obj->prepare_for_pretty_echoing($field_value),
632
-                );
633
-            } elseif (
634
-            $this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_pretty_format())
635
-            ) {
636
-                $result[$field_name] = array(
637
-                    'raw'    => $field_obj->prepare_for_get($field_value),
638
-                    'pretty' => $field_obj->prepare_for_pretty_echoing($field_value),
639
-                );
640
-            } elseif ($field_obj instanceof \EE_Datetime_Field) {
641
-                if ($field_value instanceof \DateTime) {
642
-                    $timezone = $field_value->getTimezone();
643
-                    $field_value->setTimezone(new \DateTimeZone('UTC'));
644
-                    $result[$field_name . '_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
645
-                        $field_obj,
646
-                        $field_value,
647
-                        $this->get_model_version_info()->requested_version()
648
-                    );
649
-                    $field_value->setTimezone($timezone);
650
-                    $result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
651
-                        $field_obj,
652
-                        $field_value,
653
-                        $this->get_model_version_info()->requested_version()
654
-                    );
655
-                }
656
-            } else {
657
-                $result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
658
-                    $field_obj,
659
-                    $field_obj->prepare_for_get($field_value),
660
-                    $this->get_model_version_info()->requested_version()
661
-                );
662
-            }
663
-        }
664
-        return $result;
665
-    }
666
-
667
-
668
-
669
-    /**
670
-     * Adds a few extra fields to the entity response
671
-     *
672
-     * @param \EEM_Base $model
673
-     * @param array     $db_row
674
-     * @param array     $entity_array
675
-     * @return array modified entity
676
-     */
677
-    protected function _add_extra_fields(\EEM_Base $model, $db_row, $entity_array)
678
-    {
679
-        if ($model instanceof \EEM_CPT_Base) {
680
-            $entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
681
-        }
682
-        return $entity_array;
683
-    }
684
-
685
-
686
-
687
-    /**
688
-     * Gets links we want to add to the response
689
-     *
690
-     * @global \WP_REST_Server $wp_rest_server
691
-     * @param \EEM_Base        $model
692
-     * @param array            $db_row
693
-     * @param array            $entity_array
694
-     * @return array the _links item in the entity
695
-     */
696
-    protected function _get_entity_links($model, $db_row, $entity_array)
697
-    {
698
-        //add basic links
699
-        $links = array();
700
-        if ($model->has_primary_key_field()) {
701
-            $links['self'] = array(
702
-                array(
703
-                    'href' => $this->get_versioned_link_to(
704
-                        \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
705
-                        . '/'
706
-                        . $entity_array[$model->primary_key_name()]
707
-                    ),
708
-                ),
709
-            );
710
-        }
711
-        $links['collection'] = array(
712
-            array(
713
-                'href' => $this->get_versioned_link_to(
714
-                    \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
715
-                ),
716
-            ),
717
-        );
718
-        //add links to related models
719
-        if ($model->has_primary_key_field()) {
720
-            foreach ($this->get_model_version_info()->relation_settings($model) as $relation_name => $relation_obj) {
721
-                $related_model_part = Read::get_related_entity_name($relation_name, $relation_obj);
722
-                $links[\EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
723
-                    array(
724
-                        'href'   => $this->get_versioned_link_to(
725
-                            \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
726
-                            . '/'
727
-                            . $entity_array[$model->primary_key_name()]
728
-                            . '/'
729
-                            . $related_model_part
730
-                        ),
731
-                        'single' => $relation_obj instanceof \EE_Belongs_To_Relation ? true : false,
732
-                    ),
733
-                );
734
-            }
735
-        }
736
-        return $links;
737
-    }
738
-
739
-
740
-
741
-    /**
742
-     * Adds the included models indicated in the request to the entity provided
743
-     *
744
-     * @param \EEM_Base        $model
745
-     * @param \WP_REST_Request $rest_request
746
-     * @param array            $entity_array
747
-     * @param array            $db_row
748
-     * @return array the modified entity
749
-     */
750
-    protected function _include_requested_models(
751
-        \EEM_Base $model,
752
-        \WP_REST_Request $rest_request,
753
-        $entity_array,
754
-        $db_row = array()
755
-    ) {
756
-        //if $db_row not included, hope the entity array has what we need
757
-        if (! $db_row) {
758
-            $db_row = $entity_array;
759
-        }
760
-        $includes_for_this_model = $this->explode_and_get_items_prefixed_with($rest_request->get_param('include'), '');
761
-        $includes_for_this_model = $this->_remove_model_names_from_array($includes_for_this_model);
762
-        //if they passed in * or didn't specify any includes, return everything
763
-        if (! in_array('*', $includes_for_this_model)
764
-            && ! empty($includes_for_this_model)
765
-        ) {
766
-            if ($model->has_primary_key_field()) {
767
-                //always include the primary key. ya just gotta know that at least
768
-                $includes_for_this_model[] = $model->primary_key_name();
769
-            }
770
-            if ($this->explode_and_get_items_prefixed_with($rest_request->get_param('calculate'), '')) {
771
-                $includes_for_this_model[] = '_calculated_fields';
772
-            }
773
-            $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
774
-        }
775
-        $relation_settings = $this->get_model_version_info()->relation_settings($model);
776
-        foreach ($relation_settings as $relation_name => $relation_obj) {
777
-            $related_fields_to_include = $this->explode_and_get_items_prefixed_with(
778
-                $rest_request->get_param('include'),
779
-                $relation_name
780
-            );
781
-            $related_fields_to_calculate = $this->explode_and_get_items_prefixed_with(
782
-                $rest_request->get_param('calculate'),
783
-                $relation_name
784
-            );
785
-            //did they specify they wanted to include a related model, or
786
-            //specific fields from a related model?
787
-            //or did they specify to calculate a field from a related model?
788
-            if ($related_fields_to_include || $related_fields_to_calculate) {
789
-                //if so, we should include at least some part of the related model
790
-                $pretend_related_request = new \WP_REST_Request();
791
-                $pretend_related_request->set_query_params(
792
-                    array(
793
-                        'caps'      => $rest_request->get_param('caps'),
794
-                        'include'   => $related_fields_to_include,
795
-                        'calculate' => $related_fields_to_calculate,
796
-                    )
797
-                );
798
-                $pretend_related_request->add_header('no_rest_headers', true);
799
-                $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
800
-                    $model->get_index_primary_key_string(
801
-                        $model->deduce_fields_n_values_from_cols_n_values($db_row)
802
-                    )
803
-                );
804
-                $related_results = $this->_get_entities_from_relation(
805
-                    $primary_model_query_params,
806
-                    $relation_obj,
807
-                    $pretend_related_request
808
-                );
809
-                $entity_array[Read::get_related_entity_name($relation_name, $relation_obj)] = $related_results
810
-                                                                                              instanceof
811
-                                                                                              \WP_Error
812
-                    ? null
813
-                    : $related_results;
814
-            }
815
-        }
816
-        return $entity_array;
817
-    }
818
-
819
-
820
-
821
-    /**
822
-     * Returns a new array with all the names of models removed. Eg
823
-     * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
824
-     *
825
-     * @param array $arr
826
-     * @return array
827
-     */
828
-    private function _remove_model_names_from_array($arr)
829
-    {
830
-        return array_diff($arr, array_keys(\EE_Registry::instance()->non_abstract_db_models));
831
-    }
832
-
833
-
834
-
835
-    /**
836
-     * Gets the calculated fields for the response
837
-     *
838
-     * @param \EEM_Base        $model
839
-     * @param array            $wpdb_row
840
-     * @param \WP_REST_Request $rest_request
841
-     * @return \stdClass the _calculations item in the entity
842
-     */
843
-    protected function _get_entity_calculations($model, $wpdb_row, $rest_request)
844
-    {
845
-        $calculated_fields = $this->explode_and_get_items_prefixed_with(
846
-            $rest_request->get_param('calculate'),
847
-            ''
848
-        );
849
-        //note: setting calculate=* doesn't do anything
850
-        $calculated_fields_to_return = new \stdClass();
851
-        foreach ($calculated_fields as $field_to_calculate) {
852
-            try {
853
-                $calculated_fields_to_return->$field_to_calculate = Model_Data_Translator::prepare_field_value_for_json(
854
-                    null,
855
-                    $this->_fields_calculator->retrieve_calculated_field_value(
856
-                        $model,
857
-                        $field_to_calculate,
858
-                        $wpdb_row,
859
-                        $rest_request,
860
-                        $this
861
-                    ),
862
-                    $this->get_model_version_info()->requested_version()
863
-                );
864
-            } catch (Rest_Exception $e) {
865
-                //if we don't have permission to read it, just leave it out. but let devs know about the problem
866
-                $this->_set_response_header(
867
-                    'Notices-Field-Calculation-Errors['
868
-                    . $e->get_string_code()
869
-                    . ']['
870
-                    . $model->get_this_model_name()
871
-                    . ']['
872
-                    . $field_to_calculate
873
-                    . ']',
874
-                    $e->getMessage(),
875
-                    true
876
-                );
877
-            }
878
-        }
879
-        return $calculated_fields_to_return;
880
-    }
881
-
882
-
883
-
884
-    /**
885
-     * Gets the full URL to the resource, taking the requested version into account
886
-     *
887
-     * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
888
-     * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
889
-     */
890
-    public function get_versioned_link_to($link_part_after_version_and_slash)
891
-    {
892
-        return rest_url(
893
-            \EED_Core_Rest_Api::ee_api_namespace
894
-            . $this->get_model_version_info()->requested_version()
895
-            . '/'
896
-            . $link_part_after_version_and_slash
897
-        );
898
-    }
899
-
900
-
901
-
902
-    /**
903
-     * Gets the correct lowercase name for the relation in the API according
904
-     * to the relation's type
905
-     *
906
-     * @param string                  $relation_name
907
-     * @param \EE_Model_Relation_Base $relation_obj
908
-     * @return string
909
-     */
910
-    public static function get_related_entity_name($relation_name, $relation_obj)
911
-    {
912
-        if ($relation_obj instanceof \EE_Belongs_To_Relation) {
913
-            return strtolower($relation_name);
914
-        } else {
915
-            return \EEH_Inflector::pluralize_and_lower($relation_name);
916
-        }
917
-    }
918
-
919
-
920
-
921
-    /**
922
-     * Gets the one model object with the specified id for the specified model
923
-     *
924
-     * @param \EEM_Base        $model
925
-     * @param \WP_REST_Request $request
926
-     * @return array|\WP_Error
927
-     */
928
-    public function get_entity_from_model($model, $request)
929
-    {
930
-        $query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
931
-        if ($model instanceof \EEM_Soft_Delete_Base) {
932
-            $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
933
-        }
934
-        $restricted_query_params = $query_params;
935
-        $restricted_query_params['caps'] = $this->validate_context($request->get_param('caps'));
936
-        $this->_set_debug_info('model query params', $restricted_query_params);
937
-        $model_rows = $model->get_all_wpdb_results($restricted_query_params);
938
-        if (! empty ($model_rows)) {
939
-            return $this->create_entity_from_wpdb_result(
940
-                $model,
941
-                array_shift($model_rows),
942
-                $request);
943
-        } else {
944
-            //ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
945
-            $lowercase_model_name = strtolower($model->get_this_model_name());
946
-            $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
947
-            if (! empty($model_rows_found_sans_restrictions)) {
948
-                //you got shafted- it existed but we didn't want to tell you!
949
-                return new \WP_Error(
950
-                    'rest_user_cannot_read',
951
-                    sprintf(
952
-                        __('Sorry, you cannot read this %1$s. Missing permissions are: %2$s', 'event_espresso'),
953
-                        strtolower($model->get_this_model_name()),
954
-                        Capabilities::get_missing_permissions_string(
955
-                            $model,
956
-                            $this->validate_context($request->get_param('caps')))
957
-                    ),
958
-                    array('status' => 403)
959
-                );
960
-            } else {
961
-                //it's not you. It just doesn't exist
962
-                return new \WP_Error(
963
-                    sprintf('rest_%s_invalid_id', $lowercase_model_name),
964
-                    sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
965
-                    array('status' => 404)
966
-                );
967
-            }
968
-        }
969
-    }
970
-
971
-
972
-
973
-    /**
974
-     * If a context is provided which isn't valid, maybe it was added in a future
975
-     * version so just treat it as a default read
976
-     *
977
-     * @param string $context
978
-     * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
979
-     */
980
-    public function validate_context($context)
981
-    {
982
-        if (! $context) {
983
-            $context = \EEM_Base::caps_read;
984
-        }
985
-        $valid_contexts = \EEM_Base::valid_cap_contexts();
986
-        if (in_array($context, $valid_contexts)) {
987
-            return $context;
988
-        } else {
989
-            return \EEM_Base::caps_read;
990
-        }
991
-    }
992
-
993
-
994
-
995
-    /**
996
-     * Verifies the passed in value is an allowable default where conditions value.
997
-     *
998
-     * @param $default_query_params
999
-     * @return string
1000
-     */
1001
-    public function validate_default_query_params($default_query_params)
1002
-    {
1003
-        $valid_default_where_conditions_for_api_calls = array(
1004
-            \EEM_Base::default_where_conditions_all,
1005
-            \EEM_Base::default_where_conditions_minimum_all,
1006
-            \EEM_Base::default_where_conditions_minimum_others,
1007
-        );
1008
-        if (! $default_query_params) {
1009
-            $default_query_params = \EEM_Base::default_where_conditions_all;
1010
-        }
1011
-        if (
1012
-        in_array(
1013
-            $default_query_params,
1014
-            $valid_default_where_conditions_for_api_calls,
1015
-            true
1016
-        )
1017
-        ) {
1018
-            return $default_query_params;
1019
-        } else {
1020
-            return \EEM_Base::default_where_conditions_all;
1021
-        }
1022
-    }
1023
-
1024
-
1025
-
1026
-    /**
1027
-     * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
1028
-     * Note: right now the query parameter keys for fields (and related fields)
1029
-     * can be left as-is, but it's quite possible this will change someday.
1030
-     * Also, this method's contents might be candidate for moving to Model_Data_Translator
1031
-     *
1032
-     * @param \EEM_Base $model
1033
-     * @param array     $query_parameters from $_GET parameter @see Read:handle_request_get_all
1034
-     * @return array like what EEM_Base::get_all() expects or FALSE to indicate
1035
-     *                                    that absolutely no results should be returned
1036
-     * @throws \EE_Error
1037
-     */
1038
-    public function create_model_query_params($model, $query_parameters)
1039
-    {
1040
-        $model_query_params = array();
1041
-        if (isset($query_parameters['where'])) {
1042
-            $model_query_params[0] = Model_Data_Translator::prepare_conditions_query_params_for_models(
1043
-                $query_parameters['where'],
1044
-                $model,
1045
-                $this->get_model_version_info()->requested_version()
1046
-            );
1047
-        }
1048
-        if (isset($query_parameters['order_by'])) {
1049
-            $order_by = $query_parameters['order_by'];
1050
-        } elseif (isset($query_parameters['orderby'])) {
1051
-            $order_by = $query_parameters['orderby'];
1052
-        } else {
1053
-            $order_by = null;
1054
-        }
1055
-        if ($order_by !== null) {
1056
-            if (is_array($order_by)) {
1057
-                $order_by = Model_Data_Translator::prepare_field_names_in_array_keys_from_json($order_by);
1058
-            } else {
1059
-                //it's a single item
1060
-                $order_by = Model_Data_Translator::prepare_field_name_from_json($order_by);
1061
-            }
1062
-            $model_query_params['order_by'] = $order_by;
1063
-        }
1064
-        if (isset($query_parameters['group_by'])) {
1065
-            $group_by = $query_parameters['group_by'];
1066
-        } elseif (isset($query_parameters['groupby'])) {
1067
-            $group_by = $query_parameters['groupby'];
1068
-        } else {
1069
-            $group_by = array_keys($model->get_combined_primary_key_fields());
1070
-        }
1071
-        //make sure they're all real names
1072
-        if (is_array($group_by)) {
1073
-            $group_by = Model_Data_Translator::prepare_field_names_from_json($group_by);
1074
-        }
1075
-        if ($group_by !== null) {
1076
-            $model_query_params['group_by'] = $group_by;
1077
-        }
1078
-        if (isset($query_parameters['having'])) {
1079
-            $model_query_params['having'] = Model_Data_Translator::prepare_conditions_query_params_for_models(
1080
-                $query_parameters['having'],
1081
-                $model,
1082
-                $this->get_model_version_info()->requested_version()
1083
-            );
1084
-        }
1085
-        if (isset($query_parameters['order'])) {
1086
-            $model_query_params['order'] = $query_parameters['order'];
1087
-        }
1088
-        if (isset($query_parameters['mine'])) {
1089
-            $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1090
-        }
1091
-        if (isset($query_parameters['limit'])) {
1092
-            //limit should be either a string like '23' or '23,43', or an array with two items in it
1093
-            if (! is_array($query_parameters['limit'])) {
1094
-                $limit_array = explode(',', (string)$query_parameters['limit']);
1095
-            } else {
1096
-                $limit_array = $query_parameters['limit'];
1097
-            }
1098
-            $sanitized_limit = array();
1099
-            foreach ($limit_array as $key => $limit_part) {
1100
-                if ($this->_debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1101
-                    throw new \EE_Error(
1102
-                        sprintf(
1103
-                            __('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.',
1104
-                                'event_espresso'),
1105
-                            wp_json_encode($query_parameters['limit'])
1106
-                        )
1107
-                    );
1108
-                }
1109
-                $sanitized_limit[] = (int)$limit_part;
1110
-            }
1111
-            $model_query_params['limit'] = implode(',', $sanitized_limit);
1112
-        } else {
1113
-            $model_query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
1114
-        }
1115
-        if (isset($query_parameters['caps'])) {
1116
-            $model_query_params['caps'] = $this->validate_context($query_parameters['caps']);
1117
-        } else {
1118
-            $model_query_params['caps'] = \EEM_Base::caps_read;
1119
-        }
1120
-        if (isset($query_parameters['default_where_conditions'])) {
1121
-            $model_query_params['default_where_conditions'] = $this->validate_default_query_params($query_parameters['default_where_conditions']);
1122
-        }
1123
-        return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
1124
-    }
1125
-
1126
-
1127
-
1128
-    /**
1129
-     * Changes the REST-style query params for use in the models
1130
-     *
1131
-     * @deprecated
1132
-     * @param \EEM_Base $model
1133
-     * @param array     $query_params sub-array from @see EEM_Base::get_all()
1134
-     * @return array
1135
-     */
1136
-    public function prepare_rest_query_params_key_for_models($model, $query_params)
1137
-    {
1138
-        $model_ready_query_params = array();
1139
-        foreach ($query_params as $key => $value) {
1140
-            if (is_array($value)) {
1141
-                $model_ready_query_params[$key] = $this->prepare_rest_query_params_key_for_models($model, $value);
1142
-            } else {
1143
-                $model_ready_query_params[$key] = $value;
1144
-            }
1145
-        }
1146
-        return $model_ready_query_params;
1147
-    }
1148
-
1149
-
1150
-
1151
-    /**
1152
-     * @deprecated
1153
-     * @param $model
1154
-     * @param $query_params
1155
-     * @return array
1156
-     */
1157
-    public function prepare_rest_query_params_values_for_models($model, $query_params)
1158
-    {
1159
-        $model_ready_query_params = array();
1160
-        foreach ($query_params as $key => $value) {
1161
-            if (is_array($value)) {
1162
-                $model_ready_query_params[$key] = $this->prepare_rest_query_params_values_for_models($model, $value);
1163
-            } else {
1164
-                $model_ready_query_params[$key] = $value;
1165
-            }
1166
-        }
1167
-        return $model_ready_query_params;
1168
-    }
1169
-
1170
-
1171
-
1172
-    /**
1173
-     * Explodes the string on commas, and only returns items with $prefix followed by a period.
1174
-     * If no prefix is specified, returns items with no period.
1175
-     *
1176
-     * @param string|array $string_to_explode eg "jibba,jabba, blah, blaabla" or array('jibba', 'jabba' )
1177
-     * @param string       $prefix            "Event" or "foobar"
1178
-     * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1179
-     *                                        we only return strings starting with that and a period; if no prefix was
1180
-     *                                        specified we return all items containing NO periods
1181
-     */
1182
-    public function explode_and_get_items_prefixed_with($string_to_explode, $prefix)
1183
-    {
1184
-        if (is_string($string_to_explode)) {
1185
-            $exploded_contents = explode(',', $string_to_explode);
1186
-        } else if (is_array($string_to_explode)) {
1187
-            $exploded_contents = $string_to_explode;
1188
-        } else {
1189
-            $exploded_contents = array();
1190
-        }
1191
-        //if the string was empty, we want an empty array
1192
-        $exploded_contents = array_filter($exploded_contents);
1193
-        $contents_with_prefix = array();
1194
-        foreach ($exploded_contents as $item) {
1195
-            $item = trim($item);
1196
-            //if no prefix was provided, so we look for items with no "." in them
1197
-            if (! $prefix) {
1198
-                //does this item have a period?
1199
-                if (strpos($item, '.') === false) {
1200
-                    //if not, then its what we're looking for
1201
-                    $contents_with_prefix[] = $item;
1202
-                }
1203
-            } else if (strpos($item, $prefix . '.') === 0) {
1204
-                //this item has the prefix and a period, grab it
1205
-                $contents_with_prefix[] = substr(
1206
-                    $item,
1207
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1208
-                );
1209
-            } else if ($item === $prefix) {
1210
-                //this item is JUST the prefix
1211
-                //so let's grab everything after, which is a blank string
1212
-                $contents_with_prefix[] = '';
1213
-            }
1214
-        }
1215
-        return $contents_with_prefix;
1216
-    }
1217
-
1218
-
1219
-
1220
-    /**
1221
-     * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1222
-     * Deprecated because its return values were really quite confusing- sometimes it returned
1223
-     * an empty array (when the include string was blank or '*') or sometimes it returned
1224
-     * array('*') (when you provided a model and a model of that kind was found).
1225
-     * Parses the $include_string so we fetch all the field names relating to THIS model
1226
-     * (ie have NO period in them), or for the provided model (ie start with the model
1227
-     * name and then a period).
1228
-     * @param string $include_string @see Read:handle_request_get_all
1229
-     * @param string $model_name
1230
-     * @return array of fields for this model. If $model_name is provided, then
1231
-     *                               the fields for that model, with the model's name removed from each.
1232
-     *                               If $include_string was blank or '*' returns an empty array
1233
-     */
1234
-    public function extract_includes_for_this_model($include_string, $model_name = null)
1235
-    {
1236
-        if (is_array($include_string)) {
1237
-            $include_string = implode(',', $include_string);
1238
-        }
1239
-        if ($include_string === '*' || $include_string === '') {
1240
-            return array();
1241
-        }
1242
-        $includes = explode(',', $include_string);
1243
-        $extracted_fields_to_include = array();
1244
-        if ($model_name) {
1245
-            foreach ($includes as $field_to_include) {
1246
-                $field_to_include = trim($field_to_include);
1247
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1248
-                    //found the model name at the exact start
1249
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1250
-                    $extracted_fields_to_include[] = $field_sans_model_name;
1251
-                } elseif ($field_to_include == $model_name) {
1252
-                    $extracted_fields_to_include[] = '*';
1253
-                }
1254
-            }
1255
-        } else {
1256
-            //look for ones with no period
1257
-            foreach ($includes as $field_to_include) {
1258
-                $field_to_include = trim($field_to_include);
1259
-                if (
1260
-                    strpos($field_to_include, '.') === false
1261
-                    && ! $this->get_model_version_info()->is_model_name_in_this_version($field_to_include)
1262
-                ) {
1263
-                    $extracted_fields_to_include[] = $field_to_include;
1264
-                }
1265
-            }
1266
-        }
1267
-        return $extracted_fields_to_include;
1268
-    }
30
+	/**
31
+	 * @var Calculated_Model_Fields
32
+	 */
33
+	protected $_fields_calculator;
34
+
35
+
36
+
37
+	/**
38
+	 * Read constructor.
39
+	 */
40
+	public function __construct()
41
+	{
42
+		parent::__construct();
43
+		$this->_fields_calculator = new Calculated_Model_Fields();
44
+	}
45
+
46
+
47
+
48
+	/**
49
+	 * Handles requests to get all (or a filtered subset) of entities for a particular model
50
+	 *
51
+	 * @param \WP_REST_Request $request
52
+	 * @return \WP_REST_Response|\WP_Error
53
+	 */
54
+	public static function handle_request_get_all(\WP_REST_Request $request)
55
+	{
56
+		$controller = new Read();
57
+		try {
58
+			$matches = $controller->parse_route(
59
+				$request->get_route(),
60
+				'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)~',
61
+				array('version', 'model')
62
+			);
63
+			$controller->set_requested_version($matches['version']);
64
+			$model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
65
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
66
+				return $controller->send_response(
67
+					new \WP_Error(
68
+						'endpoint_parsing_error',
69
+						sprintf(
70
+							__('There is no model for endpoint %s. Please contact event espresso support',
71
+								'event_espresso'),
72
+							$model_name_singular
73
+						)
74
+					)
75
+				);
76
+			}
77
+			return $controller->send_response(
78
+				$controller->get_entities_from_model(
79
+					$controller->get_model_version_info()->load_model($model_name_singular),
80
+					$request
81
+				)
82
+			);
83
+		} catch (\Exception $e) {
84
+			return $controller->send_response($e);
85
+		}
86
+	}
87
+
88
+
89
+
90
+	/**
91
+	 * Prepares and returns schema for any OPTIONS request.
92
+	 *
93
+	 * @param string $model_name Something like `Event` or `Registration`
94
+	 * @param string $version    The API endpoint version being used.
95
+	 * @return array
96
+	 */
97
+	public static function handle_schema_request($model_name, $version)
98
+	{
99
+		$controller = new Read();
100
+		try {
101
+			$controller->set_requested_version($version);
102
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name)) {
103
+				return array();
104
+			}
105
+			//get the model for this version
106
+			$model = $controller->get_model_version_info()->load_model($model_name);
107
+			$model_schema = new JsonModelSchema($model);
108
+			return $model_schema->getModelSchemaForRelations(
109
+				$controller->get_model_version_info()->relation_settings($model),
110
+				$controller->_customize_schema_for_rest_response(
111
+					$model,
112
+					$model_schema->getModelSchemaForFields(
113
+						$controller->get_model_version_info()->fields_on_model_in_this_version($model),
114
+						$model_schema->getInitialSchemaStructure()
115
+					)
116
+				)
117
+			);
118
+		} catch (\Exception $e) {
119
+			return array();
120
+		}
121
+	}
122
+
123
+
124
+
125
+	/**
126
+	 * This loops through each field in the given schema for the model and does the following:
127
+	 * - add any extra fields that are REST API specific and related to existing fields.
128
+	 * - transform default values into the correct format for a REST API response.
129
+	 *
130
+	 * @param \EEM_Base $model
131
+	 * @param array     $schema
132
+	 * @return array  The final schema.
133
+	 */
134
+	protected function _customize_schema_for_rest_response(\EEM_Base $model, array $schema)
135
+	{
136
+		foreach ($this->get_model_version_info()->fields_on_model_in_this_version($model) as $field_name => $field) {
137
+			$schema = $this->_translate_defaults_for_rest_response(
138
+				$field_name,
139
+				$field,
140
+				$this->_maybe_add_extra_fields_to_schema($field_name, $field, $schema)
141
+			);
142
+		}
143
+		return $schema;
144
+	}
145
+
146
+
147
+
148
+	/**
149
+	 * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
150
+	 * response.
151
+	 *
152
+	 * @param                      $field_name
153
+	 * @param \EE_Model_Field_Base $field
154
+	 * @param array                $schema
155
+	 * @return array
156
+	 */
157
+	protected function _translate_defaults_for_rest_response($field_name, \EE_Model_Field_Base $field, array $schema)
158
+	{
159
+		if (isset($schema['properties'][$field_name]['default'])) {
160
+			if (is_array($schema['properties'][$field_name]['default'])) {
161
+				foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) {
162
+					if ($default_key === 'raw') {
163
+						$schema['properties'][$field_name]['default'][$default_key] = Model_Data_Translator::prepare_field_value_for_json(
164
+							$field,
165
+							$default_value,
166
+							$this->get_model_version_info()->requested_version()
167
+						);
168
+					}
169
+				}
170
+			} else {
171
+				$schema['properties'][$field_name]['default'] = Model_Data_Translator::prepare_field_value_for_json(
172
+					$field,
173
+					$schema['properties'][$field_name]['default'],
174
+					$this->get_model_version_info()->requested_version()
175
+				);
176
+			}
177
+		}
178
+		return $schema;
179
+	}
180
+
181
+
182
+
183
+	/**
184
+	 * Adds additional fields to the schema
185
+	 * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
186
+	 * needs to be added to the schema.
187
+	 *
188
+	 * @param                      $field_name
189
+	 * @param \EE_Model_Field_Base $field
190
+	 * @param array                $schema
191
+	 * @return array
192
+	 */
193
+	protected function _maybe_add_extra_fields_to_schema($field_name, \EE_Model_Field_Base $field, array $schema)
194
+	{
195
+		if ($field instanceof EE_Datetime_Field) {
196
+			$schema['properties'][$field_name . '_gmt'] = $field->getSchema();
197
+			//modify the description
198
+			$schema['properties'][$field_name . '_gmt']['description'] = sprintf(
199
+				esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
200
+				$field->get_nicename()
201
+			);
202
+		}
203
+		return $schema;
204
+	}
205
+
206
+
207
+
208
+	/**
209
+	 * Used to figure out the route from the request when a `WP_REST_Request` object is not available
210
+	 *
211
+	 * @return string
212
+	 */
213
+	protected function get_route_from_request()
214
+	{
215
+		if (isset($GLOBALS['wp'])
216
+			&& $GLOBALS['wp'] instanceof \WP
217
+			&& isset($GLOBALS['wp']->query_vars['rest_route'])
218
+		) {
219
+			return $GLOBALS['wp']->query_vars['rest_route'];
220
+		} else {
221
+			return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';
222
+		}
223
+	}
224
+
225
+
226
+
227
+	/**
228
+	 * Gets a single entity related to the model indicated in the path and its id
229
+	 *
230
+	 * @param \WP_REST_Request $request
231
+	 * @return \WP_REST_Response|\WP_Error
232
+	 */
233
+	public static function handle_request_get_one(\WP_REST_Request $request)
234
+	{
235
+		$controller = new Read();
236
+		try {
237
+			$matches = $controller->parse_route(
238
+				$request->get_route(),
239
+				'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)~',
240
+				array('version', 'model', 'id'));
241
+			$controller->set_requested_version($matches['version']);
242
+			$model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
243
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
244
+				return $controller->send_response(
245
+					new \WP_Error(
246
+						'endpoint_parsing_error',
247
+						sprintf(
248
+							__('There is no model for endpoint %s. Please contact event espresso support',
249
+								'event_espresso'),
250
+							$model_name_singular
251
+						)
252
+					)
253
+				);
254
+			}
255
+			return $controller->send_response(
256
+				$controller->get_entity_from_model(
257
+					$controller->get_model_version_info()->load_model($model_name_singular),
258
+					$request
259
+				)
260
+			);
261
+		} catch (\Exception $e) {
262
+			return $controller->send_response($e);
263
+		}
264
+	}
265
+
266
+
267
+
268
+	/**
269
+	 * Gets all the related entities (or if its a belongs-to relation just the one)
270
+	 * to the item with the given id
271
+	 *
272
+	 * @param \WP_REST_Request $request
273
+	 * @return \WP_REST_Response|\WP_Error
274
+	 */
275
+	public static function handle_request_get_related(\WP_REST_Request $request)
276
+	{
277
+		$controller = new Read();
278
+		try {
279
+			$matches = $controller->parse_route(
280
+				$request->get_route(),
281
+				'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)/(.*)~',
282
+				array('version', 'model', 'id', 'related_model')
283
+			);
284
+			$controller->set_requested_version($matches['version']);
285
+			$main_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
286
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
287
+				return $controller->send_response(
288
+					new \WP_Error(
289
+						'endpoint_parsing_error',
290
+						sprintf(
291
+							__('There is no model for endpoint %s. Please contact event espresso support',
292
+								'event_espresso'),
293
+							$main_model_name_singular
294
+						)
295
+					)
296
+				);
297
+			}
298
+			$main_model = $controller->get_model_version_info()->load_model($main_model_name_singular);
299
+			//assume the related model name is plural and try to find the model's name
300
+			$related_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['related_model']);
301
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
302
+				//so the word didn't singularize well. Maybe that's just because it's a singular word?
303
+				$related_model_name_singular = \EEH_Inflector::humanize($matches['related_model']);
304
+			}
305
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
306
+				return $controller->send_response(
307
+					new \WP_Error(
308
+						'endpoint_parsing_error',
309
+						sprintf(
310
+							__('There is no model for endpoint %s. Please contact event espresso support',
311
+								'event_espresso'),
312
+							$related_model_name_singular
313
+						)
314
+					)
315
+				);
316
+			}
317
+			return $controller->send_response(
318
+				$controller->get_entities_from_relation(
319
+					$request->get_param('id'),
320
+					$main_model->related_settings_for($related_model_name_singular),
321
+					$request
322
+				)
323
+			);
324
+		} catch (\Exception $e) {
325
+			return $controller->send_response($e);
326
+		}
327
+	}
328
+
329
+
330
+
331
+	/**
332
+	 * Gets a collection for the given model and filters
333
+	 *
334
+	 * @param \EEM_Base        $model
335
+	 * @param \WP_REST_Request $request
336
+	 * @return array|\WP_Error
337
+	 */
338
+	public function get_entities_from_model($model, $request)
339
+	{
340
+		$query_params = $this->create_model_query_params($model, $request->get_params());
341
+		if (! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
342
+			$model_name_plural = \EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
343
+			return new \WP_Error(
344
+				sprintf('rest_%s_cannot_list', $model_name_plural),
345
+				sprintf(
346
+					__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
347
+					$model_name_plural,
348
+					Capabilities::get_missing_permissions_string($model, $query_params['caps'])
349
+				),
350
+				array('status' => 403)
351
+			);
352
+		}
353
+		if (! $request->get_header('no_rest_headers')) {
354
+			$this->_set_headers_from_query_params($model, $query_params);
355
+		}
356
+		/** @type array $results */
357
+		$results = $model->get_all_wpdb_results($query_params);
358
+		$nice_results = array();
359
+		foreach ($results as $result) {
360
+			$nice_results[] = $this->create_entity_from_wpdb_result(
361
+				$model,
362
+				$result,
363
+				$request
364
+			);
365
+		}
366
+		return $nice_results;
367
+	}
368
+
369
+
370
+
371
+	/**
372
+	 * @param array                   $primary_model_query_params query params for finding the item from which
373
+	 *                                                            relations will be based
374
+	 * @param \EE_Model_Relation_Base $relation
375
+	 * @param \WP_REST_Request        $request
376
+	 * @return \WP_Error|array
377
+	 */
378
+	protected function _get_entities_from_relation($primary_model_query_params, $relation, $request)
379
+	{
380
+		$context = $this->validate_context($request->get_param('caps'));
381
+		$model = $relation->get_this_model();
382
+		$related_model = $relation->get_other_model();
383
+		if (! isset($primary_model_query_params[0])) {
384
+			$primary_model_query_params[0] = array();
385
+		}
386
+		//check if they can access the 1st model object
387
+		$primary_model_query_params = array(
388
+			0       => $primary_model_query_params[0],
389
+			'limit' => 1,
390
+		);
391
+		if ($model instanceof \EEM_Soft_Delete_Base) {
392
+			$primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($primary_model_query_params);
393
+		}
394
+		$restricted_query_params = $primary_model_query_params;
395
+		$restricted_query_params['caps'] = $context;
396
+		$this->_set_debug_info('main model query params', $restricted_query_params);
397
+		$this->_set_debug_info('missing caps', Capabilities::get_missing_permissions_string($related_model, $context));
398
+		if (
399
+		! (
400
+			Capabilities::current_user_has_partial_access_to($related_model, $context)
401
+			&& $model->exists($restricted_query_params)
402
+		)
403
+		) {
404
+			if ($relation instanceof \EE_Belongs_To_Relation) {
405
+				$related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
406
+			} else {
407
+				$related_model_name_maybe_plural = \EEH_Inflector::pluralize_and_lower($related_model->get_this_model_name());
408
+			}
409
+			return new \WP_Error(
410
+				sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
411
+				sprintf(
412
+					__('Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
413
+						'event_espresso'),
414
+					$related_model_name_maybe_plural,
415
+					$relation->get_this_model()->get_this_model_name(),
416
+					implode(
417
+						',',
418
+						array_keys(
419
+							Capabilities::get_missing_permissions($related_model, $context)
420
+						)
421
+					)
422
+				),
423
+				array('status' => 403)
424
+			);
425
+		}
426
+		$query_params = $this->create_model_query_params($relation->get_other_model(), $request->get_params());
427
+		foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
428
+			$query_params[0][$relation->get_this_model()->get_this_model_name()
429
+							 . '.'
430
+							 . $where_condition_key] = $where_condition_value;
431
+		}
432
+		$query_params['default_where_conditions'] = 'none';
433
+		$query_params['caps'] = $context;
434
+		if (! $request->get_header('no_rest_headers')) {
435
+			$this->_set_headers_from_query_params($relation->get_other_model(), $query_params);
436
+		}
437
+		/** @type array $results */
438
+		$results = $relation->get_other_model()->get_all_wpdb_results($query_params);
439
+		$nice_results = array();
440
+		foreach ($results as $result) {
441
+			$nice_result = $this->create_entity_from_wpdb_result(
442
+				$relation->get_other_model(),
443
+				$result,
444
+				$request
445
+			);
446
+			if ($relation instanceof \EE_HABTM_Relation) {
447
+				//put the unusual stuff (properties from the HABTM relation) first, and make sure
448
+				//if there are conflicts we prefer the properties from the main model
449
+				$join_model_result = $this->create_entity_from_wpdb_result(
450
+					$relation->get_join_model(),
451
+					$result,
452
+					$request
453
+				);
454
+				$joined_result = array_merge($nice_result, $join_model_result);
455
+				//but keep the meta stuff from the main model
456
+				if (isset($nice_result['meta'])) {
457
+					$joined_result['meta'] = $nice_result['meta'];
458
+				}
459
+				$nice_result = $joined_result;
460
+			}
461
+			$nice_results[] = $nice_result;
462
+		}
463
+		if ($relation instanceof \EE_Belongs_To_Relation) {
464
+			return array_shift($nice_results);
465
+		} else {
466
+			return $nice_results;
467
+		}
468
+	}
469
+
470
+
471
+
472
+	/**
473
+	 * Gets the collection for given relation object
474
+	 * The same as Read::get_entities_from_model(), except if the relation
475
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
476
+	 * the join-model-object into the results
477
+	 *
478
+	 * @param string                  $id the ID of the thing we are fetching related stuff from
479
+	 * @param \EE_Model_Relation_Base $relation
480
+	 * @param \WP_REST_Request        $request
481
+	 * @return array|\WP_Error
482
+	 * @throws \EE_Error
483
+	 */
484
+	public function get_entities_from_relation($id, $relation, $request)
485
+	{
486
+		if (! $relation->get_this_model()->has_primary_key_field()) {
487
+			throw new \EE_Error(
488
+				sprintf(
489
+					__('Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
490
+						'event_espresso'),
491
+					$relation->get_this_model()->get_this_model_name()
492
+				)
493
+			);
494
+		}
495
+		return $this->_get_entities_from_relation(
496
+			array(
497
+				array(
498
+					$relation->get_this_model()->primary_key_name() => $id,
499
+				),
500
+			),
501
+			$relation,
502
+			$request
503
+		);
504
+	}
505
+
506
+
507
+
508
+	/**
509
+	 * Sets the headers that are based on the model and query params,
510
+	 * like the total records. This should only be called on the original request
511
+	 * from the client, not on subsequent internal
512
+	 *
513
+	 * @param \EEM_Base $model
514
+	 * @param array     $query_params
515
+	 * @return void
516
+	 */
517
+	protected function _set_headers_from_query_params($model, $query_params)
518
+	{
519
+		$this->_set_debug_info('model query params', $query_params);
520
+		$this->_set_debug_info('missing caps',
521
+			Capabilities::get_missing_permissions_string($model, $query_params['caps']));
522
+		//normally the limit to a 2-part array, where the 2nd item is the limit
523
+		if (! isset($query_params['limit'])) {
524
+			$query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
525
+		}
526
+		if (is_array($query_params['limit'])) {
527
+			$limit_parts = $query_params['limit'];
528
+		} else {
529
+			$limit_parts = explode(',', $query_params['limit']);
530
+			if (count($limit_parts) == 1) {
531
+				$limit_parts = array(0, $limit_parts[0]);
532
+			}
533
+		}
534
+		//remove the group by and having parts of the query, as those will
535
+		//make the sql query return an array of values, instead of just a single value
536
+		unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
537
+		$count = $model->count($query_params, null, true);
538
+		$pages = $count / $limit_parts[1];
539
+		$this->_set_response_header('Total', $count, false);
540
+		$this->_set_response_header('PageSize', $limit_parts[1], false);
541
+		$this->_set_response_header('TotalPages', ceil($pages), false);
542
+	}
543
+
544
+
545
+
546
+	/**
547
+	 * Changes database results into REST API entities
548
+	 *
549
+	 * @param \EEM_Base        $model
550
+	 * @param array            $db_row     like results from $wpdb->get_results()
551
+	 * @param \WP_REST_Request $rest_request
552
+	 * @param string           $deprecated no longer used
553
+	 * @return array ready for being converted into json for sending to client
554
+	 */
555
+	public function create_entity_from_wpdb_result($model, $db_row, $rest_request, $deprecated = null)
556
+	{
557
+		if (! $rest_request instanceof \WP_REST_Request) {
558
+			//ok so this was called in the old style, where the 3rd arg was
559
+			//$include, and the 4th arg was $context
560
+			//now setup the request just to avoid fatal errors, although we won't be able
561
+			//to truly make use of it because it's kinda devoid of info
562
+			$rest_request = new \WP_REST_Request();
563
+			$rest_request->set_param('include', $rest_request);
564
+			$rest_request->set_param('caps', $deprecated);
565
+		}
566
+		if ($rest_request->get_param('caps') == null) {
567
+			$rest_request->set_param('caps', \EEM_Base::caps_read);
568
+		}
569
+		$entity_array = $this->_create_bare_entity_from_wpdb_results($model, $db_row);
570
+		$entity_array = $this->_add_extra_fields($model, $db_row, $entity_array);
571
+		$entity_array['_links'] = $this->_get_entity_links($model, $db_row, $entity_array);
572
+		$entity_array['_calculated_fields'] = $this->_get_entity_calculations($model, $db_row, $rest_request);
573
+		$entity_array = apply_filters('FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
574
+			$entity_array, $model, $rest_request->get_param('caps'), $rest_request, $this);
575
+		$entity_array = $this->_include_requested_models($model, $rest_request, $entity_array, $db_row);
576
+		$entity_array = apply_filters(
577
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
578
+			$entity_array,
579
+			$model,
580
+			$rest_request->get_param('caps'),
581
+			$rest_request,
582
+			$this
583
+		);
584
+		$result_without_inaccessible_fields = Capabilities::filter_out_inaccessible_entity_fields(
585
+			$entity_array,
586
+			$model,
587
+			$rest_request->get_param('caps'),
588
+			$this->get_model_version_info(),
589
+			$model->get_index_primary_key_string(
590
+				$model->deduce_fields_n_values_from_cols_n_values($db_row)
591
+			)
592
+		);
593
+		$this->_set_debug_info(
594
+			'inaccessible fields',
595
+			array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
596
+		);
597
+		return apply_filters(
598
+			'FHEE__Read__create_entity_from_wpdb_results__entity_return',
599
+			$result_without_inaccessible_fields,
600
+			$model,
601
+			$rest_request->get_param('caps')
602
+		);
603
+	}
604
+
605
+
606
+
607
+	/**
608
+	 * Creates a REST entity array (JSON object we're going to return in the response, but
609
+	 * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
610
+	 * from $wpdb->get_row( $sql, ARRAY_A)
611
+	 *
612
+	 * @param \EEM_Base $model
613
+	 * @param array     $db_row
614
+	 * @return array entity mostly ready for converting to JSON and sending in the response
615
+	 */
616
+	protected function _create_bare_entity_from_wpdb_results(\EEM_Base $model, $db_row)
617
+	{
618
+		$result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
619
+		$result = array_intersect_key($result,
620
+			$this->get_model_version_info()->fields_on_model_in_this_version($model));
621
+		foreach ($result as $field_name => $raw_field_value) {
622
+			$field_obj = $model->field_settings_for($field_name);
623
+			$field_value = $field_obj->prepare_for_set_from_db($raw_field_value);
624
+			if ($this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_ignored())) {
625
+				unset($result[$field_name]);
626
+			} elseif (
627
+			$this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_rendered_format())
628
+			) {
629
+				$result[$field_name] = array(
630
+					'raw'      => $field_obj->prepare_for_get($field_value),
631
+					'rendered' => $field_obj->prepare_for_pretty_echoing($field_value),
632
+				);
633
+			} elseif (
634
+			$this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_pretty_format())
635
+			) {
636
+				$result[$field_name] = array(
637
+					'raw'    => $field_obj->prepare_for_get($field_value),
638
+					'pretty' => $field_obj->prepare_for_pretty_echoing($field_value),
639
+				);
640
+			} elseif ($field_obj instanceof \EE_Datetime_Field) {
641
+				if ($field_value instanceof \DateTime) {
642
+					$timezone = $field_value->getTimezone();
643
+					$field_value->setTimezone(new \DateTimeZone('UTC'));
644
+					$result[$field_name . '_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
645
+						$field_obj,
646
+						$field_value,
647
+						$this->get_model_version_info()->requested_version()
648
+					);
649
+					$field_value->setTimezone($timezone);
650
+					$result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
651
+						$field_obj,
652
+						$field_value,
653
+						$this->get_model_version_info()->requested_version()
654
+					);
655
+				}
656
+			} else {
657
+				$result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
658
+					$field_obj,
659
+					$field_obj->prepare_for_get($field_value),
660
+					$this->get_model_version_info()->requested_version()
661
+				);
662
+			}
663
+		}
664
+		return $result;
665
+	}
666
+
667
+
668
+
669
+	/**
670
+	 * Adds a few extra fields to the entity response
671
+	 *
672
+	 * @param \EEM_Base $model
673
+	 * @param array     $db_row
674
+	 * @param array     $entity_array
675
+	 * @return array modified entity
676
+	 */
677
+	protected function _add_extra_fields(\EEM_Base $model, $db_row, $entity_array)
678
+	{
679
+		if ($model instanceof \EEM_CPT_Base) {
680
+			$entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
681
+		}
682
+		return $entity_array;
683
+	}
684
+
685
+
686
+
687
+	/**
688
+	 * Gets links we want to add to the response
689
+	 *
690
+	 * @global \WP_REST_Server $wp_rest_server
691
+	 * @param \EEM_Base        $model
692
+	 * @param array            $db_row
693
+	 * @param array            $entity_array
694
+	 * @return array the _links item in the entity
695
+	 */
696
+	protected function _get_entity_links($model, $db_row, $entity_array)
697
+	{
698
+		//add basic links
699
+		$links = array();
700
+		if ($model->has_primary_key_field()) {
701
+			$links['self'] = array(
702
+				array(
703
+					'href' => $this->get_versioned_link_to(
704
+						\EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
705
+						. '/'
706
+						. $entity_array[$model->primary_key_name()]
707
+					),
708
+				),
709
+			);
710
+		}
711
+		$links['collection'] = array(
712
+			array(
713
+				'href' => $this->get_versioned_link_to(
714
+					\EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
715
+				),
716
+			),
717
+		);
718
+		//add links to related models
719
+		if ($model->has_primary_key_field()) {
720
+			foreach ($this->get_model_version_info()->relation_settings($model) as $relation_name => $relation_obj) {
721
+				$related_model_part = Read::get_related_entity_name($relation_name, $relation_obj);
722
+				$links[\EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
723
+					array(
724
+						'href'   => $this->get_versioned_link_to(
725
+							\EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
726
+							. '/'
727
+							. $entity_array[$model->primary_key_name()]
728
+							. '/'
729
+							. $related_model_part
730
+						),
731
+						'single' => $relation_obj instanceof \EE_Belongs_To_Relation ? true : false,
732
+					),
733
+				);
734
+			}
735
+		}
736
+		return $links;
737
+	}
738
+
739
+
740
+
741
+	/**
742
+	 * Adds the included models indicated in the request to the entity provided
743
+	 *
744
+	 * @param \EEM_Base        $model
745
+	 * @param \WP_REST_Request $rest_request
746
+	 * @param array            $entity_array
747
+	 * @param array            $db_row
748
+	 * @return array the modified entity
749
+	 */
750
+	protected function _include_requested_models(
751
+		\EEM_Base $model,
752
+		\WP_REST_Request $rest_request,
753
+		$entity_array,
754
+		$db_row = array()
755
+	) {
756
+		//if $db_row not included, hope the entity array has what we need
757
+		if (! $db_row) {
758
+			$db_row = $entity_array;
759
+		}
760
+		$includes_for_this_model = $this->explode_and_get_items_prefixed_with($rest_request->get_param('include'), '');
761
+		$includes_for_this_model = $this->_remove_model_names_from_array($includes_for_this_model);
762
+		//if they passed in * or didn't specify any includes, return everything
763
+		if (! in_array('*', $includes_for_this_model)
764
+			&& ! empty($includes_for_this_model)
765
+		) {
766
+			if ($model->has_primary_key_field()) {
767
+				//always include the primary key. ya just gotta know that at least
768
+				$includes_for_this_model[] = $model->primary_key_name();
769
+			}
770
+			if ($this->explode_and_get_items_prefixed_with($rest_request->get_param('calculate'), '')) {
771
+				$includes_for_this_model[] = '_calculated_fields';
772
+			}
773
+			$entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
774
+		}
775
+		$relation_settings = $this->get_model_version_info()->relation_settings($model);
776
+		foreach ($relation_settings as $relation_name => $relation_obj) {
777
+			$related_fields_to_include = $this->explode_and_get_items_prefixed_with(
778
+				$rest_request->get_param('include'),
779
+				$relation_name
780
+			);
781
+			$related_fields_to_calculate = $this->explode_and_get_items_prefixed_with(
782
+				$rest_request->get_param('calculate'),
783
+				$relation_name
784
+			);
785
+			//did they specify they wanted to include a related model, or
786
+			//specific fields from a related model?
787
+			//or did they specify to calculate a field from a related model?
788
+			if ($related_fields_to_include || $related_fields_to_calculate) {
789
+				//if so, we should include at least some part of the related model
790
+				$pretend_related_request = new \WP_REST_Request();
791
+				$pretend_related_request->set_query_params(
792
+					array(
793
+						'caps'      => $rest_request->get_param('caps'),
794
+						'include'   => $related_fields_to_include,
795
+						'calculate' => $related_fields_to_calculate,
796
+					)
797
+				);
798
+				$pretend_related_request->add_header('no_rest_headers', true);
799
+				$primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
800
+					$model->get_index_primary_key_string(
801
+						$model->deduce_fields_n_values_from_cols_n_values($db_row)
802
+					)
803
+				);
804
+				$related_results = $this->_get_entities_from_relation(
805
+					$primary_model_query_params,
806
+					$relation_obj,
807
+					$pretend_related_request
808
+				);
809
+				$entity_array[Read::get_related_entity_name($relation_name, $relation_obj)] = $related_results
810
+																							  instanceof
811
+																							  \WP_Error
812
+					? null
813
+					: $related_results;
814
+			}
815
+		}
816
+		return $entity_array;
817
+	}
818
+
819
+
820
+
821
+	/**
822
+	 * Returns a new array with all the names of models removed. Eg
823
+	 * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
824
+	 *
825
+	 * @param array $arr
826
+	 * @return array
827
+	 */
828
+	private function _remove_model_names_from_array($arr)
829
+	{
830
+		return array_diff($arr, array_keys(\EE_Registry::instance()->non_abstract_db_models));
831
+	}
832
+
833
+
834
+
835
+	/**
836
+	 * Gets the calculated fields for the response
837
+	 *
838
+	 * @param \EEM_Base        $model
839
+	 * @param array            $wpdb_row
840
+	 * @param \WP_REST_Request $rest_request
841
+	 * @return \stdClass the _calculations item in the entity
842
+	 */
843
+	protected function _get_entity_calculations($model, $wpdb_row, $rest_request)
844
+	{
845
+		$calculated_fields = $this->explode_and_get_items_prefixed_with(
846
+			$rest_request->get_param('calculate'),
847
+			''
848
+		);
849
+		//note: setting calculate=* doesn't do anything
850
+		$calculated_fields_to_return = new \stdClass();
851
+		foreach ($calculated_fields as $field_to_calculate) {
852
+			try {
853
+				$calculated_fields_to_return->$field_to_calculate = Model_Data_Translator::prepare_field_value_for_json(
854
+					null,
855
+					$this->_fields_calculator->retrieve_calculated_field_value(
856
+						$model,
857
+						$field_to_calculate,
858
+						$wpdb_row,
859
+						$rest_request,
860
+						$this
861
+					),
862
+					$this->get_model_version_info()->requested_version()
863
+				);
864
+			} catch (Rest_Exception $e) {
865
+				//if we don't have permission to read it, just leave it out. but let devs know about the problem
866
+				$this->_set_response_header(
867
+					'Notices-Field-Calculation-Errors['
868
+					. $e->get_string_code()
869
+					. ']['
870
+					. $model->get_this_model_name()
871
+					. ']['
872
+					. $field_to_calculate
873
+					. ']',
874
+					$e->getMessage(),
875
+					true
876
+				);
877
+			}
878
+		}
879
+		return $calculated_fields_to_return;
880
+	}
881
+
882
+
883
+
884
+	/**
885
+	 * Gets the full URL to the resource, taking the requested version into account
886
+	 *
887
+	 * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
888
+	 * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
889
+	 */
890
+	public function get_versioned_link_to($link_part_after_version_and_slash)
891
+	{
892
+		return rest_url(
893
+			\EED_Core_Rest_Api::ee_api_namespace
894
+			. $this->get_model_version_info()->requested_version()
895
+			. '/'
896
+			. $link_part_after_version_and_slash
897
+		);
898
+	}
899
+
900
+
901
+
902
+	/**
903
+	 * Gets the correct lowercase name for the relation in the API according
904
+	 * to the relation's type
905
+	 *
906
+	 * @param string                  $relation_name
907
+	 * @param \EE_Model_Relation_Base $relation_obj
908
+	 * @return string
909
+	 */
910
+	public static function get_related_entity_name($relation_name, $relation_obj)
911
+	{
912
+		if ($relation_obj instanceof \EE_Belongs_To_Relation) {
913
+			return strtolower($relation_name);
914
+		} else {
915
+			return \EEH_Inflector::pluralize_and_lower($relation_name);
916
+		}
917
+	}
918
+
919
+
920
+
921
+	/**
922
+	 * Gets the one model object with the specified id for the specified model
923
+	 *
924
+	 * @param \EEM_Base        $model
925
+	 * @param \WP_REST_Request $request
926
+	 * @return array|\WP_Error
927
+	 */
928
+	public function get_entity_from_model($model, $request)
929
+	{
930
+		$query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
931
+		if ($model instanceof \EEM_Soft_Delete_Base) {
932
+			$query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
933
+		}
934
+		$restricted_query_params = $query_params;
935
+		$restricted_query_params['caps'] = $this->validate_context($request->get_param('caps'));
936
+		$this->_set_debug_info('model query params', $restricted_query_params);
937
+		$model_rows = $model->get_all_wpdb_results($restricted_query_params);
938
+		if (! empty ($model_rows)) {
939
+			return $this->create_entity_from_wpdb_result(
940
+				$model,
941
+				array_shift($model_rows),
942
+				$request);
943
+		} else {
944
+			//ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
945
+			$lowercase_model_name = strtolower($model->get_this_model_name());
946
+			$model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
947
+			if (! empty($model_rows_found_sans_restrictions)) {
948
+				//you got shafted- it existed but we didn't want to tell you!
949
+				return new \WP_Error(
950
+					'rest_user_cannot_read',
951
+					sprintf(
952
+						__('Sorry, you cannot read this %1$s. Missing permissions are: %2$s', 'event_espresso'),
953
+						strtolower($model->get_this_model_name()),
954
+						Capabilities::get_missing_permissions_string(
955
+							$model,
956
+							$this->validate_context($request->get_param('caps')))
957
+					),
958
+					array('status' => 403)
959
+				);
960
+			} else {
961
+				//it's not you. It just doesn't exist
962
+				return new \WP_Error(
963
+					sprintf('rest_%s_invalid_id', $lowercase_model_name),
964
+					sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
965
+					array('status' => 404)
966
+				);
967
+			}
968
+		}
969
+	}
970
+
971
+
972
+
973
+	/**
974
+	 * If a context is provided which isn't valid, maybe it was added in a future
975
+	 * version so just treat it as a default read
976
+	 *
977
+	 * @param string $context
978
+	 * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
979
+	 */
980
+	public function validate_context($context)
981
+	{
982
+		if (! $context) {
983
+			$context = \EEM_Base::caps_read;
984
+		}
985
+		$valid_contexts = \EEM_Base::valid_cap_contexts();
986
+		if (in_array($context, $valid_contexts)) {
987
+			return $context;
988
+		} else {
989
+			return \EEM_Base::caps_read;
990
+		}
991
+	}
992
+
993
+
994
+
995
+	/**
996
+	 * Verifies the passed in value is an allowable default where conditions value.
997
+	 *
998
+	 * @param $default_query_params
999
+	 * @return string
1000
+	 */
1001
+	public function validate_default_query_params($default_query_params)
1002
+	{
1003
+		$valid_default_where_conditions_for_api_calls = array(
1004
+			\EEM_Base::default_where_conditions_all,
1005
+			\EEM_Base::default_where_conditions_minimum_all,
1006
+			\EEM_Base::default_where_conditions_minimum_others,
1007
+		);
1008
+		if (! $default_query_params) {
1009
+			$default_query_params = \EEM_Base::default_where_conditions_all;
1010
+		}
1011
+		if (
1012
+		in_array(
1013
+			$default_query_params,
1014
+			$valid_default_where_conditions_for_api_calls,
1015
+			true
1016
+		)
1017
+		) {
1018
+			return $default_query_params;
1019
+		} else {
1020
+			return \EEM_Base::default_where_conditions_all;
1021
+		}
1022
+	}
1023
+
1024
+
1025
+
1026
+	/**
1027
+	 * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
1028
+	 * Note: right now the query parameter keys for fields (and related fields)
1029
+	 * can be left as-is, but it's quite possible this will change someday.
1030
+	 * Also, this method's contents might be candidate for moving to Model_Data_Translator
1031
+	 *
1032
+	 * @param \EEM_Base $model
1033
+	 * @param array     $query_parameters from $_GET parameter @see Read:handle_request_get_all
1034
+	 * @return array like what EEM_Base::get_all() expects or FALSE to indicate
1035
+	 *                                    that absolutely no results should be returned
1036
+	 * @throws \EE_Error
1037
+	 */
1038
+	public function create_model_query_params($model, $query_parameters)
1039
+	{
1040
+		$model_query_params = array();
1041
+		if (isset($query_parameters['where'])) {
1042
+			$model_query_params[0] = Model_Data_Translator::prepare_conditions_query_params_for_models(
1043
+				$query_parameters['where'],
1044
+				$model,
1045
+				$this->get_model_version_info()->requested_version()
1046
+			);
1047
+		}
1048
+		if (isset($query_parameters['order_by'])) {
1049
+			$order_by = $query_parameters['order_by'];
1050
+		} elseif (isset($query_parameters['orderby'])) {
1051
+			$order_by = $query_parameters['orderby'];
1052
+		} else {
1053
+			$order_by = null;
1054
+		}
1055
+		if ($order_by !== null) {
1056
+			if (is_array($order_by)) {
1057
+				$order_by = Model_Data_Translator::prepare_field_names_in_array_keys_from_json($order_by);
1058
+			} else {
1059
+				//it's a single item
1060
+				$order_by = Model_Data_Translator::prepare_field_name_from_json($order_by);
1061
+			}
1062
+			$model_query_params['order_by'] = $order_by;
1063
+		}
1064
+		if (isset($query_parameters['group_by'])) {
1065
+			$group_by = $query_parameters['group_by'];
1066
+		} elseif (isset($query_parameters['groupby'])) {
1067
+			$group_by = $query_parameters['groupby'];
1068
+		} else {
1069
+			$group_by = array_keys($model->get_combined_primary_key_fields());
1070
+		}
1071
+		//make sure they're all real names
1072
+		if (is_array($group_by)) {
1073
+			$group_by = Model_Data_Translator::prepare_field_names_from_json($group_by);
1074
+		}
1075
+		if ($group_by !== null) {
1076
+			$model_query_params['group_by'] = $group_by;
1077
+		}
1078
+		if (isset($query_parameters['having'])) {
1079
+			$model_query_params['having'] = Model_Data_Translator::prepare_conditions_query_params_for_models(
1080
+				$query_parameters['having'],
1081
+				$model,
1082
+				$this->get_model_version_info()->requested_version()
1083
+			);
1084
+		}
1085
+		if (isset($query_parameters['order'])) {
1086
+			$model_query_params['order'] = $query_parameters['order'];
1087
+		}
1088
+		if (isset($query_parameters['mine'])) {
1089
+			$model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1090
+		}
1091
+		if (isset($query_parameters['limit'])) {
1092
+			//limit should be either a string like '23' or '23,43', or an array with two items in it
1093
+			if (! is_array($query_parameters['limit'])) {
1094
+				$limit_array = explode(',', (string)$query_parameters['limit']);
1095
+			} else {
1096
+				$limit_array = $query_parameters['limit'];
1097
+			}
1098
+			$sanitized_limit = array();
1099
+			foreach ($limit_array as $key => $limit_part) {
1100
+				if ($this->_debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1101
+					throw new \EE_Error(
1102
+						sprintf(
1103
+							__('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.',
1104
+								'event_espresso'),
1105
+							wp_json_encode($query_parameters['limit'])
1106
+						)
1107
+					);
1108
+				}
1109
+				$sanitized_limit[] = (int)$limit_part;
1110
+			}
1111
+			$model_query_params['limit'] = implode(',', $sanitized_limit);
1112
+		} else {
1113
+			$model_query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
1114
+		}
1115
+		if (isset($query_parameters['caps'])) {
1116
+			$model_query_params['caps'] = $this->validate_context($query_parameters['caps']);
1117
+		} else {
1118
+			$model_query_params['caps'] = \EEM_Base::caps_read;
1119
+		}
1120
+		if (isset($query_parameters['default_where_conditions'])) {
1121
+			$model_query_params['default_where_conditions'] = $this->validate_default_query_params($query_parameters['default_where_conditions']);
1122
+		}
1123
+		return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
1124
+	}
1125
+
1126
+
1127
+
1128
+	/**
1129
+	 * Changes the REST-style query params for use in the models
1130
+	 *
1131
+	 * @deprecated
1132
+	 * @param \EEM_Base $model
1133
+	 * @param array     $query_params sub-array from @see EEM_Base::get_all()
1134
+	 * @return array
1135
+	 */
1136
+	public function prepare_rest_query_params_key_for_models($model, $query_params)
1137
+	{
1138
+		$model_ready_query_params = array();
1139
+		foreach ($query_params as $key => $value) {
1140
+			if (is_array($value)) {
1141
+				$model_ready_query_params[$key] = $this->prepare_rest_query_params_key_for_models($model, $value);
1142
+			} else {
1143
+				$model_ready_query_params[$key] = $value;
1144
+			}
1145
+		}
1146
+		return $model_ready_query_params;
1147
+	}
1148
+
1149
+
1150
+
1151
+	/**
1152
+	 * @deprecated
1153
+	 * @param $model
1154
+	 * @param $query_params
1155
+	 * @return array
1156
+	 */
1157
+	public function prepare_rest_query_params_values_for_models($model, $query_params)
1158
+	{
1159
+		$model_ready_query_params = array();
1160
+		foreach ($query_params as $key => $value) {
1161
+			if (is_array($value)) {
1162
+				$model_ready_query_params[$key] = $this->prepare_rest_query_params_values_for_models($model, $value);
1163
+			} else {
1164
+				$model_ready_query_params[$key] = $value;
1165
+			}
1166
+		}
1167
+		return $model_ready_query_params;
1168
+	}
1169
+
1170
+
1171
+
1172
+	/**
1173
+	 * Explodes the string on commas, and only returns items with $prefix followed by a period.
1174
+	 * If no prefix is specified, returns items with no period.
1175
+	 *
1176
+	 * @param string|array $string_to_explode eg "jibba,jabba, blah, blaabla" or array('jibba', 'jabba' )
1177
+	 * @param string       $prefix            "Event" or "foobar"
1178
+	 * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1179
+	 *                                        we only return strings starting with that and a period; if no prefix was
1180
+	 *                                        specified we return all items containing NO periods
1181
+	 */
1182
+	public function explode_and_get_items_prefixed_with($string_to_explode, $prefix)
1183
+	{
1184
+		if (is_string($string_to_explode)) {
1185
+			$exploded_contents = explode(',', $string_to_explode);
1186
+		} else if (is_array($string_to_explode)) {
1187
+			$exploded_contents = $string_to_explode;
1188
+		} else {
1189
+			$exploded_contents = array();
1190
+		}
1191
+		//if the string was empty, we want an empty array
1192
+		$exploded_contents = array_filter($exploded_contents);
1193
+		$contents_with_prefix = array();
1194
+		foreach ($exploded_contents as $item) {
1195
+			$item = trim($item);
1196
+			//if no prefix was provided, so we look for items with no "." in them
1197
+			if (! $prefix) {
1198
+				//does this item have a period?
1199
+				if (strpos($item, '.') === false) {
1200
+					//if not, then its what we're looking for
1201
+					$contents_with_prefix[] = $item;
1202
+				}
1203
+			} else if (strpos($item, $prefix . '.') === 0) {
1204
+				//this item has the prefix and a period, grab it
1205
+				$contents_with_prefix[] = substr(
1206
+					$item,
1207
+					strpos($item, $prefix . '.') + strlen($prefix . '.')
1208
+				);
1209
+			} else if ($item === $prefix) {
1210
+				//this item is JUST the prefix
1211
+				//so let's grab everything after, which is a blank string
1212
+				$contents_with_prefix[] = '';
1213
+			}
1214
+		}
1215
+		return $contents_with_prefix;
1216
+	}
1217
+
1218
+
1219
+
1220
+	/**
1221
+	 * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1222
+	 * Deprecated because its return values were really quite confusing- sometimes it returned
1223
+	 * an empty array (when the include string was blank or '*') or sometimes it returned
1224
+	 * array('*') (when you provided a model and a model of that kind was found).
1225
+	 * Parses the $include_string so we fetch all the field names relating to THIS model
1226
+	 * (ie have NO period in them), or for the provided model (ie start with the model
1227
+	 * name and then a period).
1228
+	 * @param string $include_string @see Read:handle_request_get_all
1229
+	 * @param string $model_name
1230
+	 * @return array of fields for this model. If $model_name is provided, then
1231
+	 *                               the fields for that model, with the model's name removed from each.
1232
+	 *                               If $include_string was blank or '*' returns an empty array
1233
+	 */
1234
+	public function extract_includes_for_this_model($include_string, $model_name = null)
1235
+	{
1236
+		if (is_array($include_string)) {
1237
+			$include_string = implode(',', $include_string);
1238
+		}
1239
+		if ($include_string === '*' || $include_string === '') {
1240
+			return array();
1241
+		}
1242
+		$includes = explode(',', $include_string);
1243
+		$extracted_fields_to_include = array();
1244
+		if ($model_name) {
1245
+			foreach ($includes as $field_to_include) {
1246
+				$field_to_include = trim($field_to_include);
1247
+				if (strpos($field_to_include, $model_name . '.') === 0) {
1248
+					//found the model name at the exact start
1249
+					$field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1250
+					$extracted_fields_to_include[] = $field_sans_model_name;
1251
+				} elseif ($field_to_include == $model_name) {
1252
+					$extracted_fields_to_include[] = '*';
1253
+				}
1254
+			}
1255
+		} else {
1256
+			//look for ones with no period
1257
+			foreach ($includes as $field_to_include) {
1258
+				$field_to_include = trim($field_to_include);
1259
+				if (
1260
+					strpos($field_to_include, '.') === false
1261
+					&& ! $this->get_model_version_info()->is_model_name_in_this_version($field_to_include)
1262
+				) {
1263
+					$extracted_fields_to_include[] = $field_to_include;
1264
+				}
1265
+			}
1266
+		}
1267
+		return $extracted_fields_to_include;
1268
+	}
1269 1269
 }
1270 1270
 
1271 1271
 
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -8,7 +8,7 @@  discard block
 block discarded – undo
8 8
 use EventEspresso\core\entities\models\JsonModelSchema;
9 9
 use EE_Datetime_Field;
10 10
 
11
-if (! defined('EVENT_ESPRESSO_VERSION')) {
11
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
12 12
     exit('No direct script access allowed');
13 13
 }
14 14
 
@@ -57,12 +57,12 @@  discard block
 block discarded – undo
57 57
         try {
58 58
             $matches = $controller->parse_route(
59 59
                 $request->get_route(),
60
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)~',
60
+                '~'.\EED_Core_Rest_Api::ee_api_namespace_for_regex.'(.*)~',
61 61
                 array('version', 'model')
62 62
             );
63 63
             $controller->set_requested_version($matches['version']);
64 64
             $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
65
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
65
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
66 66
                 return $controller->send_response(
67 67
                     new \WP_Error(
68 68
                         'endpoint_parsing_error',
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
         $controller = new Read();
100 100
         try {
101 101
             $controller->set_requested_version($version);
102
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name)) {
102
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($model_name)) {
103 103
                 return array();
104 104
             }
105 105
             //get the model for this version
@@ -193,9 +193,9 @@  discard block
 block discarded – undo
193 193
     protected function _maybe_add_extra_fields_to_schema($field_name, \EE_Model_Field_Base $field, array $schema)
194 194
     {
195 195
         if ($field instanceof EE_Datetime_Field) {
196
-            $schema['properties'][$field_name . '_gmt'] = $field->getSchema();
196
+            $schema['properties'][$field_name.'_gmt'] = $field->getSchema();
197 197
             //modify the description
198
-            $schema['properties'][$field_name . '_gmt']['description'] = sprintf(
198
+            $schema['properties'][$field_name.'_gmt']['description'] = sprintf(
199 199
                 esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
200 200
                 $field->get_nicename()
201 201
             );
@@ -236,11 +236,11 @@  discard block
 block discarded – undo
236 236
         try {
237 237
             $matches = $controller->parse_route(
238 238
                 $request->get_route(),
239
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)~',
239
+                '~'.\EED_Core_Rest_Api::ee_api_namespace_for_regex.'(.*)/(.*)~',
240 240
                 array('version', 'model', 'id'));
241 241
             $controller->set_requested_version($matches['version']);
242 242
             $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
243
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
243
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
244 244
                 return $controller->send_response(
245 245
                     new \WP_Error(
246 246
                         'endpoint_parsing_error',
@@ -278,12 +278,12 @@  discard block
 block discarded – undo
278 278
         try {
279 279
             $matches = $controller->parse_route(
280 280
                 $request->get_route(),
281
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)/(.*)~',
281
+                '~'.\EED_Core_Rest_Api::ee_api_namespace_for_regex.'(.*)/(.*)/(.*)~',
282 282
                 array('version', 'model', 'id', 'related_model')
283 283
             );
284 284
             $controller->set_requested_version($matches['version']);
285 285
             $main_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
286
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
286
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
287 287
                 return $controller->send_response(
288 288
                     new \WP_Error(
289 289
                         'endpoint_parsing_error',
@@ -298,11 +298,11 @@  discard block
 block discarded – undo
298 298
             $main_model = $controller->get_model_version_info()->load_model($main_model_name_singular);
299 299
             //assume the related model name is plural and try to find the model's name
300 300
             $related_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['related_model']);
301
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
301
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
302 302
                 //so the word didn't singularize well. Maybe that's just because it's a singular word?
303 303
                 $related_model_name_singular = \EEH_Inflector::humanize($matches['related_model']);
304 304
             }
305
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
305
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
306 306
                 return $controller->send_response(
307 307
                     new \WP_Error(
308 308
                         'endpoint_parsing_error',
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
     public function get_entities_from_model($model, $request)
339 339
     {
340 340
         $query_params = $this->create_model_query_params($model, $request->get_params());
341
-        if (! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
341
+        if ( ! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
342 342
             $model_name_plural = \EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
343 343
             return new \WP_Error(
344 344
                 sprintf('rest_%s_cannot_list', $model_name_plural),
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
                 array('status' => 403)
351 351
             );
352 352
         }
353
-        if (! $request->get_header('no_rest_headers')) {
353
+        if ( ! $request->get_header('no_rest_headers')) {
354 354
             $this->_set_headers_from_query_params($model, $query_params);
355 355
         }
356 356
         /** @type array $results */
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
         $context = $this->validate_context($request->get_param('caps'));
381 381
         $model = $relation->get_this_model();
382 382
         $related_model = $relation->get_other_model();
383
-        if (! isset($primary_model_query_params[0])) {
383
+        if ( ! isset($primary_model_query_params[0])) {
384 384
             $primary_model_query_params[0] = array();
385 385
         }
386 386
         //check if they can access the 1st model object
@@ -431,7 +431,7 @@  discard block
 block discarded – undo
431 431
         }
432 432
         $query_params['default_where_conditions'] = 'none';
433 433
         $query_params['caps'] = $context;
434
-        if (! $request->get_header('no_rest_headers')) {
434
+        if ( ! $request->get_header('no_rest_headers')) {
435 435
             $this->_set_headers_from_query_params($relation->get_other_model(), $query_params);
436 436
         }
437 437
         /** @type array $results */
@@ -483,7 +483,7 @@  discard block
 block discarded – undo
483 483
      */
484 484
     public function get_entities_from_relation($id, $relation, $request)
485 485
     {
486
-        if (! $relation->get_this_model()->has_primary_key_field()) {
486
+        if ( ! $relation->get_this_model()->has_primary_key_field()) {
487 487
             throw new \EE_Error(
488 488
                 sprintf(
489 489
                     __('Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
@@ -520,7 +520,7 @@  discard block
 block discarded – undo
520 520
         $this->_set_debug_info('missing caps',
521 521
             Capabilities::get_missing_permissions_string($model, $query_params['caps']));
522 522
         //normally the limit to a 2-part array, where the 2nd item is the limit
523
-        if (! isset($query_params['limit'])) {
523
+        if ( ! isset($query_params['limit'])) {
524 524
             $query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
525 525
         }
526 526
         if (is_array($query_params['limit'])) {
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
      */
555 555
     public function create_entity_from_wpdb_result($model, $db_row, $rest_request, $deprecated = null)
556 556
     {
557
-        if (! $rest_request instanceof \WP_REST_Request) {
557
+        if ( ! $rest_request instanceof \WP_REST_Request) {
558 558
             //ok so this was called in the old style, where the 3rd arg was
559 559
             //$include, and the 4th arg was $context
560 560
             //now setup the request just to avoid fatal errors, although we won't be able
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
                 if ($field_value instanceof \DateTime) {
642 642
                     $timezone = $field_value->getTimezone();
643 643
                     $field_value->setTimezone(new \DateTimeZone('UTC'));
644
-                    $result[$field_name . '_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
644
+                    $result[$field_name.'_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
645 645
                         $field_obj,
646 646
                         $field_value,
647 647
                         $this->get_model_version_info()->requested_version()
@@ -719,7 +719,7 @@  discard block
 block discarded – undo
719 719
         if ($model->has_primary_key_field()) {
720 720
             foreach ($this->get_model_version_info()->relation_settings($model) as $relation_name => $relation_obj) {
721 721
                 $related_model_part = Read::get_related_entity_name($relation_name, $relation_obj);
722
-                $links[\EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
722
+                $links[\EED_Core_Rest_Api::ee_api_link_namespace.$related_model_part] = array(
723 723
                     array(
724 724
                         'href'   => $this->get_versioned_link_to(
725 725
                             \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
@@ -754,13 +754,13 @@  discard block
 block discarded – undo
754 754
         $db_row = array()
755 755
     ) {
756 756
         //if $db_row not included, hope the entity array has what we need
757
-        if (! $db_row) {
757
+        if ( ! $db_row) {
758 758
             $db_row = $entity_array;
759 759
         }
760 760
         $includes_for_this_model = $this->explode_and_get_items_prefixed_with($rest_request->get_param('include'), '');
761 761
         $includes_for_this_model = $this->_remove_model_names_from_array($includes_for_this_model);
762 762
         //if they passed in * or didn't specify any includes, return everything
763
-        if (! in_array('*', $includes_for_this_model)
763
+        if ( ! in_array('*', $includes_for_this_model)
764 764
             && ! empty($includes_for_this_model)
765 765
         ) {
766 766
             if ($model->has_primary_key_field()) {
@@ -935,7 +935,7 @@  discard block
 block discarded – undo
935 935
         $restricted_query_params['caps'] = $this->validate_context($request->get_param('caps'));
936 936
         $this->_set_debug_info('model query params', $restricted_query_params);
937 937
         $model_rows = $model->get_all_wpdb_results($restricted_query_params);
938
-        if (! empty ($model_rows)) {
938
+        if ( ! empty ($model_rows)) {
939 939
             return $this->create_entity_from_wpdb_result(
940 940
                 $model,
941 941
                 array_shift($model_rows),
@@ -944,7 +944,7 @@  discard block
 block discarded – undo
944 944
             //ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
945 945
             $lowercase_model_name = strtolower($model->get_this_model_name());
946 946
             $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
947
-            if (! empty($model_rows_found_sans_restrictions)) {
947
+            if ( ! empty($model_rows_found_sans_restrictions)) {
948 948
                 //you got shafted- it existed but we didn't want to tell you!
949 949
                 return new \WP_Error(
950 950
                     'rest_user_cannot_read',
@@ -979,7 +979,7 @@  discard block
 block discarded – undo
979 979
      */
980 980
     public function validate_context($context)
981 981
     {
982
-        if (! $context) {
982
+        if ( ! $context) {
983 983
             $context = \EEM_Base::caps_read;
984 984
         }
985 985
         $valid_contexts = \EEM_Base::valid_cap_contexts();
@@ -1005,7 +1005,7 @@  discard block
 block discarded – undo
1005 1005
             \EEM_Base::default_where_conditions_minimum_all,
1006 1006
             \EEM_Base::default_where_conditions_minimum_others,
1007 1007
         );
1008
-        if (! $default_query_params) {
1008
+        if ( ! $default_query_params) {
1009 1009
             $default_query_params = \EEM_Base::default_where_conditions_all;
1010 1010
         }
1011 1011
         if (
@@ -1090,14 +1090,14 @@  discard block
 block discarded – undo
1090 1090
         }
1091 1091
         if (isset($query_parameters['limit'])) {
1092 1092
             //limit should be either a string like '23' or '23,43', or an array with two items in it
1093
-            if (! is_array($query_parameters['limit'])) {
1094
-                $limit_array = explode(',', (string)$query_parameters['limit']);
1093
+            if ( ! is_array($query_parameters['limit'])) {
1094
+                $limit_array = explode(',', (string) $query_parameters['limit']);
1095 1095
             } else {
1096 1096
                 $limit_array = $query_parameters['limit'];
1097 1097
             }
1098 1098
             $sanitized_limit = array();
1099 1099
             foreach ($limit_array as $key => $limit_part) {
1100
-                if ($this->_debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1100
+                if ($this->_debug_mode && ( ! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1101 1101
                     throw new \EE_Error(
1102 1102
                         sprintf(
1103 1103
                             __('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.',
@@ -1106,7 +1106,7 @@  discard block
 block discarded – undo
1106 1106
                         )
1107 1107
                     );
1108 1108
                 }
1109
-                $sanitized_limit[] = (int)$limit_part;
1109
+                $sanitized_limit[] = (int) $limit_part;
1110 1110
             }
1111 1111
             $model_query_params['limit'] = implode(',', $sanitized_limit);
1112 1112
         } else {
@@ -1194,17 +1194,17 @@  discard block
 block discarded – undo
1194 1194
         foreach ($exploded_contents as $item) {
1195 1195
             $item = trim($item);
1196 1196
             //if no prefix was provided, so we look for items with no "." in them
1197
-            if (! $prefix) {
1197
+            if ( ! $prefix) {
1198 1198
                 //does this item have a period?
1199 1199
                 if (strpos($item, '.') === false) {
1200 1200
                     //if not, then its what we're looking for
1201 1201
                     $contents_with_prefix[] = $item;
1202 1202
                 }
1203
-            } else if (strpos($item, $prefix . '.') === 0) {
1203
+            } else if (strpos($item, $prefix.'.') === 0) {
1204 1204
                 //this item has the prefix and a period, grab it
1205 1205
                 $contents_with_prefix[] = substr(
1206 1206
                     $item,
1207
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1207
+                    strpos($item, $prefix.'.') + strlen($prefix.'.')
1208 1208
                 );
1209 1209
             } else if ($item === $prefix) {
1210 1210
                 //this item is JUST the prefix
@@ -1244,9 +1244,9 @@  discard block
 block discarded – undo
1244 1244
         if ($model_name) {
1245 1245
             foreach ($includes as $field_to_include) {
1246 1246
                 $field_to_include = trim($field_to_include);
1247
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1247
+                if (strpos($field_to_include, $model_name.'.') === 0) {
1248 1248
                     //found the model name at the exact start
1249
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1249
+                    $field_sans_model_name = str_replace($model_name.'.', '', $field_to_include);
1250 1250
                     $extracted_fields_to_include[] = $field_sans_model_name;
1251 1251
                 } elseif ($field_to_include == $model_name) {
1252 1252
                     $extracted_fields_to_include[] = '*';
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/config/Read.php 2 patches
Indentation   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 namespace EventEspresso\core\libraries\rest_api\controllers\config;
3 3
 
4 4
 if (! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 
8 8
 
@@ -18,74 +18,74 @@  discard block
 block discarded – undo
18 18
 class Read
19 19
 {
20 20
 
21
-    /**
22
-     * @param \WP_REST_Request $request
23
-     * @return \EE_Config|\WP_Error
24
-     */
25
-    public static function handle_request(\WP_REST_Request $request)
26
-    {
27
-        $cap = \EE_Restriction_Generator_Base::get_default_restrictions_cap();
28
-        if (\EE_Capabilities::instance()->current_user_can($cap, 'read_over_api')) {
29
-            return \EE_Config::instance();
30
-        } else {
31
-            return new \WP_Error(
32
-                'cannot_read_config',
33
-                sprintf(
34
-                    __(
35
-                        'You do not have the necessary capabilities (%s) to read Event Espresso Configuration data',
36
-                        'event_espresso'
37
-                    ),
38
-                    $cap
39
-                ),
40
-                array('status' => 403)
41
-            );
42
-        }
43
-    }
21
+	/**
22
+	 * @param \WP_REST_Request $request
23
+	 * @return \EE_Config|\WP_Error
24
+	 */
25
+	public static function handle_request(\WP_REST_Request $request)
26
+	{
27
+		$cap = \EE_Restriction_Generator_Base::get_default_restrictions_cap();
28
+		if (\EE_Capabilities::instance()->current_user_can($cap, 'read_over_api')) {
29
+			return \EE_Config::instance();
30
+		} else {
31
+			return new \WP_Error(
32
+				'cannot_read_config',
33
+				sprintf(
34
+					__(
35
+						'You do not have the necessary capabilities (%s) to read Event Espresso Configuration data',
36
+						'event_espresso'
37
+					),
38
+					$cap
39
+				),
40
+				array('status' => 403)
41
+			);
42
+		}
43
+	}
44 44
 
45 45
 
46 46
 
47
-    /**
48
-     * Handles the request for public site info
49
-     *
50
-     * @global                 $wp_json_basic_auth_success       boolean set by the basic auth plugin, indicates if the
51
-     *                         current user could be authenticated using basic auth data
52
-     * @global                 $wp_json_basic_auth_received_data boolean set by the basic auth plugin, indicates if
53
-     *                         basic auth data was somehow received
54
-     * @param \WP_REST_Request $request
55
-     * @return \EE_Config|\WP_Error
56
-     */
57
-    public static function handle_request_site_info(\WP_REST_Request $request)
58
-    {
59
-        global $wp_json_basic_auth_success, $wp_json_basic_auth_received_data;
60
-        $insecure_usage_of_basic_auth = apply_filters(
61
-            'EventEspresso__core__libraries__rest_api__controllers__config__handle_request_site_info__insecure_usage_of_basic_auth',
62
-            $wp_json_basic_auth_success && ! is_ssl(),
63
-            $request
64
-        );
65
-        if ($insecure_usage_of_basic_auth) {
66
-            $warning = sprintf(
67
-                esc_html__('Your data is not secured with SSL. %1$sPlease see our recommendations.%2$s',
68
-                    'event_espresso'),
69
-                '<a href="https://eventespresso.com/wiki/rest-api-security-recommendations/">',
70
-                '</a>'
71
-            );
72
-        } else {
73
-            $warning = '';
74
-        }
75
-        return array(
76
-            'default_timezone' => array(
77
-                'pretty' => \EEH_DTT_Helper::get_timezone_string_for_display(),
78
-                'string' => get_option('timezone_string'),
79
-                'offset' => \EEH_DTT_Helper::get_site_timezone_gmt_offset(),
80
-            ),
81
-            'default_currency' => \EE_Config::instance()->currency,
82
-            'authentication'   => array(
83
-                'received_basic_auth_data'     => (bool)$wp_json_basic_auth_received_data,
84
-                'insecure_usage_of_basic_auth' => (bool)$insecure_usage_of_basic_auth,
85
-                'warning'                      => $warning
86
-            )
87
-        );
88
-    }
47
+	/**
48
+	 * Handles the request for public site info
49
+	 *
50
+	 * @global                 $wp_json_basic_auth_success       boolean set by the basic auth plugin, indicates if the
51
+	 *                         current user could be authenticated using basic auth data
52
+	 * @global                 $wp_json_basic_auth_received_data boolean set by the basic auth plugin, indicates if
53
+	 *                         basic auth data was somehow received
54
+	 * @param \WP_REST_Request $request
55
+	 * @return \EE_Config|\WP_Error
56
+	 */
57
+	public static function handle_request_site_info(\WP_REST_Request $request)
58
+	{
59
+		global $wp_json_basic_auth_success, $wp_json_basic_auth_received_data;
60
+		$insecure_usage_of_basic_auth = apply_filters(
61
+			'EventEspresso__core__libraries__rest_api__controllers__config__handle_request_site_info__insecure_usage_of_basic_auth',
62
+			$wp_json_basic_auth_success && ! is_ssl(),
63
+			$request
64
+		);
65
+		if ($insecure_usage_of_basic_auth) {
66
+			$warning = sprintf(
67
+				esc_html__('Your data is not secured with SSL. %1$sPlease see our recommendations.%2$s',
68
+					'event_espresso'),
69
+				'<a href="https://eventespresso.com/wiki/rest-api-security-recommendations/">',
70
+				'</a>'
71
+			);
72
+		} else {
73
+			$warning = '';
74
+		}
75
+		return array(
76
+			'default_timezone' => array(
77
+				'pretty' => \EEH_DTT_Helper::get_timezone_string_for_display(),
78
+				'string' => get_option('timezone_string'),
79
+				'offset' => \EEH_DTT_Helper::get_site_timezone_gmt_offset(),
80
+			),
81
+			'default_currency' => \EE_Config::instance()->currency,
82
+			'authentication'   => array(
83
+				'received_basic_auth_data'     => (bool)$wp_json_basic_auth_received_data,
84
+				'insecure_usage_of_basic_auth' => (bool)$insecure_usage_of_basic_auth,
85
+				'warning'                      => $warning
86
+			)
87
+		);
88
+	}
89 89
 }
90 90
 
91 91
 // End of file Read.php
92 92
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 namespace EventEspresso\core\libraries\rest_api\controllers\config;
3 3
 
4
-if (! defined('EVENT_ESPRESSO_VERSION')) {
4
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5 5
     exit('No direct script access allowed');
6 6
 }
7 7
 
@@ -80,8 +80,8 @@  discard block
 block discarded – undo
80 80
             ),
81 81
             'default_currency' => \EE_Config::instance()->currency,
82 82
             'authentication'   => array(
83
-                'received_basic_auth_data'     => (bool)$wp_json_basic_auth_received_data,
84
-                'insecure_usage_of_basic_auth' => (bool)$insecure_usage_of_basic_auth,
83
+                'received_basic_auth_data'     => (bool) $wp_json_basic_auth_received_data,
84
+                'insecure_usage_of_basic_auth' => (bool) $insecure_usage_of_basic_auth,
85 85
                 'warning'                      => $warning
86 86
             )
87 87
         );
Please login to merge, or discard this patch.
core/libraries/rest_api/changes/Changes_In_4_8_33.php 1 patch
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -7,60 +7,60 @@
 block discarded – undo
7 7
 class Changes_In_4_8_33 extends Changes_In_Base
8 8
 {
9 9
 
10
-    /**
11
-     * Adds hooks so requests to 4.8.29 don't have the checkin endpoints
12
-     */
13
-    public function set_hooks()
14
-    {
15
-        //set a hook to remove the checkout/checkout endpoints if the request 
16
-        //is for lower than 4.8.33
17
-        add_filter(
18
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
19
-            array($this, 'remove_checkin_routes_earlier_than_4_8_33'),
20
-            10,
21
-            2
22
-        );
23
-        add_filter(
24
-            'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_headers_from_ee_notices__return',
25
-            array($this, 'dont_add_headers_from_ee_notices'),
26
-            10,
27
-            2
28
-        );
29
-    }
10
+	/**
11
+	 * Adds hooks so requests to 4.8.29 don't have the checkin endpoints
12
+	 */
13
+	public function set_hooks()
14
+	{
15
+		//set a hook to remove the checkout/checkout endpoints if the request 
16
+		//is for lower than 4.8.33
17
+		add_filter(
18
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
19
+			array($this, 'remove_checkin_routes_earlier_than_4_8_33'),
20
+			10,
21
+			2
22
+		);
23
+		add_filter(
24
+			'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_headers_from_ee_notices__return',
25
+			array($this, 'dont_add_headers_from_ee_notices'),
26
+			10,
27
+			2
28
+		);
29
+	}
30 30
 
31 31
 
32 32
 
33
-    /**
34
-     * Removes the checkin and checkout endpoints from the index for requests
35
-     * to api versions lowers than 4.8.33
36
-     *
37
-     * @param array  $routes_on_this_version
38
-     * @param string $version
39
-     * @return array like $routes_on_this_version
40
-     */
41
-    public function remove_checkin_routes_earlier_than_4_8_33($routes_on_this_version, $version)
42
-    {
43
-        if ($this->applies_to_version($version)) {
44
-            unset($routes_on_this_version['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)']);
45
-        }
46
-        return $routes_on_this_version;
47
-    }
33
+	/**
34
+	 * Removes the checkin and checkout endpoints from the index for requests
35
+	 * to api versions lowers than 4.8.33
36
+	 *
37
+	 * @param array  $routes_on_this_version
38
+	 * @param string $version
39
+	 * @return array like $routes_on_this_version
40
+	 */
41
+	public function remove_checkin_routes_earlier_than_4_8_33($routes_on_this_version, $version)
42
+	{
43
+		if ($this->applies_to_version($version)) {
44
+			unset($routes_on_this_version['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)']);
45
+		}
46
+		return $routes_on_this_version;
47
+	}
48 48
 
49 49
 
50 50
 
51
-    /**
52
-     * We just added headers for notices in this version
53
-     *
54
-     * @param array  $headers_from_ee_notices
55
-     * @param string $requested_version
56
-     * @return array
57
-     */
58
-    public function dont_add_headers_from_ee_notices($headers_from_ee_notices, $requested_version)
59
-    {
60
-        if ($this->applies_to_version($requested_version)) {
61
-            return array();
62
-        }
63
-        return $headers_from_ee_notices;
64
-    }
51
+	/**
52
+	 * We just added headers for notices in this version
53
+	 *
54
+	 * @param array  $headers_from_ee_notices
55
+	 * @param string $requested_version
56
+	 * @return array
57
+	 */
58
+	public function dont_add_headers_from_ee_notices($headers_from_ee_notices, $requested_version)
59
+	{
60
+		if ($this->applies_to_version($requested_version)) {
61
+			return array();
62
+		}
63
+		return $headers_from_ee_notices;
64
+	}
65 65
 }
66 66
 
Please login to merge, or discard this patch.
modules/ticket_selector/TicketSelectorRowStandard.php 1 patch
Indentation   +398 added lines, -398 removed lines patch added patch discarded remove patch
@@ -19,404 +19,404 @@
 block discarded – undo
19 19
 class TicketSelectorRowStandard extends TicketSelectorRow
20 20
 {
21 21
 
22
-    /**
23
-     * @var TicketDetails $ticket_details
24
-     */
25
-    protected $ticket_details;
26
-
27
-    /**
28
-     * @var \EE_Ticket_Selector_Config $template_settings
29
-     */
30
-    protected $template_settings;
31
-
32
-    /**
33
-     * @var \EE_Tax_Config $tax_settings
34
-     */
35
-    protected $tax_settings;
36
-
37
-    /**
38
-     * @var boolean $prices_displayed_including_taxes
39
-     */
40
-    protected $prices_displayed_including_taxes;
41
-
42
-    /**
43
-     * @var int $row
44
-     */
45
-    protected $row;
46
-
47
-    /**
48
-     * @var int $cols
49
-     */
50
-    protected $cols;
51
-
52
-    /**
53
-     * @var boolean $hidden_input_qty
54
-     */
55
-    protected $hidden_input_qty;
56
-
57
-    /**
58
-     * @var string $ticket_datetime_classes
59
-     */
60
-    protected $ticket_datetime_classes;
61
-
62
-
63
-
64
-    /**
65
-     * TicketDetails constructor.
66
-     *
67
-     * @param TicketDetails  $ticket_details
68
-     * @param \EE_Tax_Config $tax_settings
69
-     * @param int            $total_tickets
70
-     * @param int            $max_atndz
71
-     * @param int            $row
72
-     * @param int            $cols
73
-     * @param boolean        $required_ticket_sold_out
74
-     * @param string         $event_status
75
-     * @param string         $ticket_datetime_classes
76
-     * @throws EE_Error
77
-     * @throws UnexpectedEntityException
78
-     */
79
-    public function __construct(
80
-        TicketDetails $ticket_details,
81
-        \EE_Tax_Config $tax_settings,
82
-        $total_tickets,
83
-        $max_atndz,
84
-        $row,
85
-        $cols,
86
-        $required_ticket_sold_out,
87
-        $event_status,
88
-        $ticket_datetime_classes
89
-    ) {
90
-        $this->ticket = $ticket_details->getTicket();
91
-        $this->ticket_details = $ticket_details;
92
-        $this->template_settings = $ticket_details->getTemplateSettings();
93
-        $this->tax_settings = $tax_settings;
94
-        $this->total_tickets = $total_tickets;
95
-        $this->max_atndz = $max_atndz;
96
-        $this->row = $row;
97
-        $this->cols = $cols;
98
-        $this->date_format = $ticket_details->getDateFormat();
99
-        $this->ticket_datetime_classes = $ticket_datetime_classes;
100
-        parent::__construct($this->ticket, $max_atndz, $this->date_format, $event_status, $required_ticket_sold_out);
101
-    }
102
-
103
-
104
-
105
-    /**
106
-     * other ticket rows will need to know if a required ticket is sold out,
107
-     * so that they are not offered for sale
108
-     *
109
-     * @return boolean
110
-     */
111
-    public function getRequiredTicketSoldOut()
112
-    {
113
-        return $this->required_ticket_sold_out;
114
-    }
115
-
116
-
117
-
118
-    /**
119
-     * @return int
120
-     */
121
-    public function getCols()
122
-    {
123
-        return $this->cols;
124
-    }
125
-
126
-
127
-
128
-    /**
129
-     * getHtml
130
-     *
131
-     * @return string
132
-     * @throws EE_Error
133
-     */
134
-    public function getHtml()
135
-    {
136
-        $min = 0;
137
-        $max = $this->ticket->max();
138
-        $remaining = $this->ticket->remaining();
139
-        if ($this->ticket->is_on_sale() && $this->ticket->is_remaining()) {
140
-            list($min, $max) = $this->setTicketMinAndMax($remaining);
141
-        } else {
142
-            // set flag if ticket is required (flag is set to start date so that future tickets are not blocked)
143
-            $this->required_ticket_sold_out = $this->ticket->required() && ! $remaining
144
-                ? $this->ticket->start_date()
145
-                : $this->required_ticket_sold_out;
146
-        }
147
-        list($ticket_price, $ticket_bundle) = $this->getTicketPriceDetails();
148
-        list($tkt_status, $ticket_status, $status_class) = $this->getTicketStatusClasses($remaining);
149
-        /**
150
-         * Allow plugins to hook in and abort the generation and display of this row to do
151
-         * something else if they want.
152
-         * For an addon to abort things, all they have to do is register a filter with this hook, and
153
-         * return a value that is NOT false.  Whatever is returned gets echoed instead of the
154
-         * current row.
155
-         *
156
-         * @var string|bool
157
-         */
158
-        $ticket_selector_row_html = apply_filters(
159
-            'FHEE__ticket_selector_chart_template__do_ticket_entire_row',
160
-            false,
161
-            $this->ticket,
162
-            $max,
163
-            $min,
164
-            $this->required_ticket_sold_out,
165
-            $ticket_price,
166
-            $ticket_bundle,
167
-            $ticket_status,
168
-            $status_class
169
-        );
170
-        if ($ticket_selector_row_html !== false) {
171
-            return $ticket_selector_row_html;
172
-        }
173
-        $ticket_selector_row_html = \EEH_HTML::tr(
174
-            '', '',
175
-            "tckt-slctr-tbl-tr {$status_class}{$this->ticket_datetime_classes} " . espresso_get_object_css_class($this->ticket)
176
-        );
177
-        /**
178
-         * Allow plugins to hook in and abort the generation and display of the contents of this
179
-         * row to do something else if they want.
180
-         * For an addon to abort things, all they have to do is register a filter with this hook, and
181
-         * return a value that is NOT false.  Whatever is returned gets echoed instead of the
182
-         * current row.
183
-         *
184
-         * @var string|bool
185
-         */
186
-        $new_row_cells_content = apply_filters(
187
-            'FHEE__ticket_selector_chart_template__do_ticket_inside_row',
188
-            false,
189
-            $this->ticket,
190
-            $max,
191
-            $min,
192
-            $this->required_ticket_sold_out,
193
-            $ticket_price,
194
-            $ticket_bundle,
195
-            $ticket_status,
196
-            $status_class
197
-        );
198
-        if ($new_row_cells_content !== false && $this->max_atndz === 1) {
199
-            return $ticket_selector_row_html
200
-                   . $new_row_cells_content
201
-                   . $this->ticketQtyAndIdHiddenInputs()
202
-                   . \EEH_HTML::trx();
203
-        }
204
-        if ($new_row_cells_content !== false) {
205
-            return $ticket_selector_row_html
206
-                   . $new_row_cells_content
207
-                   . \EEH_HTML::trx();
208
-        }
209
-        $this->hidden_input_qty = $this->max_atndz > 1 ? true : false;
210
-
211
-        $ticket_selector_row_html .= $this->ticketNameTableCell();
212
-        $ticket_selector_row_html .= $this->ticketPriceTableCell($ticket_price, $ticket_bundle);
213
-        $ticket_selector_row_html .= \EEH_HTML::td('', '', 'tckt-slctr-tbl-td-qty cntr');
214
-        $this->setTicketStatusDisplay($tkt_status, $ticket_status, $remaining);
215
-        if (empty($this->ticket_status_display)) {
216
-            if ($this->max_atndz === 1) {
217
-                // only ONE attendee is allowed to register at a time
218
-                $ticket_selector_row_html .= $this->onlyOneAttendeeCanRegister();
219
-            } else if ($max > 0) {
220
-                $ticket_selector_row_html .= $this->ticketQuantitySelector($min, $max);
221
-            }
222
-        }
223
-        $ticket_selector_row_html .= $this->ticket_status_display;
224
-        $ticket_selector_row_html .= $this->ticketQtyAndIdHiddenInputs();
225
-        $ticket_selector_row_html .= $this->ticket_details->display($ticket_price, $remaining, $this->cols);
226
-        $ticket_selector_row_html .= \EEH_HTML::tdx();
227
-        $ticket_selector_row_html .= \EEH_HTML::trx();
228
-
229
-
230
-        $this->row++;
231
-        return $ticket_selector_row_html;
232
-    }
233
-
234
-
235
-
236
-    /**
237
-     * setTicketMinAndMax
238
-     *
239
-     * @param int $remaining
240
-     * @return array
241
-     * @throws EE_Error
242
-     */
243
-    protected function setTicketMinAndMax($remaining)
244
-    {
245
-        // offer the number of $tickets_remaining or $this->max_atndz, whichever is smaller
246
-        $max = min($remaining, $this->max_atndz);
247
-        // but... we also want to restrict the number of tickets by the ticket max setting,
248
-        // however, the max still can't be higher than what was just set above
249
-        $max = $this->ticket->max() > 0 ? min($this->ticket->max(), $max) : $max;
250
-        // and we also want to restrict the minimum number of tickets by the ticket min setting
251
-        $min = $this->ticket->min() > 0 ? $this->ticket->min() : 0;
252
-        // and if the ticket is required, then make sure that min qty is at least 1
253
-        $min = $this->ticket->required() ? max($min, 1) : $min;
254
-        return array($min, $max);
255
-    }
256
-
257
-
258
-
259
-    /**
260
-     * getTicketPriceDetails
261
-     *
262
-     * @return array
263
-     * @throws EE_Error
264
-     */
265
-    protected function getTicketPriceDetails()
266
-    {
267
-        $ticket_price = $this->tax_settings->prices_displayed_including_taxes
268
-            ? $this->ticket->get_ticket_total_with_taxes()
269
-            : $this->ticket->get_ticket_subtotal();
270
-        $ticket_bundle = false;
271
-        $ticket_min = $this->ticket->min();
272
-        // for ticket bundles, set min and max qty the same
273
-        if ($ticket_min !== 0 && $ticket_min === $this->ticket->max()) {
274
-            $ticket_price *= $ticket_min;
275
-            $ticket_bundle = true;
276
-        }
277
-        $ticket_price = apply_filters(
278
-            'FHEE__ticket_selector_chart_template__ticket_price',
279
-            $ticket_price,
280
-            $this->ticket
281
-        );
282
-        return array($ticket_price, $ticket_bundle);
283
-    }
284
-
285
-
286
-
287
-
288
-    /**
289
-     * ticketNameTableCell
290
-     *
291
-     * @return string
292
-     * @throws EE_Error
293
-     */
294
-    protected function ticketNameTableCell()
295
-    {
296
-        $html = \EEH_HTML::td('', '', 'tckt-slctr-tbl-td-name');
297
-        $html .= \EEH_HTML::strong($this->ticket->get_pretty('TKT_name'));
298
-        $html .= $this->ticket_details->getShowHideLinks();
299
-        if ($this->ticket->required()) {
300
-            $html .= \EEH_HTML::p(
301
-                    apply_filters(
302
-                            'FHEE__ticket_selector_chart_template__ticket_required_message',
303
-                            esc_html__('This ticket is required and must be purchased.', 'event_espresso')
304
-                    ),
305
-                    '', 'ticket-required-pg'
306
-            );
307
-        }
308
-        $html .= \EEH_HTML::tdx();
309
-        return $html;
310
-    }
311
-
312
-
313
-
314
-    /**
315
-     * ticketPriceTableCell
316
-     *
317
-     * @param float $ticket_price
318
-     * @param bool  $ticket_bundle
319
-     * @return string
320
-     * @throws EE_Error
321
-     */
322
-    protected function ticketPriceTableCell($ticket_price, $ticket_bundle)
323
-    {
324
-        $html = '';
325
-        if (apply_filters('FHEE__ticket_selector_chart_template__display_ticket_price_details', true)) {
326
-            $html .= \EEH_HTML::td('', '', 'tckt-slctr-tbl-td-price jst-rght');
327
-            $html .= \EEH_Template::format_currency($ticket_price);
328
-            $html .= $this->ticket->taxable()
329
-                ? \EEH_HTML::span( '*', '', 'taxable-tickets-asterisk grey-text' )
330
-                : '';
331
-            $html .= '&nbsp;';
332
-            $html .= \EEH_HTML::span(
333
-                $ticket_bundle
334
-                    ? apply_filters(
335
-                        'FHEE__ticket_selector_chart_template__per_ticket_bundle_text',
336
-                        __(' / bundle', 'event_espresso')
337
-                    )
338
-                    : apply_filters(
339
-                        'FHEE__ticket_selector_chart_template__per_ticket_text',
340
-                        __('', 'event_espresso')
341
-                    ),
342
-                '', 'smaller-text no-bold'
343
-            );
344
-            $html .= '&nbsp;';
345
-            $html .= \EEH_HTML::tdx();
346
-            $this->cols++;
347
-        }
348
-        return $html;
349
-    }
350
-
351
-
352
-
353
-    /**
354
-     * onlyOneAttendeeCanRegister
355
-     *
356
-     * @return string
357
-     */
358
-    protected function onlyOneAttendeeCanRegister()
359
-    {
360
-        // display submit button since we have tickets available
361
-        add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
362
-        $this->hidden_input_qty = false;
363
-        $html = '<input type="radio" name="tkt-slctr-qty-' . $this->EVT_ID . '"';
364
-        $html .= ' id="ticket-selector-tbl-qty-slct-' . $this->EVT_ID . '-' . $this->row . '"';
365
-        $html .= ' class="ticket-selector-tbl-qty-slct" value="' . $this->row . '-1"';
366
-        $html .= $this->total_tickets === 1 ? ' checked="checked"' : '';
367
-        $html .= ' title=""/>';
368
-        return $html;
369
-    }
370
-
371
-
372
-
373
-    /**
374
-     * ticketQuantitySelector
375
-     *
376
-     * @param int $min
377
-     * @param int $max
378
-     * @return string
379
-     * @throws EE_Error
380
-     */
381
-    protected function ticketQuantitySelector($min = 0, $max = 0)
382
-    {
383
-        // display submit button since we have tickets available
384
-        add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
385
-        $this->hidden_input_qty = false;
386
-        $html = '<select name="tkt-slctr-qty-' . $this->EVT_ID . '[]"';
387
-        $html .= ' id="ticket-selector-tbl-qty-slct-' . $this->EVT_ID . '-' . $this->row . '"';
388
-        $html .= ' class="ticket-selector-tbl-qty-slct">';
389
-        // this ensures that non-required tickets with non-zero MIN QTYs don't HAVE to be purchased
390
-        if ($min !== 0 && ! $this->ticket->required()) {
391
-            $html .= '<option value="0">&nbsp;0&nbsp;</option>';
392
-        }
393
-        // offer ticket quantities from the min to the max
394
-        for ($i = $min; $i <= $max; $i++) {
395
-            $html .= '<option value="' . $i . '">&nbsp;' . $i . '&nbsp;</option>';
396
-        }
397
-        $html .= '</select>';
398
-        return $html;
399
-    }
400
-
401
-
402
-
403
-    /**
404
-     * getHiddenInputs
405
-     *
406
-     * @return string
407
-     * @throws EE_Error
408
-     */
409
-    protected function ticketQtyAndIdHiddenInputs()
410
-    {
411
-        $html = '';
412
-        // depending on group reg we need to change the format for qty
413
-        if ($this->hidden_input_qty) {
414
-            $html .= '<input type="hidden" name="tkt-slctr-qty-' . $this->EVT_ID . '[]" value="0"/>';
415
-        }
416
-        $html .= '<input type="hidden" name="tkt-slctr-ticket-id-' . $this->EVT_ID . '[]"';
417
-        $html .= ' value="' . $this->ticket->ID() . '"/>';
418
-        return $html;
419
-    }
22
+	/**
23
+	 * @var TicketDetails $ticket_details
24
+	 */
25
+	protected $ticket_details;
26
+
27
+	/**
28
+	 * @var \EE_Ticket_Selector_Config $template_settings
29
+	 */
30
+	protected $template_settings;
31
+
32
+	/**
33
+	 * @var \EE_Tax_Config $tax_settings
34
+	 */
35
+	protected $tax_settings;
36
+
37
+	/**
38
+	 * @var boolean $prices_displayed_including_taxes
39
+	 */
40
+	protected $prices_displayed_including_taxes;
41
+
42
+	/**
43
+	 * @var int $row
44
+	 */
45
+	protected $row;
46
+
47
+	/**
48
+	 * @var int $cols
49
+	 */
50
+	protected $cols;
51
+
52
+	/**
53
+	 * @var boolean $hidden_input_qty
54
+	 */
55
+	protected $hidden_input_qty;
56
+
57
+	/**
58
+	 * @var string $ticket_datetime_classes
59
+	 */
60
+	protected $ticket_datetime_classes;
61
+
62
+
63
+
64
+	/**
65
+	 * TicketDetails constructor.
66
+	 *
67
+	 * @param TicketDetails  $ticket_details
68
+	 * @param \EE_Tax_Config $tax_settings
69
+	 * @param int            $total_tickets
70
+	 * @param int            $max_atndz
71
+	 * @param int            $row
72
+	 * @param int            $cols
73
+	 * @param boolean        $required_ticket_sold_out
74
+	 * @param string         $event_status
75
+	 * @param string         $ticket_datetime_classes
76
+	 * @throws EE_Error
77
+	 * @throws UnexpectedEntityException
78
+	 */
79
+	public function __construct(
80
+		TicketDetails $ticket_details,
81
+		\EE_Tax_Config $tax_settings,
82
+		$total_tickets,
83
+		$max_atndz,
84
+		$row,
85
+		$cols,
86
+		$required_ticket_sold_out,
87
+		$event_status,
88
+		$ticket_datetime_classes
89
+	) {
90
+		$this->ticket = $ticket_details->getTicket();
91
+		$this->ticket_details = $ticket_details;
92
+		$this->template_settings = $ticket_details->getTemplateSettings();
93
+		$this->tax_settings = $tax_settings;
94
+		$this->total_tickets = $total_tickets;
95
+		$this->max_atndz = $max_atndz;
96
+		$this->row = $row;
97
+		$this->cols = $cols;
98
+		$this->date_format = $ticket_details->getDateFormat();
99
+		$this->ticket_datetime_classes = $ticket_datetime_classes;
100
+		parent::__construct($this->ticket, $max_atndz, $this->date_format, $event_status, $required_ticket_sold_out);
101
+	}
102
+
103
+
104
+
105
+	/**
106
+	 * other ticket rows will need to know if a required ticket is sold out,
107
+	 * so that they are not offered for sale
108
+	 *
109
+	 * @return boolean
110
+	 */
111
+	public function getRequiredTicketSoldOut()
112
+	{
113
+		return $this->required_ticket_sold_out;
114
+	}
115
+
116
+
117
+
118
+	/**
119
+	 * @return int
120
+	 */
121
+	public function getCols()
122
+	{
123
+		return $this->cols;
124
+	}
125
+
126
+
127
+
128
+	/**
129
+	 * getHtml
130
+	 *
131
+	 * @return string
132
+	 * @throws EE_Error
133
+	 */
134
+	public function getHtml()
135
+	{
136
+		$min = 0;
137
+		$max = $this->ticket->max();
138
+		$remaining = $this->ticket->remaining();
139
+		if ($this->ticket->is_on_sale() && $this->ticket->is_remaining()) {
140
+			list($min, $max) = $this->setTicketMinAndMax($remaining);
141
+		} else {
142
+			// set flag if ticket is required (flag is set to start date so that future tickets are not blocked)
143
+			$this->required_ticket_sold_out = $this->ticket->required() && ! $remaining
144
+				? $this->ticket->start_date()
145
+				: $this->required_ticket_sold_out;
146
+		}
147
+		list($ticket_price, $ticket_bundle) = $this->getTicketPriceDetails();
148
+		list($tkt_status, $ticket_status, $status_class) = $this->getTicketStatusClasses($remaining);
149
+		/**
150
+		 * Allow plugins to hook in and abort the generation and display of this row to do
151
+		 * something else if they want.
152
+		 * For an addon to abort things, all they have to do is register a filter with this hook, and
153
+		 * return a value that is NOT false.  Whatever is returned gets echoed instead of the
154
+		 * current row.
155
+		 *
156
+		 * @var string|bool
157
+		 */
158
+		$ticket_selector_row_html = apply_filters(
159
+			'FHEE__ticket_selector_chart_template__do_ticket_entire_row',
160
+			false,
161
+			$this->ticket,
162
+			$max,
163
+			$min,
164
+			$this->required_ticket_sold_out,
165
+			$ticket_price,
166
+			$ticket_bundle,
167
+			$ticket_status,
168
+			$status_class
169
+		);
170
+		if ($ticket_selector_row_html !== false) {
171
+			return $ticket_selector_row_html;
172
+		}
173
+		$ticket_selector_row_html = \EEH_HTML::tr(
174
+			'', '',
175
+			"tckt-slctr-tbl-tr {$status_class}{$this->ticket_datetime_classes} " . espresso_get_object_css_class($this->ticket)
176
+		);
177
+		/**
178
+		 * Allow plugins to hook in and abort the generation and display of the contents of this
179
+		 * row to do something else if they want.
180
+		 * For an addon to abort things, all they have to do is register a filter with this hook, and
181
+		 * return a value that is NOT false.  Whatever is returned gets echoed instead of the
182
+		 * current row.
183
+		 *
184
+		 * @var string|bool
185
+		 */
186
+		$new_row_cells_content = apply_filters(
187
+			'FHEE__ticket_selector_chart_template__do_ticket_inside_row',
188
+			false,
189
+			$this->ticket,
190
+			$max,
191
+			$min,
192
+			$this->required_ticket_sold_out,
193
+			$ticket_price,
194
+			$ticket_bundle,
195
+			$ticket_status,
196
+			$status_class
197
+		);
198
+		if ($new_row_cells_content !== false && $this->max_atndz === 1) {
199
+			return $ticket_selector_row_html
200
+				   . $new_row_cells_content
201
+				   . $this->ticketQtyAndIdHiddenInputs()
202
+				   . \EEH_HTML::trx();
203
+		}
204
+		if ($new_row_cells_content !== false) {
205
+			return $ticket_selector_row_html
206
+				   . $new_row_cells_content
207
+				   . \EEH_HTML::trx();
208
+		}
209
+		$this->hidden_input_qty = $this->max_atndz > 1 ? true : false;
210
+
211
+		$ticket_selector_row_html .= $this->ticketNameTableCell();
212
+		$ticket_selector_row_html .= $this->ticketPriceTableCell($ticket_price, $ticket_bundle);
213
+		$ticket_selector_row_html .= \EEH_HTML::td('', '', 'tckt-slctr-tbl-td-qty cntr');
214
+		$this->setTicketStatusDisplay($tkt_status, $ticket_status, $remaining);
215
+		if (empty($this->ticket_status_display)) {
216
+			if ($this->max_atndz === 1) {
217
+				// only ONE attendee is allowed to register at a time
218
+				$ticket_selector_row_html .= $this->onlyOneAttendeeCanRegister();
219
+			} else if ($max > 0) {
220
+				$ticket_selector_row_html .= $this->ticketQuantitySelector($min, $max);
221
+			}
222
+		}
223
+		$ticket_selector_row_html .= $this->ticket_status_display;
224
+		$ticket_selector_row_html .= $this->ticketQtyAndIdHiddenInputs();
225
+		$ticket_selector_row_html .= $this->ticket_details->display($ticket_price, $remaining, $this->cols);
226
+		$ticket_selector_row_html .= \EEH_HTML::tdx();
227
+		$ticket_selector_row_html .= \EEH_HTML::trx();
228
+
229
+
230
+		$this->row++;
231
+		return $ticket_selector_row_html;
232
+	}
233
+
234
+
235
+
236
+	/**
237
+	 * setTicketMinAndMax
238
+	 *
239
+	 * @param int $remaining
240
+	 * @return array
241
+	 * @throws EE_Error
242
+	 */
243
+	protected function setTicketMinAndMax($remaining)
244
+	{
245
+		// offer the number of $tickets_remaining or $this->max_atndz, whichever is smaller
246
+		$max = min($remaining, $this->max_atndz);
247
+		// but... we also want to restrict the number of tickets by the ticket max setting,
248
+		// however, the max still can't be higher than what was just set above
249
+		$max = $this->ticket->max() > 0 ? min($this->ticket->max(), $max) : $max;
250
+		// and we also want to restrict the minimum number of tickets by the ticket min setting
251
+		$min = $this->ticket->min() > 0 ? $this->ticket->min() : 0;
252
+		// and if the ticket is required, then make sure that min qty is at least 1
253
+		$min = $this->ticket->required() ? max($min, 1) : $min;
254
+		return array($min, $max);
255
+	}
256
+
257
+
258
+
259
+	/**
260
+	 * getTicketPriceDetails
261
+	 *
262
+	 * @return array
263
+	 * @throws EE_Error
264
+	 */
265
+	protected function getTicketPriceDetails()
266
+	{
267
+		$ticket_price = $this->tax_settings->prices_displayed_including_taxes
268
+			? $this->ticket->get_ticket_total_with_taxes()
269
+			: $this->ticket->get_ticket_subtotal();
270
+		$ticket_bundle = false;
271
+		$ticket_min = $this->ticket->min();
272
+		// for ticket bundles, set min and max qty the same
273
+		if ($ticket_min !== 0 && $ticket_min === $this->ticket->max()) {
274
+			$ticket_price *= $ticket_min;
275
+			$ticket_bundle = true;
276
+		}
277
+		$ticket_price = apply_filters(
278
+			'FHEE__ticket_selector_chart_template__ticket_price',
279
+			$ticket_price,
280
+			$this->ticket
281
+		);
282
+		return array($ticket_price, $ticket_bundle);
283
+	}
284
+
285
+
286
+
287
+
288
+	/**
289
+	 * ticketNameTableCell
290
+	 *
291
+	 * @return string
292
+	 * @throws EE_Error
293
+	 */
294
+	protected function ticketNameTableCell()
295
+	{
296
+		$html = \EEH_HTML::td('', '', 'tckt-slctr-tbl-td-name');
297
+		$html .= \EEH_HTML::strong($this->ticket->get_pretty('TKT_name'));
298
+		$html .= $this->ticket_details->getShowHideLinks();
299
+		if ($this->ticket->required()) {
300
+			$html .= \EEH_HTML::p(
301
+					apply_filters(
302
+							'FHEE__ticket_selector_chart_template__ticket_required_message',
303
+							esc_html__('This ticket is required and must be purchased.', 'event_espresso')
304
+					),
305
+					'', 'ticket-required-pg'
306
+			);
307
+		}
308
+		$html .= \EEH_HTML::tdx();
309
+		return $html;
310
+	}
311
+
312
+
313
+
314
+	/**
315
+	 * ticketPriceTableCell
316
+	 *
317
+	 * @param float $ticket_price
318
+	 * @param bool  $ticket_bundle
319
+	 * @return string
320
+	 * @throws EE_Error
321
+	 */
322
+	protected function ticketPriceTableCell($ticket_price, $ticket_bundle)
323
+	{
324
+		$html = '';
325
+		if (apply_filters('FHEE__ticket_selector_chart_template__display_ticket_price_details', true)) {
326
+			$html .= \EEH_HTML::td('', '', 'tckt-slctr-tbl-td-price jst-rght');
327
+			$html .= \EEH_Template::format_currency($ticket_price);
328
+			$html .= $this->ticket->taxable()
329
+				? \EEH_HTML::span( '*', '', 'taxable-tickets-asterisk grey-text' )
330
+				: '';
331
+			$html .= '&nbsp;';
332
+			$html .= \EEH_HTML::span(
333
+				$ticket_bundle
334
+					? apply_filters(
335
+						'FHEE__ticket_selector_chart_template__per_ticket_bundle_text',
336
+						__(' / bundle', 'event_espresso')
337
+					)
338
+					: apply_filters(
339
+						'FHEE__ticket_selector_chart_template__per_ticket_text',
340
+						__('', 'event_espresso')
341
+					),
342
+				'', 'smaller-text no-bold'
343
+			);
344
+			$html .= '&nbsp;';
345
+			$html .= \EEH_HTML::tdx();
346
+			$this->cols++;
347
+		}
348
+		return $html;
349
+	}
350
+
351
+
352
+
353
+	/**
354
+	 * onlyOneAttendeeCanRegister
355
+	 *
356
+	 * @return string
357
+	 */
358
+	protected function onlyOneAttendeeCanRegister()
359
+	{
360
+		// display submit button since we have tickets available
361
+		add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
362
+		$this->hidden_input_qty = false;
363
+		$html = '<input type="radio" name="tkt-slctr-qty-' . $this->EVT_ID . '"';
364
+		$html .= ' id="ticket-selector-tbl-qty-slct-' . $this->EVT_ID . '-' . $this->row . '"';
365
+		$html .= ' class="ticket-selector-tbl-qty-slct" value="' . $this->row . '-1"';
366
+		$html .= $this->total_tickets === 1 ? ' checked="checked"' : '';
367
+		$html .= ' title=""/>';
368
+		return $html;
369
+	}
370
+
371
+
372
+
373
+	/**
374
+	 * ticketQuantitySelector
375
+	 *
376
+	 * @param int $min
377
+	 * @param int $max
378
+	 * @return string
379
+	 * @throws EE_Error
380
+	 */
381
+	protected function ticketQuantitySelector($min = 0, $max = 0)
382
+	{
383
+		// display submit button since we have tickets available
384
+		add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
385
+		$this->hidden_input_qty = false;
386
+		$html = '<select name="tkt-slctr-qty-' . $this->EVT_ID . '[]"';
387
+		$html .= ' id="ticket-selector-tbl-qty-slct-' . $this->EVT_ID . '-' . $this->row . '"';
388
+		$html .= ' class="ticket-selector-tbl-qty-slct">';
389
+		// this ensures that non-required tickets with non-zero MIN QTYs don't HAVE to be purchased
390
+		if ($min !== 0 && ! $this->ticket->required()) {
391
+			$html .= '<option value="0">&nbsp;0&nbsp;</option>';
392
+		}
393
+		// offer ticket quantities from the min to the max
394
+		for ($i = $min; $i <= $max; $i++) {
395
+			$html .= '<option value="' . $i . '">&nbsp;' . $i . '&nbsp;</option>';
396
+		}
397
+		$html .= '</select>';
398
+		return $html;
399
+	}
400
+
401
+
402
+
403
+	/**
404
+	 * getHiddenInputs
405
+	 *
406
+	 * @return string
407
+	 * @throws EE_Error
408
+	 */
409
+	protected function ticketQtyAndIdHiddenInputs()
410
+	{
411
+		$html = '';
412
+		// depending on group reg we need to change the format for qty
413
+		if ($this->hidden_input_qty) {
414
+			$html .= '<input type="hidden" name="tkt-slctr-qty-' . $this->EVT_ID . '[]" value="0"/>';
415
+		}
416
+		$html .= '<input type="hidden" name="tkt-slctr-ticket-id-' . $this->EVT_ID . '[]"';
417
+		$html .= ' value="' . $this->ticket->ID() . '"/>';
418
+		return $html;
419
+	}
420 420
 
421 421
 }
422 422
 // End of file TicketSelectorRowStandard.php
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/rpc/Checkin.php 2 patches
Indentation   +110 added lines, -110 removed lines patch added patch discarded remove patch
@@ -14,7 +14,7 @@  discard block
 block discarded – undo
14 14
 use EventEspresso\core\libraries\rest_api\controllers\model\Read;
15 15
 
16 16
 if (! defined('EVENT_ESPRESSO_VERSION')) {
17
-    exit('No direct script access allowed');
17
+	exit('No direct script access allowed');
18 18
 }
19 19
 
20 20
 
@@ -31,116 +31,116 @@  discard block
 block discarded – undo
31 31
 class Checkin extends Base
32 32
 {
33 33
 
34
-    /**
35
-     * @param WP_REST_Request $request
36
-     * @return WP_Error|WP_REST_Response
37
-     */
38
-    public static function handle_request_toggle_checkin(WP_REST_Request $request)
39
-    {
40
-        $controller = new Checkin();
41
-        return $controller->_create_checkin_checkout_object($request);
42
-    }
34
+	/**
35
+	 * @param WP_REST_Request $request
36
+	 * @return WP_Error|WP_REST_Response
37
+	 */
38
+	public static function handle_request_toggle_checkin(WP_REST_Request $request)
39
+	{
40
+		$controller = new Checkin();
41
+		return $controller->_create_checkin_checkout_object($request);
42
+	}
43 43
 
44 44
 
45 45
 
46
-    /**
47
-     * Toggles whether the user is checked in or not.
48
-     *
49
-     * @param WP_REST_Request $request
50
-     * @return WP_Error|WP_REST_Response
51
-     */
52
-    protected function _create_checkin_checkout_object(WP_REST_Request $request)
53
-    {
54
-        $reg_id = $request->get_param('REG_ID');
55
-        $dtt_id = $request->get_param('DTT_ID');
56
-        $force = $request->get_param('force');
57
-        if ($force == 'true') {
58
-            $force = true;
59
-        } else {
60
-            $force = false;
61
-        }
62
-        $reg = EEM_Registration::instance()->get_one_by_ID($reg_id);
63
-        if (! $reg instanceof EE_Registration) {
64
-            return $this->send_response(
65
-                new WP_Error(
66
-                    'rest_registration_toggle_checkin_invalid_id',
67
-                    sprintf(
68
-                        __('You cannot checkin registration with ID %1$s because it doesn\'t exist.',
69
-                            'event_espresso'),
70
-                        $reg_id
71
-                    ),
72
-                    array('status' => 422)
73
-                )
74
-            );
75
-        }
76
-        if (! EE_Capabilities::instance()
77
-                             ->current_user_can('ee_edit_checkin', 'rest_api_checkin_endpoint', $reg_id)
78
-        ) {
79
-            return $this->send_response(
80
-                new WP_Error(
81
-                    'rest_user_cannot_toggle_checkin',
82
-                    sprintf(
83
-                        __('You are not allowed to checkin registration with ID %1$s.', 'event_espresso'),
84
-                        $reg_id
85
-                    ),
86
-                    array('status' => 403)
87
-                )
88
-            );
89
-        }
90
-        $success = $reg->toggle_checkin_status($dtt_id, ! $force);
91
-        if ($success === false) {
92
-            //check if we know they can't check in because they're not approved and we aren't forcing
93
-            if (! $reg->is_approved() && ! $force) {
94
-                //rely on EE_Error::add_error messages to have been added to give more data about why it failed
95
-                return $this->send_response(
96
-                    new WP_Error(
97
-                        'rest_toggle_checkin_failed',
98
-                        __('Registration check-in failed because the registration is not approved. You may attempt to force checking in though.',
99
-                            'event_espresso')
100
-                    )
101
-                );
102
-            }
103
-            return $this->send_response(
104
-                new WP_Error(
105
-                    'rest_toggle_checkin_failed_not_forceable',
106
-                    __('Registration checkin failed. Please see additional error data.', 'event_espresso')
107
-                )
108
-            );
109
-        }
110
-        $checkin = EEM_Checkin::instance()->get_one(
111
-            array(
112
-                array(
113
-                    'REG_ID' => $reg_id,
114
-                    'DTT_ID' => $dtt_id,
115
-                ),
116
-                'order_by' => array(
117
-                    'CHK_timestamp' => 'DESC',
118
-                ),
119
-            )
120
-        );
121
-        if (! $checkin instanceof EE_Checkin) {
122
-            return $this->send_response(
123
-                new WP_Error(
124
-                    'rest_toggle_checkin_error',
125
-                    sprintf(
126
-                        __('Supposedly we created a new checkin object for registration %1$s at datetime %2$s, but we can\'t find it.',
127
-                            'event_espresso'),
128
-                        $reg_id,
129
-                        $dtt_id
130
-                    )
131
-                )
132
-            );
133
-        }
134
-        $requested_version = $this->get_requested_version($request->get_route());
135
-        $get_request = new WP_REST_Request(
136
-            'GET',
137
-            EED_Core_Rest_Api::ee_api_namespace . $requested_version . '/checkins/' . $checkin->ID()
138
-        );
139
-        $get_request->set_url_params(
140
-            array(
141
-                'id' => $checkin->ID(),
142
-            )
143
-        );
144
-        return Read::handle_request_get_one($get_request);
145
-    }
46
+	/**
47
+	 * Toggles whether the user is checked in or not.
48
+	 *
49
+	 * @param WP_REST_Request $request
50
+	 * @return WP_Error|WP_REST_Response
51
+	 */
52
+	protected function _create_checkin_checkout_object(WP_REST_Request $request)
53
+	{
54
+		$reg_id = $request->get_param('REG_ID');
55
+		$dtt_id = $request->get_param('DTT_ID');
56
+		$force = $request->get_param('force');
57
+		if ($force == 'true') {
58
+			$force = true;
59
+		} else {
60
+			$force = false;
61
+		}
62
+		$reg = EEM_Registration::instance()->get_one_by_ID($reg_id);
63
+		if (! $reg instanceof EE_Registration) {
64
+			return $this->send_response(
65
+				new WP_Error(
66
+					'rest_registration_toggle_checkin_invalid_id',
67
+					sprintf(
68
+						__('You cannot checkin registration with ID %1$s because it doesn\'t exist.',
69
+							'event_espresso'),
70
+						$reg_id
71
+					),
72
+					array('status' => 422)
73
+				)
74
+			);
75
+		}
76
+		if (! EE_Capabilities::instance()
77
+							 ->current_user_can('ee_edit_checkin', 'rest_api_checkin_endpoint', $reg_id)
78
+		) {
79
+			return $this->send_response(
80
+				new WP_Error(
81
+					'rest_user_cannot_toggle_checkin',
82
+					sprintf(
83
+						__('You are not allowed to checkin registration with ID %1$s.', 'event_espresso'),
84
+						$reg_id
85
+					),
86
+					array('status' => 403)
87
+				)
88
+			);
89
+		}
90
+		$success = $reg->toggle_checkin_status($dtt_id, ! $force);
91
+		if ($success === false) {
92
+			//check if we know they can't check in because they're not approved and we aren't forcing
93
+			if (! $reg->is_approved() && ! $force) {
94
+				//rely on EE_Error::add_error messages to have been added to give more data about why it failed
95
+				return $this->send_response(
96
+					new WP_Error(
97
+						'rest_toggle_checkin_failed',
98
+						__('Registration check-in failed because the registration is not approved. You may attempt to force checking in though.',
99
+							'event_espresso')
100
+					)
101
+				);
102
+			}
103
+			return $this->send_response(
104
+				new WP_Error(
105
+					'rest_toggle_checkin_failed_not_forceable',
106
+					__('Registration checkin failed. Please see additional error data.', 'event_espresso')
107
+				)
108
+			);
109
+		}
110
+		$checkin = EEM_Checkin::instance()->get_one(
111
+			array(
112
+				array(
113
+					'REG_ID' => $reg_id,
114
+					'DTT_ID' => $dtt_id,
115
+				),
116
+				'order_by' => array(
117
+					'CHK_timestamp' => 'DESC',
118
+				),
119
+			)
120
+		);
121
+		if (! $checkin instanceof EE_Checkin) {
122
+			return $this->send_response(
123
+				new WP_Error(
124
+					'rest_toggle_checkin_error',
125
+					sprintf(
126
+						__('Supposedly we created a new checkin object for registration %1$s at datetime %2$s, but we can\'t find it.',
127
+							'event_espresso'),
128
+						$reg_id,
129
+						$dtt_id
130
+					)
131
+				)
132
+			);
133
+		}
134
+		$requested_version = $this->get_requested_version($request->get_route());
135
+		$get_request = new WP_REST_Request(
136
+			'GET',
137
+			EED_Core_Rest_Api::ee_api_namespace . $requested_version . '/checkins/' . $checkin->ID()
138
+		);
139
+		$get_request->set_url_params(
140
+			array(
141
+				'id' => $checkin->ID(),
142
+			)
143
+		);
144
+		return Read::handle_request_get_one($get_request);
145
+	}
146 146
 }
147 147
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -13,7 +13,7 @@  discard block
 block discarded – undo
13 13
 use EventEspresso\core\libraries\rest_api\controllers\Base as Base;
14 14
 use EventEspresso\core\libraries\rest_api\controllers\model\Read;
15 15
 
16
-if (! defined('EVENT_ESPRESSO_VERSION')) {
16
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
17 17
     exit('No direct script access allowed');
18 18
 }
19 19
 
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
             $force = false;
61 61
         }
62 62
         $reg = EEM_Registration::instance()->get_one_by_ID($reg_id);
63
-        if (! $reg instanceof EE_Registration) {
63
+        if ( ! $reg instanceof EE_Registration) {
64 64
             return $this->send_response(
65 65
                 new WP_Error(
66 66
                     'rest_registration_toggle_checkin_invalid_id',
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
                 )
74 74
             );
75 75
         }
76
-        if (! EE_Capabilities::instance()
76
+        if ( ! EE_Capabilities::instance()
77 77
                              ->current_user_can('ee_edit_checkin', 'rest_api_checkin_endpoint', $reg_id)
78 78
         ) {
79 79
             return $this->send_response(
@@ -90,7 +90,7 @@  discard block
 block discarded – undo
90 90
         $success = $reg->toggle_checkin_status($dtt_id, ! $force);
91 91
         if ($success === false) {
92 92
             //check if we know they can't check in because they're not approved and we aren't forcing
93
-            if (! $reg->is_approved() && ! $force) {
93
+            if ( ! $reg->is_approved() && ! $force) {
94 94
                 //rely on EE_Error::add_error messages to have been added to give more data about why it failed
95 95
                 return $this->send_response(
96 96
                     new WP_Error(
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
                 ),
119 119
             )
120 120
         );
121
-        if (! $checkin instanceof EE_Checkin) {
121
+        if ( ! $checkin instanceof EE_Checkin) {
122 122
             return $this->send_response(
123 123
                 new WP_Error(
124 124
                     'rest_toggle_checkin_error',
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
         $requested_version = $this->get_requested_version($request->get_route());
135 135
         $get_request = new WP_REST_Request(
136 136
             'GET',
137
-            EED_Core_Rest_Api::ee_api_namespace . $requested_version . '/checkins/' . $checkin->ID()
137
+            EED_Core_Rest_Api::ee_api_namespace.$requested_version.'/checkins/'.$checkin->ID()
138 138
         );
139 139
         $get_request->set_url_params(
140 140
             array(
Please login to merge, or discard this patch.
core/libraries/shortcodes/EE_Transaction_Shortcodes.lib.php 2 patches
Indentation   +608 added lines, -608 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if (! defined('EVENT_ESPRESSO_VERSION')) {
3
-    exit('NO direct script access allowed');
3
+	exit('NO direct script access allowed');
4 4
 }
5 5
 
6 6
 
@@ -28,616 +28,616 @@  discard block
 block discarded – undo
28 28
 class EE_Transaction_Shortcodes extends EE_Shortcodes
29 29
 {
30 30
 
31
-    /**
32
-     * @var EE_Payment_Method $_invoice_pm the invoiec payment method for use in invoices etc
33
-     */
34
-    protected $_invoice_pm;
35
-
36
-
37
-
38
-    /**
39
-     * EE_Transaction_Shortcodes constructor.
40
-     */
41
-    public function __construct()
42
-    {
43
-        parent::__construct();
44
-    }
45
-
46
-
47
-
48
-    protected function _init_props()
49
-    {
50
-        $this->label = esc_html__('Transaction Shortcodes', 'event_espresso');
51
-        $this->description = esc_html__('All shortcodes specific to transaction related data', 'event_espresso');
52
-        $this->_shortcodes = array(
53
-            '[TXN_ID]'                          => esc_html__('The transaction id for the purchase.', 'event_espresso'),
54
-            '[PAYMENT_URL]'                     => esc_html__('This is a link to make a payment for the event',
55
-                'event_espresso'),
56
-            '[PAYMENT_LINK_IF_NEEDED_*]'        => esc_html__('This is a special dynamic shortcode that allows one to insert a payment link conditional on there being amount owing on the transaction. Three params are available on this shortcode:',
57
-                    'event_espresso')
58
-                                                   . '<ul>'
59
-                                                   . '<li>'
60
-                                                   . sprintf(esc_html__('%sclass:%s This can be used to indicate css class is given to the containing css element (default is "callout").',
61
-                    'event_espresso'), '<strong>', '</strong>')
62
-                                                   . '</li>'
63
-                                                   . '<li>'
64
-                                                   . sprintf(esc_html__('%scustom_text:%s This should be a sprintf format text string (with %%s for where the hyperlink tags go) that is used for the generated link text (The default is "You can %%smake a payment here »%%s.)',
65
-                    'event_espresso'), '<strong>', '</strong>')
66
-                                                   . '</li>'
67
-                                                   . '<li>'
68
-                                                   . sprintf(esc_html__('%scontainer_tag:%s Use this to indicate what container tag you want surrounding the payment link (default is "p").',
69
-                    'event_espresso'), '<strong>', '</strong>')
70
-                                                   . '</li>'
71
-                                                   . '</ul>',
72
-            '[PAYMENT_DUE_DATE_*]'              => esc_html__('This is a special dynamic shortcode that allows one to output a payment due date.  It will only result in a date shown if there is money owing.  Three parameters are available on this shortcode:',
73
-                    'event_espresso')
74
-                                                   . '<ul>'
75
-                                                   . '<li>'
76
-                                                   . sprintf(esc_html__('%sformat:%s This is used to indicate what format the date is in.  Default is whatever is set as date formats for your website.',
77
-                    'event_espresso'), '<strong>', '</strong>')
78
-                                                   . '</li>'
79
-                                                   . '<li>'
80
-                                                   . sprintf(esc_html__('%sdays_until_due:%s This is the number of days form the transaction creation date that the payment is due.  Defaults to 30.',
81
-                    'event_espresso'), '<strong>', '</strong>')
82
-                                                   . '</li>'
83
-                                                   . '<li>'
84
-                                                   . sprintf(esc_html__('%sprefix_text:%s You can use this to indicate what text will prefix the date string.  Defaults to "Payment in full due by:"',
85
-                    'event_espresso'), '<strong>', '</strong>')
86
-                                                   . '</li>',
87
-            '[INVOICE_LINK]'                    => esc_html__('This is a full html link to the invoice',
88
-                'event_espresso'),
89
-            '[INVOICE_URL]'                     => esc_html__('This is just the url for the invoice', 'event_espresso'),
90
-            '[INVOICE_LOGO_URL]'                => esc_html__('This returns the url for the logo uploaded via the invoice settings page.',
91
-                'event_espresso'),
92
-            '[INVOICE_LOGO]'                    => esc_html__('This returns the logo uploaded via the invoice settings page wrapped in img_tags and with a "logo screen" classes. The image size is also set in the img tags automatically to match the uploaded logo.',
93
-                'event_espresso'),
94
-            '[INVOICE_PAYEE_NAME]'              => esc_html__('This will parse to either: the value of the "Company Name" field in the invoice payment method settings; if that is blank, then the value of the Company Name in the "Your Organization Settings", if that is blank then an empty string.',
95
-                'event_espresso'),
96
-            '[INVOICE_PAYEE_ADDRESS]'           => esc_html__('This will parse to either: the value of the "Company Address" field in the invoice payment method settings; if that is blank, then the value of the Company Address in the "Your Organization Settings", if that is blank then an empty string.',
97
-                'event_espresso'),
98
-            '[INVOICE_PAYMENT_INSTRUCTIONS]'    => esc_html__('This will parse to the value of the "Payment Instructions" field found on the Invoice payment methods settings page',
99
-                'event_espresso'),
100
-            '[INVOICE_PAYEE_EMAIL]'             => esc_html__('This will parse to either: the value of the "Company Email" field in the invoice payment method settings; if that is blank, then the value of the Company Email in the "Your Organization Settings", if that is blank then an empty string.',
101
-                'event_espresso'),
102
-            '[INVOICE_PAYEE_TAX_NUMBER_*]'      => sprintf(esc_html__('This will parse to either: the value of the "Company Tax Number" field in the invoice payment method settings; if that is blank, then the value of the Company Tax Number in the "Your Organization Settings", if that is blank then an empty string. Note this is also a special dynamic shortcode. You can use the "prefix" parameter to indicate what text you want to use as a prefix before this tax number.  It defaults to "VAT/Tax Number:". To change this prefix you do the following format for this shortcode: %1$s[INVOICE_PAYEE_TAX_NUMBER_* prefix="GST:"]%2$s and that will output: GST: 12345t56.  If you have no tax number in your settings, then no prefix will be output either.',
103
-                'event_espresso'), '<code>', '</code>'),
104
-            '[TOTAL_COST]'                      => esc_html__('The total cost for the transaction', 'event_espresso'),
105
-            '[TXN_STATUS]'                      => esc_html__('The transaction status for the transaction.',
106
-                'event_espresso'),
107
-            '[TXN_STATUS_ID]'                   => esc_html__('The ID representing the transaction status as saved in the db.  This tends to be useful for including with css classes for styling certain statuses differently from others.',
108
-                'event_espresso'),
109
-            '[PAYMENT_STATUS]'                  => esc_html__('The transaction status for the transaction. This parses to the same value as the [TXN_STATUS] shortcode and still remains here for legacy support.',
110
-                'event_espresso'),
111
-            '[PAYMENT_GATEWAY]'                 => esc_html__('The payment gateway used for the transaction',
112
-                'event_espresso'),
113
-            '[AMOUNT_PAID]'                     => esc_html__('The amount paid or refunded.  This will only have a value if there was a payment or refund at the time of generating the message.',
114
-                'event_espresso'),
115
-            '[LAST_AMOUNT_PAID]'                => esc_html__('This is the last payment or refund made on the transaction related to the message being generated.',
116
-                'event_espresso'),
117
-            '[TOTAL_AMOUNT_PAID]'               => esc_html__('This parses to the total amount paid over all payments',
118
-                'event_espresso'),
119
-            '[TOTAL_OWING]'                     => esc_html__('The total owing on a transaction with no attributes.',
120
-                'event_espresso'),
121
-            '[TXN_SUBTOTAL]'                    => esc_html__('The subtotal for all txn line items.', 'event_espresso'),
122
-            '[TXN_TAX_SUBTOTAL]'                => esc_html__('The subtotal for all tax line items.', 'event_espresso'),
123
-            '[OWING_STATUS_MESSAGE_*]'          => esc_html__('A dynamic shortcode for adjusting how total owing gets shown. The acceptable attributes on the shortcode are:',
124
-                    'event_espresso')
125
-                                                   . '<p></ul>'
126
-                                                   .
127
-                                                   '<li><strong>still_owing</strong>:'
128
-                                                   . esc_html__('If the transaction is not paid in full, then whatever is set for this attribute is shown (otherwise its just the amount owing). The default is:',
129
-                    'event_espresso')
130
-                                                   . sprintf(esc_html__('%sPlease make a payment.%s', 'event_espresso'),
131
-                    '<a href="[PAYMENT_URL]" class="noPrint">', '</a>')
132
-                                                   . '</li>'
133
-                                                   .
134
-                                                   '<li><strong>none_owing</strong>:'
135
-                                                   . esc_html__('If the transaction is paid in full, then you can indicate how this gets displayed.  Note, that it defaults to just be the total owing.',
136
-                    'event_espresso')
137
-                                                   . '</li></ul></p>',
138
-            '[TXN_TOTAL_TICKETS]'               => esc_html__('The total number of all tickets purchased in a transaction',
139
-                'event_espresso'),
140
-            '[TKT_QTY_PURCHASED]'               => sprintf(esc_html__('The total number of all tickets purchased in a transaction. %1$sNOTE: This shortcode is good to use in the "[TICKET_LIST]" field but has been deprecated from all other contexts in favor of the more explicit [TXN_TOTAL_TICKETS] shortcode.%2$s',
141
-                'event_espresso'), '<strong>', '</strong>'),
142
-            '[TRANSACTION_ADMIN_URL]'           => esc_html__('The url to the admin page for this transaction',
143
-                'event_espresso'),
144
-            '[RECEIPT_URL]'                     => esc_html__('This parses to the generated url for retrieving the receipt for the transaction',
145
-                'event_espresso'),
146
-            '[INVOICE_RECEIPT_SWITCHER_URL]'    => esc_html__('This parses to the url that will switch to the receipt if an invoice is displayed, and switch to the invoice if receipt is displayed. If a message type OTHER than invoice or receipt is displayed then this will just return the url for the invoice. If the related message type is not active  then will parse to an empty string.',
147
-                'event_espresso'),
148
-            '[INVOICE_RECEIPT_SWITCHER_BUTTON]' => sprintf(esc_html__('The same as %1$s[INVOICE_RECEIPT_SWITCHER_URL]%2$s except this returns the html for a button linked to the invoice or receipt.',
149
-                'event_espresso'), '<code>', '</code>'),
150
-        );
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * @access protected
157
-     * @param  string $shortcode the shortcode to be parsed.
158
-     * @return string parsed shortcode
159
-     */
160
-    protected function _parser($shortcode)
161
-    {
162
-        //attempt to get the transaction.  Since this is potentially used in more fields, we may have to look in the _extra_data for the transaction.
163
-        $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null;
164
-        $transaction = ! $transaction instanceof EE_Transaction
165
-                       && is_array($this->_extra_data)
166
-                       && isset($this->_extra_data['data'])
167
-                       && $this->_extra_data['data'] instanceof EE_Messages_Addressee ? $this->_extra_data['data']->txn
168
-            : $transaction;
169
-        //payment
170
-        $payment = $this->_data->payment instanceof EE_Payment ? $this->_data->payment : null;
171
-        $payment = ! $payment instanceof EE_Payment
172
-                   && is_array($this->_extra_data)
173
-                   && isset($this->_extra_data['data'])
174
-                   && $this->_extra_data['data'] instanceof EE_Messages_Addressee ? $this->_extra_data['data']->payment
175
-            : $payment;
176
-        if (! $transaction instanceof EE_Transaction) {
177
-            return '';
178
-        }
179
-        switch ($shortcode) {
180
-            case '[TXN_ID]' :
181
-                return $transaction->ID();
182
-                break;
183
-            case '[PAYMENT_URL]' :
184
-                $payment_url = $transaction->payment_overview_url();
185
-                return empty($payment_url) ? esc_html__('http://dummypaymenturlforpreview.com', 'event_espresso')
186
-                    : $payment_url;
187
-                break;
188
-            case '[INVOICE_LINK]' :
189
-                $invoice_url = $transaction->invoice_url();
190
-                $invoice_url = empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url;
191
-                return sprintf(esc_html__('%sClick here for Invoice%s', 'event_espresso'),
192
-                    '<a href="' . $invoice_url . '">', '</a>');
193
-                break; /**/
194
-            case '[INVOICE_URL]' :
195
-                $invoice_url = $transaction->invoice_url();
196
-                return empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url;
197
-                break;
198
-            case '[INVOICE_LOGO_URL]' :
199
-                return $this->_get_invoice_logo();
200
-                break;
201
-            case '[INVOICE_LOGO]' :
202
-                return $this->_get_invoice_logo(true);
203
-                break;
204
-            case '[INVOICE_PAYEE_NAME]' :
205
-                return $this->_get_invoice_payee_name();
206
-                break;
207
-            case '[INVOICE_PAYEE_ADDRESS]' :
208
-                return $this->_get_invoice_payee_address();
209
-                break;
210
-            case '[INVOICE_PAYMENT_INSTRUCTIONS]' :
211
-                return $this->_get_invoice_payment_instructions();
212
-                break;
213
-            case '[INVOICE_PAYEE_EMAIL]' :
214
-                return $this->_get_invoice_payee_email();
215
-                break;
216
-            case '[TOTAL_COST]' :
217
-                $total = $transaction->total();
218
-                return ! empty($total) ? EEH_Template::format_currency($total) : '';
219
-                break;
220
-            case '[PAYMENT_STATUS]' :
221
-                $status = $transaction->pretty_status();
222
-                return ! empty($status) ? $status : esc_html__('Unknown', 'event_espresso');
223
-                break; /**/
224
-            // note the [payment_status] shortcode is kind of misleading because payment status might be different from txn status so I'm adding this here for clarity.
225
-            case '[TXN_STATUS]':
226
-                $status = $transaction->pretty_status();
227
-                return ! empty($status) ? $status : esc_html__('Unknown', 'event_espresso');
228
-                break;
229
-            case '[TXN_STATUS_ID]' :
230
-                return $transaction->status_ID();
231
-                break;
232
-            case '[PAYMENT_GATEWAY]' :
233
-                return $this->_get_payment_gateway($transaction);
234
-                break;
235
-            case '[AMOUNT_PAID]' :
236
-                return $payment instanceof EE_Payment
237
-                    ? EEH_Template::format_currency($payment->amount())
238
-                    : EEH_Template::format_currency(0);
239
-                break;
240
-            case '[LAST_AMOUNT_PAID]' :
241
-                $last_payment = $transaction->last_payment();
242
-                return $last_payment instanceof EE_Payment
243
-                    ? EEH_Template::format_currency($last_payment->amount())
244
-                    : EEH_Template::format_currency(0);
245
-            case '[TOTAL_AMOUNT_PAID]' :
246
-                return EEH_Template::format_currency($transaction->paid());
247
-                break;
248
-            case '[TOTAL_OWING]' :
249
-                $total_owing = $transaction->remaining();
250
-                return EEH_Template::format_currency($total_owing);
251
-                break;
252
-            case '[TXN_SUBTOTAL]' :
253
-                return EEH_Template::format_currency($this->_get_subtotal());
254
-                break;
255
-            case '[TXN_TAX_SUBTOTAL]' :
256
-                return EEH_Template::format_currency($this->_get_subtotal(true));
257
-                break;
258
-            case '[TKT_QTY_PURCHASED]' :
259
-            case '[TXN_TOTAL_TICKETS]' :
260
-                return $this->_data->total_ticket_count;
261
-                break;
262
-            case '[TRANSACTION_ADMIN_URL]' :
263
-                require_once EE_CORE . 'admin/EE_Admin_Page.core.php';
264
-                $query_args = array(
265
-                    'page'   => 'espresso_transactions',
266
-                    'action' => 'view_transaction',
267
-                    'TXN_ID' => $transaction->ID(),
268
-                );
269
-                $url = EE_Admin_Page::add_query_args_and_nonce($query_args, admin_url('admin.php'));
270
-                return $url;
271
-                break;
272
-            case '[RECEIPT_URL]' :
273
-                //get primary_registration
274
-                $reg = $this->_data->primary_reg_obj;
275
-                if (! $reg instanceof EE_Registration) {
276
-                    return '';
277
-                }
278
-                return $reg->receipt_url();
279
-                break;
280
-            case '[INVOICE_RECEIPT_SWITCHER_URL]' :
281
-                return $this->_get_invoice_receipt_switcher(false);
282
-                break;
283
-            case '[INVOICE_RECEIPT_SWITCHER_BUTTON]' :
284
-                return $this->_get_invoice_receipt_switcher();
285
-                break;
286
-        }
287
-        if (strpos($shortcode, '[OWING_STATUS_MESSAGE_*') !== false) {
288
-            return $this->_get_custom_total_owing($shortcode);
289
-        }
290
-        if (strpos($shortcode, '[INVOICE_PAYEE_TAX_NUMBER_*') !== false) {
291
-            return $this->_get_invoice_payee_tax_number($shortcode);
292
-        }
293
-        if (strpos($shortcode, '[PAYMENT_LINK_IF_NEEDED_*') !== false) {
294
-            return $this->_get_payment_link_if_needed($shortcode);
295
-        }
296
-        if (strpos($shortcode, '[PAYMENT_DUE_DATE_*') !== false) {
297
-            return $this->_get_payment_due_date($shortcode, $transaction);
298
-        }
299
-        return '';
300
-    }
301
-
302
-
303
-
304
-    /**
305
-     * parser for the [OWING_STATUS_MESSAGE_*] attribute type shortcode
306
-     *
307
-     * @since 4.5.0
308
-     * @param string $shortcode the incoming shortcode
309
-     * @return string parsed.
310
-     */
311
-    private function _get_custom_total_owing($shortcode)
312
-    {
313
-        $valid_shortcodes = array('transaction');
314
-        $attrs = $this->_get_shortcode_attrs($shortcode);
315
-        //ensure default is set.
316
-        $addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null;
317
-        $total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction
318
-            ? $addressee->txn->remaining() : 0;
319
-        if ($total_owing > 0) {
320
-            $owing_content = ! empty($attrs['still_owing'])
321
-                ? $attrs['still_owing']
322
-                : sprintf(esc_html__('%sPlease make a payment.%s', 'event_espresso'),
323
-                    '<a href="[PAYMENT_URL]" class="noPrint">', '</a>');
324
-            $owing_content = $this->_shortcode_helper->parse_message_template($owing_content, $addressee,
325
-                $valid_shortcodes, $this->_message_type, $this->_messenger, $this->_message);
326
-        } else {
327
-            $owing_content = ! empty($attrs['none_owing']) ? $attrs['none_owing'] : '';
328
-        }
329
-        return $owing_content;
330
-    }
331
-
332
-
333
-
334
-    /**
335
-     * @param EE_Transaction $transaction
336
-     * @return string
337
-     */
338
-    private function _get_payment_gateway($transaction)
339
-    {
340
-        if($transaction instanceof EE_Transaction){
341
-            $pm = $transaction->payment_method();
342
-        } else {
343
-            $pm = null;
344
-        }
345
-        return $pm instanceof EE_Payment_Method ? $pm->name() : '';
346
-    }
347
-
348
-
349
-
350
-    /**
351
-     * This retrieves a logo to be used for the invoice from whatever is set on the invoice logo settings page.  If its
352
-     * not present then the organization logo is used if its found (set on the organization settings page).
353
-     *
354
-     * @since 4.5.0
355
-     * @param bool $img_tags TRUE means to return with the img tag wrappers.  False just returns the url to the image.
356
-     * @return string url or html
357
-     */
358
-    private function _get_invoice_logo($img_tags = false)
359
-    {
360
-        //try to get the invoice payment method's logo for this transaction image first
361
-        $pm = $this->_get_invoice_payment_method();
362
-        if ($pm instanceof EE_Payment_Method) {
363
-            $invoice_logo_url = $pm->get_extra_meta('pdf_logo_image', true);
364
-        } else {
365
-            $invoice_logo_url = null;
366
-        }
367
-        if (empty($invoice_logo_url)) {
368
-            $invoice_logo_url = EE_Registry::instance()->CFG->organization->logo_url;
369
-        }
370
-        if (empty($invoice_logo_url)) {
371
-            return '';
372
-        }
373
-        if (! $img_tags) {
374
-            return $invoice_logo_url;
375
-        }
376
-        //image tags have been requested.
377
-        $image_size = getimagesize($invoice_logo_url);
378
-        //if image is wider than 300px, set the width to 300
379
-        if ($image_size[0] > 300) {
380
-            $image_width = 300;
381
-        } else {
382
-            $image_width = $image_size[0];
383
-        }
384
-        return '<img class="logo screen" src="' . $invoice_logo_url . '" width="' . $image_width . '" alt="logo" />';
385
-    }
386
-
387
-
388
-
389
-    /**
390
-     * Used to retrieve the appropriate content for the invoice payee name shortcode
391
-     *
392
-     * @since 4.5.0
393
-     * @return string
394
-     */
395
-    private function _get_invoice_payee_name()
396
-    {
397
-        $payee_name = null;
398
-        $pm = $this->_get_invoice_payment_method();
399
-        if ($pm instanceof EE_Payment_Method) {
400
-            $payee_name = $pm->get_extra_meta('pdf_payee_name', true);
401
-        }
402
-        $payee_name = empty($payee_name) ? EE_Registry::instance()->CFG->organization->get_pretty('name') : $payee_name;
403
-        return $payee_name;
404
-    }
405
-
406
-
407
-
408
-    /**
409
-     * gets the default invoice payment method, but has a filter so it can be overridden
410
-     *
411
-     * @return \EE_Payment_Method|null
412
-     */
413
-    private function _get_invoice_payment_method()
414
-    {
415
-        if (! $this->_invoice_pm instanceof EE_Payment_Method) {
416
-            $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null;
417
-            $transaction = ! $transaction instanceof EE_Transaction
418
-                           && is_array($this->_extra_data)
419
-                           && isset($this->_extra_data['data'])
420
-                           && $this->_extra_data['data'] instanceof EE_Messages_Addressee
421
-                ? $this->_extra_data['data']->txn : $transaction;
422
-            //get the invoice payment method, and remember it for the next call too
423
-            $this->_invoice_pm = apply_filters('FHEE__EE_Transaction_Shortcodes__get_payment_method__default',
424
-                EEM_Payment_Method::instance()->get_one_of_type('Invoice'), $transaction);
425
-        }
426
-        return $this->_invoice_pm;
427
-    }
428
-
429
-
430
-
431
-    /**
432
-     * Used to retrieve the appropriate content for the invoice payee email shortcode
433
-     *
434
-     * @since 4.5.0
435
-     * @return string
436
-     */
437
-    private function _get_invoice_payee_email()
438
-    {
439
-        $payee_email = null;
440
-        $pm = $this->_get_invoice_payment_method();
441
-        if ($pm instanceof EE_Payment_Method) {
442
-            $payee_email = $pm->get_extra_meta('pdf_payee_email', true);
443
-        }
444
-        $payee_email = empty($payee_email) ? EE_Registry::instance()->CFG->organization->get_pretty('email')
445
-            : $payee_email;
446
-        return $payee_email;
447
-    }
448
-
449
-
450
-
451
-    /**
452
-     * Used to retrieve the appropriate content for the invoice payee tax number shortcode
453
-     *
454
-     * @since 4.5.0
455
-     * @param string $shortcode
456
-     * @return string
457
-     */
458
-    private function _get_invoice_payee_tax_number($shortcode)
459
-    {
460
-        $payee_tax_number = null;
461
-        $pm = $this->_get_invoice_payment_method();
462
-        if ($pm instanceof EE_Payment_Method) {
463
-            $payee_tax_number = $pm->get_extra_meta('pdf_payee_tax_number', true);
464
-        }
465
-        $payee_tax_number = empty($payee_tax_number) ? EE_Registry::instance()->CFG->organization->vat
466
-            : $payee_tax_number;
467
-        if (empty($payee_tax_number)) {
468
-            return '';
469
-        }
470
-        //any attributes?
471
-        $attrs = $this->_get_shortcode_attrs($shortcode);
472
-        //prefix?
473
-        $prefix = isset($attrs['prefix']) ? $attrs['prefix'] : esc_html__('VAT/Tax Number: ', 'event_espresso');
474
-        return $prefix . $payee_tax_number;
475
-    }
476
-
477
-
478
-
479
-    /**
480
-     * Used to retrieve the appropriate content for the invoice payee address shortcode.
481
-     *
482
-     * @since 4.5.0
483
-     * @return string
484
-     */
485
-    private function _get_invoice_payee_address()
486
-    {
487
-        $payee_address = null;
488
-        $pm = $this->_get_invoice_payment_method();
489
-        if ($pm instanceof EE_Payment_Method) {
490
-            $payee_address = $pm->get_extra_meta('pdf_payee_address', true);
491
-        }
492
-        if (empty($payee_address)) {
493
-            $organization = EE_Registry::instance()->CFG->organization;
494
-            $payee_address = $organization->get_pretty('address_1') . '<br>';
495
-            $payee_address .= ! empty($organization->address_2) ? $organization->get_pretty('address_2') . '<br>' : '';
496
-            $payee_address .= $organization->get_pretty('city') . '<br>';
497
-            //state
498
-            $state = EE_Registry::instance()->load_model('State')->get_one_by_ID($organization->STA_ID);
499
-            $payee_address .= $state instanceof EE_State ? $state->name() : '';
500
-            //Country
501
-            $payee_address .= ! empty($organization->CNT_ISO) ? ', ' . $organization->CNT_ISO . '<br>' : '';
502
-            $payee_address .= ! empty($organization->zip) ? $organization->zip : '';
503
-        }
504
-        return $payee_address;
505
-    }
506
-
507
-
508
-
509
-    /**
510
-     * Used to retrieve the appropriate content for the invoice payment instructions shortcode.
511
-     *
512
-     * @since 4.5.0
513
-     * @return string
514
-     */
515
-    private function _get_invoice_payment_instructions()
516
-    {
517
-        $instructions = null;
518
-        $pm = $this->_get_invoice_payment_method();
519
-        return ($pm instanceof EE_Payment_Method) ? $pm->get_extra_meta('pdf_instructions', true) : '';
520
-    }
521
-
522
-
523
-
524
-    /**
525
-     * get invoice/receipt switch button or url.
526
-     *
527
-     * @param bool $button true (default) returns the html for a button, false just returns the url.
528
-     * @return string
529
-     */
530
-    protected function _get_invoice_receipt_switcher($button = true)
531
-    {
532
-        $reg = $this->_data->primary_reg_obj;
533
-        $message_type = isset($this->_extra_data['message_type']) ? $this->_extra_data['message_type'] : '';
534
-        if (! $reg instanceof EE_Registration || empty($message_type)) {
535
-            return '';
536
-        }
537
-        $switch_to_invoice = ! $message_type instanceof EE_Invoice_message_type ? true : false;
538
-        $switch_to_label = $switch_to_invoice && ! $message_type instanceof EE_Receipt_message_type
539
-            ? esc_html__('View Invoice', 'event_espresso') : esc_html__('Switch to Invoice', 'event_espresso');
540
-        $switch_to_label = ! $switch_to_invoice ? esc_html__('Switch to Receipt', 'event_espresso') : $switch_to_label;
541
-        $switch_to_url = $switch_to_invoice ? $reg->invoice_url() : $reg->receipt_url();
542
-        if (! $button) {
543
-            return $switch_to_url;
544
-        }
545
-        if (! empty($switch_to_url)) {
546
-            return '
31
+	/**
32
+	 * @var EE_Payment_Method $_invoice_pm the invoiec payment method for use in invoices etc
33
+	 */
34
+	protected $_invoice_pm;
35
+
36
+
37
+
38
+	/**
39
+	 * EE_Transaction_Shortcodes constructor.
40
+	 */
41
+	public function __construct()
42
+	{
43
+		parent::__construct();
44
+	}
45
+
46
+
47
+
48
+	protected function _init_props()
49
+	{
50
+		$this->label = esc_html__('Transaction Shortcodes', 'event_espresso');
51
+		$this->description = esc_html__('All shortcodes specific to transaction related data', 'event_espresso');
52
+		$this->_shortcodes = array(
53
+			'[TXN_ID]'                          => esc_html__('The transaction id for the purchase.', 'event_espresso'),
54
+			'[PAYMENT_URL]'                     => esc_html__('This is a link to make a payment for the event',
55
+				'event_espresso'),
56
+			'[PAYMENT_LINK_IF_NEEDED_*]'        => esc_html__('This is a special dynamic shortcode that allows one to insert a payment link conditional on there being amount owing on the transaction. Three params are available on this shortcode:',
57
+					'event_espresso')
58
+												   . '<ul>'
59
+												   . '<li>'
60
+												   . sprintf(esc_html__('%sclass:%s This can be used to indicate css class is given to the containing css element (default is "callout").',
61
+					'event_espresso'), '<strong>', '</strong>')
62
+												   . '</li>'
63
+												   . '<li>'
64
+												   . sprintf(esc_html__('%scustom_text:%s This should be a sprintf format text string (with %%s for where the hyperlink tags go) that is used for the generated link text (The default is "You can %%smake a payment here »%%s.)',
65
+					'event_espresso'), '<strong>', '</strong>')
66
+												   . '</li>'
67
+												   . '<li>'
68
+												   . sprintf(esc_html__('%scontainer_tag:%s Use this to indicate what container tag you want surrounding the payment link (default is "p").',
69
+					'event_espresso'), '<strong>', '</strong>')
70
+												   . '</li>'
71
+												   . '</ul>',
72
+			'[PAYMENT_DUE_DATE_*]'              => esc_html__('This is a special dynamic shortcode that allows one to output a payment due date.  It will only result in a date shown if there is money owing.  Three parameters are available on this shortcode:',
73
+					'event_espresso')
74
+												   . '<ul>'
75
+												   . '<li>'
76
+												   . sprintf(esc_html__('%sformat:%s This is used to indicate what format the date is in.  Default is whatever is set as date formats for your website.',
77
+					'event_espresso'), '<strong>', '</strong>')
78
+												   . '</li>'
79
+												   . '<li>'
80
+												   . sprintf(esc_html__('%sdays_until_due:%s This is the number of days form the transaction creation date that the payment is due.  Defaults to 30.',
81
+					'event_espresso'), '<strong>', '</strong>')
82
+												   . '</li>'
83
+												   . '<li>'
84
+												   . sprintf(esc_html__('%sprefix_text:%s You can use this to indicate what text will prefix the date string.  Defaults to "Payment in full due by:"',
85
+					'event_espresso'), '<strong>', '</strong>')
86
+												   . '</li>',
87
+			'[INVOICE_LINK]'                    => esc_html__('This is a full html link to the invoice',
88
+				'event_espresso'),
89
+			'[INVOICE_URL]'                     => esc_html__('This is just the url for the invoice', 'event_espresso'),
90
+			'[INVOICE_LOGO_URL]'                => esc_html__('This returns the url for the logo uploaded via the invoice settings page.',
91
+				'event_espresso'),
92
+			'[INVOICE_LOGO]'                    => esc_html__('This returns the logo uploaded via the invoice settings page wrapped in img_tags and with a "logo screen" classes. The image size is also set in the img tags automatically to match the uploaded logo.',
93
+				'event_espresso'),
94
+			'[INVOICE_PAYEE_NAME]'              => esc_html__('This will parse to either: the value of the "Company Name" field in the invoice payment method settings; if that is blank, then the value of the Company Name in the "Your Organization Settings", if that is blank then an empty string.',
95
+				'event_espresso'),
96
+			'[INVOICE_PAYEE_ADDRESS]'           => esc_html__('This will parse to either: the value of the "Company Address" field in the invoice payment method settings; if that is blank, then the value of the Company Address in the "Your Organization Settings", if that is blank then an empty string.',
97
+				'event_espresso'),
98
+			'[INVOICE_PAYMENT_INSTRUCTIONS]'    => esc_html__('This will parse to the value of the "Payment Instructions" field found on the Invoice payment methods settings page',
99
+				'event_espresso'),
100
+			'[INVOICE_PAYEE_EMAIL]'             => esc_html__('This will parse to either: the value of the "Company Email" field in the invoice payment method settings; if that is blank, then the value of the Company Email in the "Your Organization Settings", if that is blank then an empty string.',
101
+				'event_espresso'),
102
+			'[INVOICE_PAYEE_TAX_NUMBER_*]'      => sprintf(esc_html__('This will parse to either: the value of the "Company Tax Number" field in the invoice payment method settings; if that is blank, then the value of the Company Tax Number in the "Your Organization Settings", if that is blank then an empty string. Note this is also a special dynamic shortcode. You can use the "prefix" parameter to indicate what text you want to use as a prefix before this tax number.  It defaults to "VAT/Tax Number:". To change this prefix you do the following format for this shortcode: %1$s[INVOICE_PAYEE_TAX_NUMBER_* prefix="GST:"]%2$s and that will output: GST: 12345t56.  If you have no tax number in your settings, then no prefix will be output either.',
103
+				'event_espresso'), '<code>', '</code>'),
104
+			'[TOTAL_COST]'                      => esc_html__('The total cost for the transaction', 'event_espresso'),
105
+			'[TXN_STATUS]'                      => esc_html__('The transaction status for the transaction.',
106
+				'event_espresso'),
107
+			'[TXN_STATUS_ID]'                   => esc_html__('The ID representing the transaction status as saved in the db.  This tends to be useful for including with css classes for styling certain statuses differently from others.',
108
+				'event_espresso'),
109
+			'[PAYMENT_STATUS]'                  => esc_html__('The transaction status for the transaction. This parses to the same value as the [TXN_STATUS] shortcode and still remains here for legacy support.',
110
+				'event_espresso'),
111
+			'[PAYMENT_GATEWAY]'                 => esc_html__('The payment gateway used for the transaction',
112
+				'event_espresso'),
113
+			'[AMOUNT_PAID]'                     => esc_html__('The amount paid or refunded.  This will only have a value if there was a payment or refund at the time of generating the message.',
114
+				'event_espresso'),
115
+			'[LAST_AMOUNT_PAID]'                => esc_html__('This is the last payment or refund made on the transaction related to the message being generated.',
116
+				'event_espresso'),
117
+			'[TOTAL_AMOUNT_PAID]'               => esc_html__('This parses to the total amount paid over all payments',
118
+				'event_espresso'),
119
+			'[TOTAL_OWING]'                     => esc_html__('The total owing on a transaction with no attributes.',
120
+				'event_espresso'),
121
+			'[TXN_SUBTOTAL]'                    => esc_html__('The subtotal for all txn line items.', 'event_espresso'),
122
+			'[TXN_TAX_SUBTOTAL]'                => esc_html__('The subtotal for all tax line items.', 'event_espresso'),
123
+			'[OWING_STATUS_MESSAGE_*]'          => esc_html__('A dynamic shortcode for adjusting how total owing gets shown. The acceptable attributes on the shortcode are:',
124
+					'event_espresso')
125
+												   . '<p></ul>'
126
+												   .
127
+												   '<li><strong>still_owing</strong>:'
128
+												   . esc_html__('If the transaction is not paid in full, then whatever is set for this attribute is shown (otherwise its just the amount owing). The default is:',
129
+					'event_espresso')
130
+												   . sprintf(esc_html__('%sPlease make a payment.%s', 'event_espresso'),
131
+					'<a href="[PAYMENT_URL]" class="noPrint">', '</a>')
132
+												   . '</li>'
133
+												   .
134
+												   '<li><strong>none_owing</strong>:'
135
+												   . esc_html__('If the transaction is paid in full, then you can indicate how this gets displayed.  Note, that it defaults to just be the total owing.',
136
+					'event_espresso')
137
+												   . '</li></ul></p>',
138
+			'[TXN_TOTAL_TICKETS]'               => esc_html__('The total number of all tickets purchased in a transaction',
139
+				'event_espresso'),
140
+			'[TKT_QTY_PURCHASED]'               => sprintf(esc_html__('The total number of all tickets purchased in a transaction. %1$sNOTE: This shortcode is good to use in the "[TICKET_LIST]" field but has been deprecated from all other contexts in favor of the more explicit [TXN_TOTAL_TICKETS] shortcode.%2$s',
141
+				'event_espresso'), '<strong>', '</strong>'),
142
+			'[TRANSACTION_ADMIN_URL]'           => esc_html__('The url to the admin page for this transaction',
143
+				'event_espresso'),
144
+			'[RECEIPT_URL]'                     => esc_html__('This parses to the generated url for retrieving the receipt for the transaction',
145
+				'event_espresso'),
146
+			'[INVOICE_RECEIPT_SWITCHER_URL]'    => esc_html__('This parses to the url that will switch to the receipt if an invoice is displayed, and switch to the invoice if receipt is displayed. If a message type OTHER than invoice or receipt is displayed then this will just return the url for the invoice. If the related message type is not active  then will parse to an empty string.',
147
+				'event_espresso'),
148
+			'[INVOICE_RECEIPT_SWITCHER_BUTTON]' => sprintf(esc_html__('The same as %1$s[INVOICE_RECEIPT_SWITCHER_URL]%2$s except this returns the html for a button linked to the invoice or receipt.',
149
+				'event_espresso'), '<code>', '</code>'),
150
+		);
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * @access protected
157
+	 * @param  string $shortcode the shortcode to be parsed.
158
+	 * @return string parsed shortcode
159
+	 */
160
+	protected function _parser($shortcode)
161
+	{
162
+		//attempt to get the transaction.  Since this is potentially used in more fields, we may have to look in the _extra_data for the transaction.
163
+		$transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null;
164
+		$transaction = ! $transaction instanceof EE_Transaction
165
+					   && is_array($this->_extra_data)
166
+					   && isset($this->_extra_data['data'])
167
+					   && $this->_extra_data['data'] instanceof EE_Messages_Addressee ? $this->_extra_data['data']->txn
168
+			: $transaction;
169
+		//payment
170
+		$payment = $this->_data->payment instanceof EE_Payment ? $this->_data->payment : null;
171
+		$payment = ! $payment instanceof EE_Payment
172
+				   && is_array($this->_extra_data)
173
+				   && isset($this->_extra_data['data'])
174
+				   && $this->_extra_data['data'] instanceof EE_Messages_Addressee ? $this->_extra_data['data']->payment
175
+			: $payment;
176
+		if (! $transaction instanceof EE_Transaction) {
177
+			return '';
178
+		}
179
+		switch ($shortcode) {
180
+			case '[TXN_ID]' :
181
+				return $transaction->ID();
182
+				break;
183
+			case '[PAYMENT_URL]' :
184
+				$payment_url = $transaction->payment_overview_url();
185
+				return empty($payment_url) ? esc_html__('http://dummypaymenturlforpreview.com', 'event_espresso')
186
+					: $payment_url;
187
+				break;
188
+			case '[INVOICE_LINK]' :
189
+				$invoice_url = $transaction->invoice_url();
190
+				$invoice_url = empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url;
191
+				return sprintf(esc_html__('%sClick here for Invoice%s', 'event_espresso'),
192
+					'<a href="' . $invoice_url . '">', '</a>');
193
+				break; /**/
194
+			case '[INVOICE_URL]' :
195
+				$invoice_url = $transaction->invoice_url();
196
+				return empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url;
197
+				break;
198
+			case '[INVOICE_LOGO_URL]' :
199
+				return $this->_get_invoice_logo();
200
+				break;
201
+			case '[INVOICE_LOGO]' :
202
+				return $this->_get_invoice_logo(true);
203
+				break;
204
+			case '[INVOICE_PAYEE_NAME]' :
205
+				return $this->_get_invoice_payee_name();
206
+				break;
207
+			case '[INVOICE_PAYEE_ADDRESS]' :
208
+				return $this->_get_invoice_payee_address();
209
+				break;
210
+			case '[INVOICE_PAYMENT_INSTRUCTIONS]' :
211
+				return $this->_get_invoice_payment_instructions();
212
+				break;
213
+			case '[INVOICE_PAYEE_EMAIL]' :
214
+				return $this->_get_invoice_payee_email();
215
+				break;
216
+			case '[TOTAL_COST]' :
217
+				$total = $transaction->total();
218
+				return ! empty($total) ? EEH_Template::format_currency($total) : '';
219
+				break;
220
+			case '[PAYMENT_STATUS]' :
221
+				$status = $transaction->pretty_status();
222
+				return ! empty($status) ? $status : esc_html__('Unknown', 'event_espresso');
223
+				break; /**/
224
+			// note the [payment_status] shortcode is kind of misleading because payment status might be different from txn status so I'm adding this here for clarity.
225
+			case '[TXN_STATUS]':
226
+				$status = $transaction->pretty_status();
227
+				return ! empty($status) ? $status : esc_html__('Unknown', 'event_espresso');
228
+				break;
229
+			case '[TXN_STATUS_ID]' :
230
+				return $transaction->status_ID();
231
+				break;
232
+			case '[PAYMENT_GATEWAY]' :
233
+				return $this->_get_payment_gateway($transaction);
234
+				break;
235
+			case '[AMOUNT_PAID]' :
236
+				return $payment instanceof EE_Payment
237
+					? EEH_Template::format_currency($payment->amount())
238
+					: EEH_Template::format_currency(0);
239
+				break;
240
+			case '[LAST_AMOUNT_PAID]' :
241
+				$last_payment = $transaction->last_payment();
242
+				return $last_payment instanceof EE_Payment
243
+					? EEH_Template::format_currency($last_payment->amount())
244
+					: EEH_Template::format_currency(0);
245
+			case '[TOTAL_AMOUNT_PAID]' :
246
+				return EEH_Template::format_currency($transaction->paid());
247
+				break;
248
+			case '[TOTAL_OWING]' :
249
+				$total_owing = $transaction->remaining();
250
+				return EEH_Template::format_currency($total_owing);
251
+				break;
252
+			case '[TXN_SUBTOTAL]' :
253
+				return EEH_Template::format_currency($this->_get_subtotal());
254
+				break;
255
+			case '[TXN_TAX_SUBTOTAL]' :
256
+				return EEH_Template::format_currency($this->_get_subtotal(true));
257
+				break;
258
+			case '[TKT_QTY_PURCHASED]' :
259
+			case '[TXN_TOTAL_TICKETS]' :
260
+				return $this->_data->total_ticket_count;
261
+				break;
262
+			case '[TRANSACTION_ADMIN_URL]' :
263
+				require_once EE_CORE . 'admin/EE_Admin_Page.core.php';
264
+				$query_args = array(
265
+					'page'   => 'espresso_transactions',
266
+					'action' => 'view_transaction',
267
+					'TXN_ID' => $transaction->ID(),
268
+				);
269
+				$url = EE_Admin_Page::add_query_args_and_nonce($query_args, admin_url('admin.php'));
270
+				return $url;
271
+				break;
272
+			case '[RECEIPT_URL]' :
273
+				//get primary_registration
274
+				$reg = $this->_data->primary_reg_obj;
275
+				if (! $reg instanceof EE_Registration) {
276
+					return '';
277
+				}
278
+				return $reg->receipt_url();
279
+				break;
280
+			case '[INVOICE_RECEIPT_SWITCHER_URL]' :
281
+				return $this->_get_invoice_receipt_switcher(false);
282
+				break;
283
+			case '[INVOICE_RECEIPT_SWITCHER_BUTTON]' :
284
+				return $this->_get_invoice_receipt_switcher();
285
+				break;
286
+		}
287
+		if (strpos($shortcode, '[OWING_STATUS_MESSAGE_*') !== false) {
288
+			return $this->_get_custom_total_owing($shortcode);
289
+		}
290
+		if (strpos($shortcode, '[INVOICE_PAYEE_TAX_NUMBER_*') !== false) {
291
+			return $this->_get_invoice_payee_tax_number($shortcode);
292
+		}
293
+		if (strpos($shortcode, '[PAYMENT_LINK_IF_NEEDED_*') !== false) {
294
+			return $this->_get_payment_link_if_needed($shortcode);
295
+		}
296
+		if (strpos($shortcode, '[PAYMENT_DUE_DATE_*') !== false) {
297
+			return $this->_get_payment_due_date($shortcode, $transaction);
298
+		}
299
+		return '';
300
+	}
301
+
302
+
303
+
304
+	/**
305
+	 * parser for the [OWING_STATUS_MESSAGE_*] attribute type shortcode
306
+	 *
307
+	 * @since 4.5.0
308
+	 * @param string $shortcode the incoming shortcode
309
+	 * @return string parsed.
310
+	 */
311
+	private function _get_custom_total_owing($shortcode)
312
+	{
313
+		$valid_shortcodes = array('transaction');
314
+		$attrs = $this->_get_shortcode_attrs($shortcode);
315
+		//ensure default is set.
316
+		$addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null;
317
+		$total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction
318
+			? $addressee->txn->remaining() : 0;
319
+		if ($total_owing > 0) {
320
+			$owing_content = ! empty($attrs['still_owing'])
321
+				? $attrs['still_owing']
322
+				: sprintf(esc_html__('%sPlease make a payment.%s', 'event_espresso'),
323
+					'<a href="[PAYMENT_URL]" class="noPrint">', '</a>');
324
+			$owing_content = $this->_shortcode_helper->parse_message_template($owing_content, $addressee,
325
+				$valid_shortcodes, $this->_message_type, $this->_messenger, $this->_message);
326
+		} else {
327
+			$owing_content = ! empty($attrs['none_owing']) ? $attrs['none_owing'] : '';
328
+		}
329
+		return $owing_content;
330
+	}
331
+
332
+
333
+
334
+	/**
335
+	 * @param EE_Transaction $transaction
336
+	 * @return string
337
+	 */
338
+	private function _get_payment_gateway($transaction)
339
+	{
340
+		if($transaction instanceof EE_Transaction){
341
+			$pm = $transaction->payment_method();
342
+		} else {
343
+			$pm = null;
344
+		}
345
+		return $pm instanceof EE_Payment_Method ? $pm->name() : '';
346
+	}
347
+
348
+
349
+
350
+	/**
351
+	 * This retrieves a logo to be used for the invoice from whatever is set on the invoice logo settings page.  If its
352
+	 * not present then the organization logo is used if its found (set on the organization settings page).
353
+	 *
354
+	 * @since 4.5.0
355
+	 * @param bool $img_tags TRUE means to return with the img tag wrappers.  False just returns the url to the image.
356
+	 * @return string url or html
357
+	 */
358
+	private function _get_invoice_logo($img_tags = false)
359
+	{
360
+		//try to get the invoice payment method's logo for this transaction image first
361
+		$pm = $this->_get_invoice_payment_method();
362
+		if ($pm instanceof EE_Payment_Method) {
363
+			$invoice_logo_url = $pm->get_extra_meta('pdf_logo_image', true);
364
+		} else {
365
+			$invoice_logo_url = null;
366
+		}
367
+		if (empty($invoice_logo_url)) {
368
+			$invoice_logo_url = EE_Registry::instance()->CFG->organization->logo_url;
369
+		}
370
+		if (empty($invoice_logo_url)) {
371
+			return '';
372
+		}
373
+		if (! $img_tags) {
374
+			return $invoice_logo_url;
375
+		}
376
+		//image tags have been requested.
377
+		$image_size = getimagesize($invoice_logo_url);
378
+		//if image is wider than 300px, set the width to 300
379
+		if ($image_size[0] > 300) {
380
+			$image_width = 300;
381
+		} else {
382
+			$image_width = $image_size[0];
383
+		}
384
+		return '<img class="logo screen" src="' . $invoice_logo_url . '" width="' . $image_width . '" alt="logo" />';
385
+	}
386
+
387
+
388
+
389
+	/**
390
+	 * Used to retrieve the appropriate content for the invoice payee name shortcode
391
+	 *
392
+	 * @since 4.5.0
393
+	 * @return string
394
+	 */
395
+	private function _get_invoice_payee_name()
396
+	{
397
+		$payee_name = null;
398
+		$pm = $this->_get_invoice_payment_method();
399
+		if ($pm instanceof EE_Payment_Method) {
400
+			$payee_name = $pm->get_extra_meta('pdf_payee_name', true);
401
+		}
402
+		$payee_name = empty($payee_name) ? EE_Registry::instance()->CFG->organization->get_pretty('name') : $payee_name;
403
+		return $payee_name;
404
+	}
405
+
406
+
407
+
408
+	/**
409
+	 * gets the default invoice payment method, but has a filter so it can be overridden
410
+	 *
411
+	 * @return \EE_Payment_Method|null
412
+	 */
413
+	private function _get_invoice_payment_method()
414
+	{
415
+		if (! $this->_invoice_pm instanceof EE_Payment_Method) {
416
+			$transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null;
417
+			$transaction = ! $transaction instanceof EE_Transaction
418
+						   && is_array($this->_extra_data)
419
+						   && isset($this->_extra_data['data'])
420
+						   && $this->_extra_data['data'] instanceof EE_Messages_Addressee
421
+				? $this->_extra_data['data']->txn : $transaction;
422
+			//get the invoice payment method, and remember it for the next call too
423
+			$this->_invoice_pm = apply_filters('FHEE__EE_Transaction_Shortcodes__get_payment_method__default',
424
+				EEM_Payment_Method::instance()->get_one_of_type('Invoice'), $transaction);
425
+		}
426
+		return $this->_invoice_pm;
427
+	}
428
+
429
+
430
+
431
+	/**
432
+	 * Used to retrieve the appropriate content for the invoice payee email shortcode
433
+	 *
434
+	 * @since 4.5.0
435
+	 * @return string
436
+	 */
437
+	private function _get_invoice_payee_email()
438
+	{
439
+		$payee_email = null;
440
+		$pm = $this->_get_invoice_payment_method();
441
+		if ($pm instanceof EE_Payment_Method) {
442
+			$payee_email = $pm->get_extra_meta('pdf_payee_email', true);
443
+		}
444
+		$payee_email = empty($payee_email) ? EE_Registry::instance()->CFG->organization->get_pretty('email')
445
+			: $payee_email;
446
+		return $payee_email;
447
+	}
448
+
449
+
450
+
451
+	/**
452
+	 * Used to retrieve the appropriate content for the invoice payee tax number shortcode
453
+	 *
454
+	 * @since 4.5.0
455
+	 * @param string $shortcode
456
+	 * @return string
457
+	 */
458
+	private function _get_invoice_payee_tax_number($shortcode)
459
+	{
460
+		$payee_tax_number = null;
461
+		$pm = $this->_get_invoice_payment_method();
462
+		if ($pm instanceof EE_Payment_Method) {
463
+			$payee_tax_number = $pm->get_extra_meta('pdf_payee_tax_number', true);
464
+		}
465
+		$payee_tax_number = empty($payee_tax_number) ? EE_Registry::instance()->CFG->organization->vat
466
+			: $payee_tax_number;
467
+		if (empty($payee_tax_number)) {
468
+			return '';
469
+		}
470
+		//any attributes?
471
+		$attrs = $this->_get_shortcode_attrs($shortcode);
472
+		//prefix?
473
+		$prefix = isset($attrs['prefix']) ? $attrs['prefix'] : esc_html__('VAT/Tax Number: ', 'event_espresso');
474
+		return $prefix . $payee_tax_number;
475
+	}
476
+
477
+
478
+
479
+	/**
480
+	 * Used to retrieve the appropriate content for the invoice payee address shortcode.
481
+	 *
482
+	 * @since 4.5.0
483
+	 * @return string
484
+	 */
485
+	private function _get_invoice_payee_address()
486
+	{
487
+		$payee_address = null;
488
+		$pm = $this->_get_invoice_payment_method();
489
+		if ($pm instanceof EE_Payment_Method) {
490
+			$payee_address = $pm->get_extra_meta('pdf_payee_address', true);
491
+		}
492
+		if (empty($payee_address)) {
493
+			$organization = EE_Registry::instance()->CFG->organization;
494
+			$payee_address = $organization->get_pretty('address_1') . '<br>';
495
+			$payee_address .= ! empty($organization->address_2) ? $organization->get_pretty('address_2') . '<br>' : '';
496
+			$payee_address .= $organization->get_pretty('city') . '<br>';
497
+			//state
498
+			$state = EE_Registry::instance()->load_model('State')->get_one_by_ID($organization->STA_ID);
499
+			$payee_address .= $state instanceof EE_State ? $state->name() : '';
500
+			//Country
501
+			$payee_address .= ! empty($organization->CNT_ISO) ? ', ' . $organization->CNT_ISO . '<br>' : '';
502
+			$payee_address .= ! empty($organization->zip) ? $organization->zip : '';
503
+		}
504
+		return $payee_address;
505
+	}
506
+
507
+
508
+
509
+	/**
510
+	 * Used to retrieve the appropriate content for the invoice payment instructions shortcode.
511
+	 *
512
+	 * @since 4.5.0
513
+	 * @return string
514
+	 */
515
+	private function _get_invoice_payment_instructions()
516
+	{
517
+		$instructions = null;
518
+		$pm = $this->_get_invoice_payment_method();
519
+		return ($pm instanceof EE_Payment_Method) ? $pm->get_extra_meta('pdf_instructions', true) : '';
520
+	}
521
+
522
+
523
+
524
+	/**
525
+	 * get invoice/receipt switch button or url.
526
+	 *
527
+	 * @param bool $button true (default) returns the html for a button, false just returns the url.
528
+	 * @return string
529
+	 */
530
+	protected function _get_invoice_receipt_switcher($button = true)
531
+	{
532
+		$reg = $this->_data->primary_reg_obj;
533
+		$message_type = isset($this->_extra_data['message_type']) ? $this->_extra_data['message_type'] : '';
534
+		if (! $reg instanceof EE_Registration || empty($message_type)) {
535
+			return '';
536
+		}
537
+		$switch_to_invoice = ! $message_type instanceof EE_Invoice_message_type ? true : false;
538
+		$switch_to_label = $switch_to_invoice && ! $message_type instanceof EE_Receipt_message_type
539
+			? esc_html__('View Invoice', 'event_espresso') : esc_html__('Switch to Invoice', 'event_espresso');
540
+		$switch_to_label = ! $switch_to_invoice ? esc_html__('Switch to Receipt', 'event_espresso') : $switch_to_label;
541
+		$switch_to_url = $switch_to_invoice ? $reg->invoice_url() : $reg->receipt_url();
542
+		if (! $button) {
543
+			return $switch_to_url;
544
+		}
545
+		if (! empty($switch_to_url)) {
546
+			return '
547 547
 	<form method="post" action="' . $switch_to_url . '" >
548 548
 		<input class="print_button" type="submit" value="' . $switch_to_label . '" />
549 549
 	</form>
550 550
 			';
551
-        }
552
-        return '';
553
-    }
554
-
555
-
556
-
557
-    /**
558
-     * This returns a subtotal.
559
-     *
560
-     * @param bool $tax if true then return the subtotal for tax otherwise return subtotal.
561
-     * @return int
562
-     */
563
-    private function _get_subtotal($tax = false)
564
-    {
565
-        $grand_total = isset($this->_data->grand_total_line_item) ? $this->_data->grand_total_line_item : null;
566
-        if (! $grand_total instanceof EE_Line_Item) {
567
-            return 0;
568
-        }
569
-        return $tax ? $grand_total->get_total_tax() : $grand_total->get_items_total();
570
-    }
571
-
572
-
573
-
574
-    /**
575
-     * parser for the [PAYMENT_LINK_IF_NEEDED_*] attribute type shortcode
576
-     *
577
-     * @since 4.7.0
578
-     * @param string $shortcode the incoming shortcode
579
-     * @return string parsed.
580
-     */
581
-    private function _get_payment_link_if_needed($shortcode)
582
-    {
583
-        $valid_shortcodes = array('transaction');
584
-        $attrs = $this->_get_shortcode_attrs($shortcode);
585
-        //ensure default is set.
586
-        $addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null;
587
-        $total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction
588
-            ? $addressee->txn->remaining() : 0;
589
-        if ($total_owing > 0) {
590
-            $class = isset($attrs['class']) ? $attrs['class'] : 'callout';
591
-            $custom_text = isset($attrs['custom_text']) ? $attrs['custom_text'] : 'You can %smake a payment here »%s.';
592
-            $container_tag = isset($attrs['container_tag']) ? $attrs['container_tag'] : 'p';
593
-            $opening_tag = ! empty($container_tag) ? '<' . $container_tag : '';
594
-            $opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="' . $class . '"' : $opening_tag;
595
-            $opening_tag .= ! empty($opening_tag) ? '>' : $opening_tag;
596
-            $closing_tag = ! empty($container_tag) ? '</' . $container_tag . '>' : '';
597
-            $content = $opening_tag . sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>') . $closing_tag;
598
-            //we need to re run this string through the parser to catch any shortcodes that are in it.
599
-            $owing_content = $this->_shortcode_helper->parse_message_template($content, $addressee, $valid_shortcodes,
600
-                $this->_message_type, $this->_messenger, $this->_message);
601
-        } else {
602
-            return '';
603
-        }
604
-        return $owing_content;
605
-    }
606
-
607
-
608
-
609
-    /**
610
-     * Parser for the [PAYMENT_DUE_DATE_*] attribute type shortcode
611
-     *
612
-     * @since 4.8.28.rc.011
613
-     * @param string         $shortcode The shortcode being parsed.
614
-     * @param EE_Transaction $transaction
615
-     * @return string
616
-     */
617
-    protected function _get_payment_due_date($shortcode, EE_Transaction $transaction)
618
-    {
619
-        //if transaction is paid in full then we can just return an empty string
620
-        if ($transaction->remaining() === 0) {
621
-            return '';
622
-        }
623
-        $attrs = $this->_get_shortcode_attrs($shortcode);
624
-        $format = isset($attrs['format']) ? $attrs['format'] : get_option('date_format');
625
-        $days_until_due = isset($attrs['days_until_due']) ? (int)$attrs['days_until_due'] : 30;
626
-        $prefix_text = isset($attrs['prefix_text']) ? $attrs['prefix_text']
627
-            : esc_html__('Payment in full due by: ', 'event_espresso');
628
-        $transaction_created = $transaction->get_DateTime_object('TXN_timestamp');
629
-        //setup date due:
630
-        try {
631
-            if ($transaction_created instanceof DateTime) {
632
-                $date_due = $transaction_created->add(new DateInterval('P' . $days_until_due . 'D'))->format($format);
633
-            } else {
634
-                throw new Exception();
635
-            }
636
-        } catch (Exception $e) {
637
-            //format was likely invalid.
638
-            $date_due = 'Unable to calculate date due, likely the format string is invalid.';
639
-        }
640
-        return $prefix_text . $date_due;
641
-    }
551
+		}
552
+		return '';
553
+	}
554
+
555
+
556
+
557
+	/**
558
+	 * This returns a subtotal.
559
+	 *
560
+	 * @param bool $tax if true then return the subtotal for tax otherwise return subtotal.
561
+	 * @return int
562
+	 */
563
+	private function _get_subtotal($tax = false)
564
+	{
565
+		$grand_total = isset($this->_data->grand_total_line_item) ? $this->_data->grand_total_line_item : null;
566
+		if (! $grand_total instanceof EE_Line_Item) {
567
+			return 0;
568
+		}
569
+		return $tax ? $grand_total->get_total_tax() : $grand_total->get_items_total();
570
+	}
571
+
572
+
573
+
574
+	/**
575
+	 * parser for the [PAYMENT_LINK_IF_NEEDED_*] attribute type shortcode
576
+	 *
577
+	 * @since 4.7.0
578
+	 * @param string $shortcode the incoming shortcode
579
+	 * @return string parsed.
580
+	 */
581
+	private function _get_payment_link_if_needed($shortcode)
582
+	{
583
+		$valid_shortcodes = array('transaction');
584
+		$attrs = $this->_get_shortcode_attrs($shortcode);
585
+		//ensure default is set.
586
+		$addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null;
587
+		$total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction
588
+			? $addressee->txn->remaining() : 0;
589
+		if ($total_owing > 0) {
590
+			$class = isset($attrs['class']) ? $attrs['class'] : 'callout';
591
+			$custom_text = isset($attrs['custom_text']) ? $attrs['custom_text'] : 'You can %smake a payment here »%s.';
592
+			$container_tag = isset($attrs['container_tag']) ? $attrs['container_tag'] : 'p';
593
+			$opening_tag = ! empty($container_tag) ? '<' . $container_tag : '';
594
+			$opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="' . $class . '"' : $opening_tag;
595
+			$opening_tag .= ! empty($opening_tag) ? '>' : $opening_tag;
596
+			$closing_tag = ! empty($container_tag) ? '</' . $container_tag . '>' : '';
597
+			$content = $opening_tag . sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>') . $closing_tag;
598
+			//we need to re run this string through the parser to catch any shortcodes that are in it.
599
+			$owing_content = $this->_shortcode_helper->parse_message_template($content, $addressee, $valid_shortcodes,
600
+				$this->_message_type, $this->_messenger, $this->_message);
601
+		} else {
602
+			return '';
603
+		}
604
+		return $owing_content;
605
+	}
606
+
607
+
608
+
609
+	/**
610
+	 * Parser for the [PAYMENT_DUE_DATE_*] attribute type shortcode
611
+	 *
612
+	 * @since 4.8.28.rc.011
613
+	 * @param string         $shortcode The shortcode being parsed.
614
+	 * @param EE_Transaction $transaction
615
+	 * @return string
616
+	 */
617
+	protected function _get_payment_due_date($shortcode, EE_Transaction $transaction)
618
+	{
619
+		//if transaction is paid in full then we can just return an empty string
620
+		if ($transaction->remaining() === 0) {
621
+			return '';
622
+		}
623
+		$attrs = $this->_get_shortcode_attrs($shortcode);
624
+		$format = isset($attrs['format']) ? $attrs['format'] : get_option('date_format');
625
+		$days_until_due = isset($attrs['days_until_due']) ? (int)$attrs['days_until_due'] : 30;
626
+		$prefix_text = isset($attrs['prefix_text']) ? $attrs['prefix_text']
627
+			: esc_html__('Payment in full due by: ', 'event_espresso');
628
+		$transaction_created = $transaction->get_DateTime_object('TXN_timestamp');
629
+		//setup date due:
630
+		try {
631
+			if ($transaction_created instanceof DateTime) {
632
+				$date_due = $transaction_created->add(new DateInterval('P' . $days_until_due . 'D'))->format($format);
633
+			} else {
634
+				throw new Exception();
635
+			}
636
+		} catch (Exception $e) {
637
+			//format was likely invalid.
638
+			$date_due = 'Unable to calculate date due, likely the format string is invalid.';
639
+		}
640
+		return $prefix_text . $date_due;
641
+	}
642 642
 
643 643
 } //end EE_Transaction Shortcodes library
Please login to merge, or discard this patch.
Spacing   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-if (! defined('EVENT_ESPRESSO_VERSION')) {
2
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
3 3
     exit('NO direct script access allowed');
4 4
 }
5 5
 
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
                    && isset($this->_extra_data['data'])
174 174
                    && $this->_extra_data['data'] instanceof EE_Messages_Addressee ? $this->_extra_data['data']->payment
175 175
             : $payment;
176
-        if (! $transaction instanceof EE_Transaction) {
176
+        if ( ! $transaction instanceof EE_Transaction) {
177 177
             return '';
178 178
         }
179 179
         switch ($shortcode) {
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
                 $invoice_url = $transaction->invoice_url();
190 190
                 $invoice_url = empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url;
191 191
                 return sprintf(esc_html__('%sClick here for Invoice%s', 'event_espresso'),
192
-                    '<a href="' . $invoice_url . '">', '</a>');
192
+                    '<a href="'.$invoice_url.'">', '</a>');
193 193
                 break; /**/
194 194
             case '[INVOICE_URL]' :
195 195
                 $invoice_url = $transaction->invoice_url();
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
                 return $this->_data->total_ticket_count;
261 261
                 break;
262 262
             case '[TRANSACTION_ADMIN_URL]' :
263
-                require_once EE_CORE . 'admin/EE_Admin_Page.core.php';
263
+                require_once EE_CORE.'admin/EE_Admin_Page.core.php';
264 264
                 $query_args = array(
265 265
                     'page'   => 'espresso_transactions',
266 266
                     'action' => 'view_transaction',
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
             case '[RECEIPT_URL]' :
273 273
                 //get primary_registration
274 274
                 $reg = $this->_data->primary_reg_obj;
275
-                if (! $reg instanceof EE_Registration) {
275
+                if ( ! $reg instanceof EE_Registration) {
276 276
                     return '';
277 277
                 }
278 278
                 return $reg->receipt_url();
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
      */
338 338
     private function _get_payment_gateway($transaction)
339 339
     {
340
-        if($transaction instanceof EE_Transaction){
340
+        if ($transaction instanceof EE_Transaction) {
341 341
             $pm = $transaction->payment_method();
342 342
         } else {
343 343
             $pm = null;
@@ -370,7 +370,7 @@  discard block
 block discarded – undo
370 370
         if (empty($invoice_logo_url)) {
371 371
             return '';
372 372
         }
373
-        if (! $img_tags) {
373
+        if ( ! $img_tags) {
374 374
             return $invoice_logo_url;
375 375
         }
376 376
         //image tags have been requested.
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
         } else {
382 382
             $image_width = $image_size[0];
383 383
         }
384
-        return '<img class="logo screen" src="' . $invoice_logo_url . '" width="' . $image_width . '" alt="logo" />';
384
+        return '<img class="logo screen" src="'.$invoice_logo_url.'" width="'.$image_width.'" alt="logo" />';
385 385
     }
386 386
 
387 387
 
@@ -412,7 +412,7 @@  discard block
 block discarded – undo
412 412
      */
413 413
     private function _get_invoice_payment_method()
414 414
     {
415
-        if (! $this->_invoice_pm instanceof EE_Payment_Method) {
415
+        if ( ! $this->_invoice_pm instanceof EE_Payment_Method) {
416 416
             $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null;
417 417
             $transaction = ! $transaction instanceof EE_Transaction
418 418
                            && is_array($this->_extra_data)
@@ -471,7 +471,7 @@  discard block
 block discarded – undo
471 471
         $attrs = $this->_get_shortcode_attrs($shortcode);
472 472
         //prefix?
473 473
         $prefix = isset($attrs['prefix']) ? $attrs['prefix'] : esc_html__('VAT/Tax Number: ', 'event_espresso');
474
-        return $prefix . $payee_tax_number;
474
+        return $prefix.$payee_tax_number;
475 475
     }
476 476
 
477 477
 
@@ -491,14 +491,14 @@  discard block
 block discarded – undo
491 491
         }
492 492
         if (empty($payee_address)) {
493 493
             $organization = EE_Registry::instance()->CFG->organization;
494
-            $payee_address = $organization->get_pretty('address_1') . '<br>';
495
-            $payee_address .= ! empty($organization->address_2) ? $organization->get_pretty('address_2') . '<br>' : '';
496
-            $payee_address .= $organization->get_pretty('city') . '<br>';
494
+            $payee_address = $organization->get_pretty('address_1').'<br>';
495
+            $payee_address .= ! empty($organization->address_2) ? $organization->get_pretty('address_2').'<br>' : '';
496
+            $payee_address .= $organization->get_pretty('city').'<br>';
497 497
             //state
498 498
             $state = EE_Registry::instance()->load_model('State')->get_one_by_ID($organization->STA_ID);
499 499
             $payee_address .= $state instanceof EE_State ? $state->name() : '';
500 500
             //Country
501
-            $payee_address .= ! empty($organization->CNT_ISO) ? ', ' . $organization->CNT_ISO . '<br>' : '';
501
+            $payee_address .= ! empty($organization->CNT_ISO) ? ', '.$organization->CNT_ISO.'<br>' : '';
502 502
             $payee_address .= ! empty($organization->zip) ? $organization->zip : '';
503 503
         }
504 504
         return $payee_address;
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
     {
532 532
         $reg = $this->_data->primary_reg_obj;
533 533
         $message_type = isset($this->_extra_data['message_type']) ? $this->_extra_data['message_type'] : '';
534
-        if (! $reg instanceof EE_Registration || empty($message_type)) {
534
+        if ( ! $reg instanceof EE_Registration || empty($message_type)) {
535 535
             return '';
536 536
         }
537 537
         $switch_to_invoice = ! $message_type instanceof EE_Invoice_message_type ? true : false;
@@ -539,13 +539,13 @@  discard block
 block discarded – undo
539 539
             ? esc_html__('View Invoice', 'event_espresso') : esc_html__('Switch to Invoice', 'event_espresso');
540 540
         $switch_to_label = ! $switch_to_invoice ? esc_html__('Switch to Receipt', 'event_espresso') : $switch_to_label;
541 541
         $switch_to_url = $switch_to_invoice ? $reg->invoice_url() : $reg->receipt_url();
542
-        if (! $button) {
542
+        if ( ! $button) {
543 543
             return $switch_to_url;
544 544
         }
545
-        if (! empty($switch_to_url)) {
545
+        if ( ! empty($switch_to_url)) {
546 546
             return '
547
-	<form method="post" action="' . $switch_to_url . '" >
548
-		<input class="print_button" type="submit" value="' . $switch_to_label . '" />
547
+	<form method="post" action="' . $switch_to_url.'" >
548
+		<input class="print_button" type="submit" value="' . $switch_to_label.'" />
549 549
 	</form>
550 550
 			';
551 551
         }
@@ -563,7 +563,7 @@  discard block
 block discarded – undo
563 563
     private function _get_subtotal($tax = false)
564 564
     {
565 565
         $grand_total = isset($this->_data->grand_total_line_item) ? $this->_data->grand_total_line_item : null;
566
-        if (! $grand_total instanceof EE_Line_Item) {
566
+        if ( ! $grand_total instanceof EE_Line_Item) {
567 567
             return 0;
568 568
         }
569 569
         return $tax ? $grand_total->get_total_tax() : $grand_total->get_items_total();
@@ -590,11 +590,11 @@  discard block
 block discarded – undo
590 590
             $class = isset($attrs['class']) ? $attrs['class'] : 'callout';
591 591
             $custom_text = isset($attrs['custom_text']) ? $attrs['custom_text'] : 'You can %smake a payment here »%s.';
592 592
             $container_tag = isset($attrs['container_tag']) ? $attrs['container_tag'] : 'p';
593
-            $opening_tag = ! empty($container_tag) ? '<' . $container_tag : '';
594
-            $opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="' . $class . '"' : $opening_tag;
593
+            $opening_tag = ! empty($container_tag) ? '<'.$container_tag : '';
594
+            $opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="'.$class.'"' : $opening_tag;
595 595
             $opening_tag .= ! empty($opening_tag) ? '>' : $opening_tag;
596
-            $closing_tag = ! empty($container_tag) ? '</' . $container_tag . '>' : '';
597
-            $content = $opening_tag . sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>') . $closing_tag;
596
+            $closing_tag = ! empty($container_tag) ? '</'.$container_tag.'>' : '';
597
+            $content = $opening_tag.sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>').$closing_tag;
598 598
             //we need to re run this string through the parser to catch any shortcodes that are in it.
599 599
             $owing_content = $this->_shortcode_helper->parse_message_template($content, $addressee, $valid_shortcodes,
600 600
                 $this->_message_type, $this->_messenger, $this->_message);
@@ -622,14 +622,14 @@  discard block
 block discarded – undo
622 622
         }
623 623
         $attrs = $this->_get_shortcode_attrs($shortcode);
624 624
         $format = isset($attrs['format']) ? $attrs['format'] : get_option('date_format');
625
-        $days_until_due = isset($attrs['days_until_due']) ? (int)$attrs['days_until_due'] : 30;
625
+        $days_until_due = isset($attrs['days_until_due']) ? (int) $attrs['days_until_due'] : 30;
626 626
         $prefix_text = isset($attrs['prefix_text']) ? $attrs['prefix_text']
627 627
             : esc_html__('Payment in full due by: ', 'event_espresso');
628 628
         $transaction_created = $transaction->get_DateTime_object('TXN_timestamp');
629 629
         //setup date due:
630 630
         try {
631 631
             if ($transaction_created instanceof DateTime) {
632
-                $date_due = $transaction_created->add(new DateInterval('P' . $days_until_due . 'D'))->format($format);
632
+                $date_due = $transaction_created->add(new DateInterval('P'.$days_until_due.'D'))->format($format);
633 633
             } else {
634 634
                 throw new Exception();
635 635
             }
@@ -637,7 +637,7 @@  discard block
 block discarded – undo
637 637
             //format was likely invalid.
638 638
             $date_due = 'Unable to calculate date due, likely the format string is invalid.';
639 639
         }
640
-        return $prefix_text . $date_due;
640
+        return $prefix_text.$date_due;
641 641
     }
642 642
 
643 643
 } //end EE_Transaction Shortcodes library
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('ABSPATH')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /*
5 5
   Plugin Name:		Event Espresso
@@ -40,243 +40,243 @@  discard block
 block discarded – undo
40 40
  * @since            4.0
41 41
  */
42 42
 if (function_exists('espresso_version')) {
43
-    /**
44
-     *    espresso_duplicate_plugin_error
45
-     *    displays if more than one version of EE is activated at the same time
46
-     */
47
-    function espresso_duplicate_plugin_error()
48
-    {
49
-        ?>
43
+	/**
44
+	 *    espresso_duplicate_plugin_error
45
+	 *    displays if more than one version of EE is activated at the same time
46
+	 */
47
+	function espresso_duplicate_plugin_error()
48
+	{
49
+		?>
50 50
         <div class="error">
51 51
             <p>
52 52
                 <?php echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                ); ?>
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+				); ?>
56 56
             </p>
57 57
         </div>
58 58
         <?php
59
-        espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-    }
59
+		espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+	}
61 61
 
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
-    if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
+	if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                            esc_html__(
79
-                                    'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                                    'event_espresso'
81
-                            ),
82
-                            EE_MIN_PHP_VER_REQUIRED,
83
-                            PHP_VERSION,
84
-                            '<br/>',
85
-                            '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+							esc_html__(
79
+									'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+									'event_espresso'
81
+							),
82
+							EE_MIN_PHP_VER_REQUIRED,
83
+							PHP_VERSION,
84
+							'<br/>',
85
+							'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        /**
97
-         * espresso_version
98
-         * Returns the plugin version
99
-         *
100
-         * @return string
101
-         */
102
-        function espresso_version()
103
-        {
104
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.35.rc.009');
105
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		/**
97
+		 * espresso_version
98
+		 * Returns the plugin version
99
+		 *
100
+		 * @return string
101
+		 */
102
+		function espresso_version()
103
+		{
104
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.35.rc.009');
105
+		}
106 106
 
107
-        // define versions
108
-        define('EVENT_ESPRESSO_VERSION', espresso_version());
109
-        define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
-        define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
-        define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
-        //used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
-        if ( ! defined('DS')) {
115
-            define('DS', '/');
116
-        }
117
-        if ( ! defined('PS')) {
118
-            define('PS', PATH_SEPARATOR);
119
-        }
120
-        if ( ! defined('SP')) {
121
-            define('SP', ' ');
122
-        }
123
-        if ( ! defined('EENL')) {
124
-            define('EENL', "\n");
125
-        }
126
-        define('EE_SUPPORT_EMAIL', '[email protected]');
127
-        // define the plugin directory and URL
128
-        define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
-        define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
-        define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
-        // main root folder paths
132
-        define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
-        define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
-        define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
-        define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
-        define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
-        define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
-        define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
-        define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
-        // core system paths
141
-        define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
-        define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
-        define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
-        define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
-        define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
-        define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
-        define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
-        define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
-        define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
-        define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
-        define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
-        define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
-        // gateways
154
-        define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
-        define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
-        // asset URL paths
157
-        define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
-        define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
-        define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
-        define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
-        define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
-        define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
-        // define upload paths
164
-        $uploads = wp_upload_dir();
165
-        // define the uploads directory and URL
166
-        define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
-        define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
-        // define the templates directory and URL
169
-        define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
-        define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
-        // define the gateway directory and URL
172
-        define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
-        define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
-        // languages folder/path
175
-        define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
-        define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
-        //check for dompdf fonts in uploads
178
-        if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
-            define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
-        }
181
-        //ajax constants
182
-        define(
183
-                'EE_FRONT_AJAX',
184
-                isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
-        );
186
-        define(
187
-                'EE_ADMIN_AJAX',
188
-                isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
-        );
190
-        //just a handy constant occasionally needed for finding values representing infinity in the DB
191
-        //you're better to use this than its straight value (currently -1) in case you ever
192
-        //want to change its default value! or find when -1 means infinity
193
-        define('EE_INF_IN_DB', -1);
194
-        define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
-        define('EE_DEBUG', false);
196
-        // for older WP versions
197
-        if ( ! defined('MONTH_IN_SECONDS')) {
198
-            define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
-        }
200
-        /**
201
-         *    espresso_plugin_activation
202
-         *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
-         */
204
-        function espresso_plugin_activation()
205
-        {
206
-            update_option('ee_espresso_activation', true);
207
-        }
107
+		// define versions
108
+		define('EVENT_ESPRESSO_VERSION', espresso_version());
109
+		define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
+		define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
+		define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
+		//used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
+		if ( ! defined('DS')) {
115
+			define('DS', '/');
116
+		}
117
+		if ( ! defined('PS')) {
118
+			define('PS', PATH_SEPARATOR);
119
+		}
120
+		if ( ! defined('SP')) {
121
+			define('SP', ' ');
122
+		}
123
+		if ( ! defined('EENL')) {
124
+			define('EENL', "\n");
125
+		}
126
+		define('EE_SUPPORT_EMAIL', '[email protected]');
127
+		// define the plugin directory and URL
128
+		define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
+		define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
+		define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
+		// main root folder paths
132
+		define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
+		define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
+		define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
+		define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
+		define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
+		define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
+		define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
+		define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
+		// core system paths
141
+		define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
+		define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
+		define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
+		define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
+		define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
+		define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
+		define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
+		define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
+		define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
+		define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
+		define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
+		define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
+		// gateways
154
+		define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
+		define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
+		// asset URL paths
157
+		define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
+		define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
+		define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
+		define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
+		define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
+		define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
+		// define upload paths
164
+		$uploads = wp_upload_dir();
165
+		// define the uploads directory and URL
166
+		define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
+		define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
+		// define the templates directory and URL
169
+		define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
+		define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
+		// define the gateway directory and URL
172
+		define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
+		define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
+		// languages folder/path
175
+		define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
+		define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
+		//check for dompdf fonts in uploads
178
+		if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
+			define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
+		}
181
+		//ajax constants
182
+		define(
183
+				'EE_FRONT_AJAX',
184
+				isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
+		);
186
+		define(
187
+				'EE_ADMIN_AJAX',
188
+				isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
+		);
190
+		//just a handy constant occasionally needed for finding values representing infinity in the DB
191
+		//you're better to use this than its straight value (currently -1) in case you ever
192
+		//want to change its default value! or find when -1 means infinity
193
+		define('EE_INF_IN_DB', -1);
194
+		define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
+		define('EE_DEBUG', false);
196
+		// for older WP versions
197
+		if ( ! defined('MONTH_IN_SECONDS')) {
198
+			define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
+		}
200
+		/**
201
+		 *    espresso_plugin_activation
202
+		 *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
+		 */
204
+		function espresso_plugin_activation()
205
+		{
206
+			update_option('ee_espresso_activation', true);
207
+		}
208 208
 
209
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
-        /**
211
-         *    espresso_load_error_handling
212
-         *    this function loads EE's class for handling exceptions and errors
213
-         */
214
-        function espresso_load_error_handling()
215
-        {
216
-            // load debugging tools
217
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
-                EEH_Debug_Tools::instance();
220
-            }
221
-            // load error handling
222
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
-                require_once(EE_CORE . 'EE_Error.core.php');
224
-            } else {
225
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
-            }
227
-        }
209
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
+		/**
211
+		 *    espresso_load_error_handling
212
+		 *    this function loads EE's class for handling exceptions and errors
213
+		 */
214
+		function espresso_load_error_handling()
215
+		{
216
+			// load debugging tools
217
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
+				EEH_Debug_Tools::instance();
220
+			}
221
+			// load error handling
222
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
+				require_once(EE_CORE . 'EE_Error.core.php');
224
+			} else {
225
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
+			}
227
+		}
228 228
 
229
-        /**
230
-         *    espresso_load_required
231
-         *    given a class name and path, this function will load that file or throw an exception
232
-         *
233
-         * @param    string $classname
234
-         * @param    string $full_path_to_file
235
-         * @throws    EE_Error
236
-         */
237
-        function espresso_load_required($classname, $full_path_to_file)
238
-        {
239
-            static $error_handling_loaded = false;
240
-            if ( ! $error_handling_loaded) {
241
-                espresso_load_error_handling();
242
-                $error_handling_loaded = true;
243
-            }
244
-            if (is_readable($full_path_to_file)) {
245
-                require_once($full_path_to_file);
246
-            } else {
247
-                throw new EE_Error (
248
-                        sprintf(
249
-                                esc_html__(
250
-                                        'The %s class file could not be located or is not readable due to file permissions.',
251
-                                        'event_espresso'
252
-                                ),
253
-                                $classname
254
-                        )
255
-                );
256
-            }
257
-        }
229
+		/**
230
+		 *    espresso_load_required
231
+		 *    given a class name and path, this function will load that file or throw an exception
232
+		 *
233
+		 * @param    string $classname
234
+		 * @param    string $full_path_to_file
235
+		 * @throws    EE_Error
236
+		 */
237
+		function espresso_load_required($classname, $full_path_to_file)
238
+		{
239
+			static $error_handling_loaded = false;
240
+			if ( ! $error_handling_loaded) {
241
+				espresso_load_error_handling();
242
+				$error_handling_loaded = true;
243
+			}
244
+			if (is_readable($full_path_to_file)) {
245
+				require_once($full_path_to_file);
246
+			} else {
247
+				throw new EE_Error (
248
+						sprintf(
249
+								esc_html__(
250
+										'The %s class file could not be located or is not readable due to file permissions.',
251
+										'event_espresso'
252
+								),
253
+								$classname
254
+						)
255
+				);
256
+			}
257
+		}
258 258
 
259
-        espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
-        espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
-        espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
-        new EE_Bootstrap();
263
-    }
259
+		espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
+		espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
+		espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
+		new EE_Bootstrap();
263
+	}
264 264
 }
265 265
 if ( ! function_exists('espresso_deactivate_plugin')) {
266
-    /**
267
-     *    deactivate_plugin
268
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
-     *
270
-     * @access public
271
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
-     * @return    void
273
-     */
274
-    function espresso_deactivate_plugin($plugin_basename = '')
275
-    {
276
-        if ( ! function_exists('deactivate_plugins')) {
277
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
-        }
279
-        unset($_GET['activate'], $_REQUEST['activate']);
280
-        deactivate_plugins($plugin_basename);
281
-    }
266
+	/**
267
+	 *    deactivate_plugin
268
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
+	 *
270
+	 * @access public
271
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
+	 * @return    void
273
+	 */
274
+	function espresso_deactivate_plugin($plugin_basename = '')
275
+	{
276
+		if ( ! function_exists('deactivate_plugins')) {
277
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
+		}
279
+		unset($_GET['activate'], $_REQUEST['activate']);
280
+		deactivate_plugins($plugin_basename);
281
+	}
282 282
 }
283 283
\ No newline at end of file
Please login to merge, or discard this patch.