Completed
Branch FET-8385-datetime-ticket-selec... (1e9ded)
by
unknown
83:08 queued 72:04
created
core/libraries/rest_api/controllers/model/Read.php 2 patches
Indentation   +1101 added lines, -1101 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@  discard block
 block discarded – undo
7 7
 use EventEspresso\core\libraries\rest_api\Model_Data_Translator;
8 8
 
9 9
 if (! defined('EVENT_ESPRESSO_VERSION')) {
10
-    exit('No direct script access allowed');
10
+	exit('No direct script access allowed');
11 11
 }
12 12
 
13 13
 
@@ -25,1106 +25,1106 @@  discard block
 block discarded – undo
25 25
 
26 26
 
27 27
 
28
-    /**
29
-     * @var Calculated_Model_Fields
30
-     */
31
-    protected $_fields_calculator;
32
-
33
-
34
-
35
-    /**
36
-     * Read constructor.
37
-     */
38
-    public function __construct()
39
-    {
40
-        parent::__construct();
41
-        $this->_fields_calculator = new Calculated_Model_Fields();
42
-    }
43
-
44
-
45
-
46
-    /**
47
-     * Handles requests to get all (or a filtered subset) of entities for a particular model
48
-     *
49
-     * @param \WP_REST_Request $request
50
-     * @return \WP_REST_Response|\WP_Error
51
-     */
52
-    public static function handle_request_get_all(\WP_REST_Request $request)
53
-    {
54
-        $controller = new Read();
55
-        try {
56
-            $matches = $controller->parse_route(
57
-                $request->get_route(),
58
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)~',
59
-                array('version', 'model')
60
-            );
61
-            $controller->set_requested_version($matches['version']);
62
-            $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
63
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
64
-                return $controller->send_response(
65
-                    new \WP_Error(
66
-                        'endpoint_parsing_error',
67
-                        sprintf(
68
-                            __('There is no model for endpoint %s. Please contact event espresso support',
69
-                                'event_espresso'),
70
-                            $model_name_singular
71
-                        )
72
-                    )
73
-                );
74
-            }
75
-            return $controller->send_response(
76
-                $controller->get_entities_from_model(
77
-                    $controller->get_model_version_info()->load_model($model_name_singular),
78
-                    $request
79
-                )
80
-            );
81
-        } catch (\Exception $e) {
82
-            return $controller->send_response($e);
83
-        }
84
-    }
85
-
86
-
87
-
88
-    /**
89
-     * Gets a single entity related to the model indicated in the path and its id
90
-     *
91
-     * @param \WP_REST_Request $request
92
-     * @return \WP_REST_Response|\WP_Error
93
-     */
94
-    public static function handle_request_get_one(\WP_REST_Request $request)
95
-    {
96
-        $controller = new Read();
97
-        try {
98
-            $matches = $controller->parse_route(
99
-                $request->get_route(),
100
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)~',
101
-                array('version', 'model', 'id'));
102
-            $controller->set_requested_version($matches['version']);
103
-            $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
104
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
105
-                return $controller->send_response(
106
-                    new \WP_Error(
107
-                        'endpoint_parsing_error',
108
-                        sprintf(
109
-                            __('There is no model for endpoint %s. Please contact event espresso support',
110
-                                'event_espresso'),
111
-                            $model_name_singular
112
-                        )
113
-                    )
114
-                );
115
-            }
116
-            return $controller->send_response(
117
-                $controller->get_entity_from_model(
118
-                    $controller->get_model_version_info()->load_model($model_name_singular),
119
-                    $request
120
-                )
121
-            );
122
-        } catch (\Exception $e) {
123
-            return $controller->send_response($e);
124
-        }
125
-    }
126
-
127
-
128
-
129
-    /**
130
-     * Gets all the related entities (or if its a belongs-to relation just the one)
131
-     * to the item with the given id
132
-     *
133
-     * @param \WP_REST_Request $request
134
-     * @return \WP_REST_Response|\WP_Error
135
-     */
136
-    public static function handle_request_get_related(\WP_REST_Request $request)
137
-    {
138
-        $controller = new Read();
139
-        try {
140
-            $matches = $controller->parse_route(
141
-                $request->get_route(),
142
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)/(.*)~',
143
-                array('version', 'model', 'id', 'related_model')
144
-            );
145
-            $controller->set_requested_version($matches['version']);
146
-            $main_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
147
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
148
-                return $controller->send_response(
149
-                    new \WP_Error(
150
-                        'endpoint_parsing_error',
151
-                        sprintf(
152
-                            __('There is no model for endpoint %s. Please contact event espresso support',
153
-                                'event_espresso'),
154
-                            $main_model_name_singular
155
-                        )
156
-                    )
157
-                );
158
-            }
159
-            $main_model = $controller->get_model_version_info()->load_model($main_model_name_singular);
160
-            //assume the related model name is plural and try to find the model's name
161
-            $related_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['related_model']);
162
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
163
-                //so the word didn't singularize well. Maybe that's just because it's a singular word?
164
-                $related_model_name_singular = \EEH_Inflector::humanize($matches['related_model']);
165
-            }
166
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
167
-                return $controller->send_response(
168
-                    new \WP_Error(
169
-                        'endpoint_parsing_error',
170
-                        sprintf(
171
-                            __('There is no model for endpoint %s. Please contact event espresso support',
172
-                                'event_espresso'),
173
-                            $related_model_name_singular
174
-                        )
175
-                    )
176
-                );
177
-            }
178
-            return $controller->send_response(
179
-                $controller->get_entities_from_relation(
180
-                    $request->get_param('id'),
181
-                    $main_model->related_settings_for($related_model_name_singular),
182
-                    $request
183
-                )
184
-            );
185
-        } catch (\Exception $e) {
186
-            return $controller->send_response($e);
187
-        }
188
-    }
189
-
190
-
191
-
192
-    /**
193
-     * Gets a collection for the given model and filters
194
-     *
195
-     * @param \EEM_Base        $model
196
-     * @param \WP_REST_Request $request
197
-     * @return array|\WP_Error
198
-     */
199
-    public function get_entities_from_model($model, $request)
200
-    {
201
-        $query_params = $this->create_model_query_params($model, $request->get_params());
202
-        if (! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
203
-            $model_name_plural = \EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
204
-            return new \WP_Error(
205
-                sprintf('rest_%s_cannot_list', $model_name_plural),
206
-                sprintf(
207
-                    __('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
208
-                    $model_name_plural,
209
-                    Capabilities::get_missing_permissions_string($model, $query_params['caps'])
210
-                ),
211
-                array('status' => 403)
212
-            );
213
-        }
214
-        if (! $request->get_header('no_rest_headers')) {
215
-            $this->_set_headers_from_query_params($model, $query_params);
216
-        }
217
-        /** @type array $results */
218
-        $results = $model->get_all_wpdb_results($query_params);
219
-        $nice_results = array();
220
-        foreach ($results as $result) {
221
-            $nice_results[] = $this->create_entity_from_wpdb_result(
222
-                $model,
223
-                $result,
224
-                $request
225
-            );
226
-        }
227
-        return $nice_results;
228
-    }
229
-
230
-
231
-
232
-    /**
233
-     * @param array                   $primary_model_query_params query params for finding the item from which
234
-     *                                                            relations will be based
235
-     * @param \EE_Model_Relation_Base $relation
236
-     * @param \WP_REST_Request        $request
237
-     * @return \WP_Error|array
238
-     */
239
-    protected function _get_entities_from_relation($primary_model_query_params, $relation, $request)
240
-    {
241
-        $context = $this->validate_context($request->get_param('caps'));
242
-        $model = $relation->get_this_model();
243
-        $related_model = $relation->get_other_model();
244
-        if (! isset($primary_model_query_params[0])) {
245
-            $primary_model_query_params[0] = array();
246
-        }
247
-        //check if they can access the 1st model object
248
-        $primary_model_query_params = array(
249
-            0       => $primary_model_query_params[0],
250
-            'limit' => 1,
251
-        );
252
-        if ($model instanceof \EEM_Soft_Delete_Base) {
253
-            $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($primary_model_query_params);
254
-        }
255
-        $restricted_query_params = $primary_model_query_params;
256
-        $restricted_query_params['caps'] = $context;
257
-        $this->_set_debug_info('main model query params', $restricted_query_params);
258
-        $this->_set_debug_info('missing caps', Capabilities::get_missing_permissions_string($related_model, $context));
259
-        if (
260
-        ! (
261
-            Capabilities::current_user_has_partial_access_to($related_model, $context)
262
-            && $model->exists($restricted_query_params)
263
-        )
264
-        ) {
265
-            if ($relation instanceof \EE_Belongs_To_Relation) {
266
-                $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
267
-            } else {
268
-                $related_model_name_maybe_plural = \EEH_Inflector::pluralize_and_lower($related_model->get_this_model_name());
269
-            }
270
-            return new \WP_Error(
271
-                sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
272
-                sprintf(
273
-                    __('Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
274
-                        'event_espresso'),
275
-                    $related_model_name_maybe_plural,
276
-                    $relation->get_this_model()->get_this_model_name(),
277
-                    implode(
278
-                        ',',
279
-                        array_keys(
280
-                            Capabilities::get_missing_permissions($related_model, $context)
281
-                        )
282
-                    )
283
-                ),
284
-                array('status' => 403)
285
-            );
286
-        }
287
-        $query_params = $this->create_model_query_params($relation->get_other_model(), $request->get_params());
288
-        foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
289
-            $query_params[0][$relation->get_this_model()->get_this_model_name()
290
-                             . '.'
291
-                             . $where_condition_key] = $where_condition_value;
292
-        }
293
-        $query_params['default_where_conditions'] = 'none';
294
-        $query_params['caps'] = $context;
295
-        if (! $request->get_header('no_rest_headers')) {
296
-            $this->_set_headers_from_query_params($relation->get_other_model(), $query_params);
297
-        }
298
-        /** @type array $results */
299
-        $results = $relation->get_other_model()->get_all_wpdb_results($query_params);
300
-        $nice_results = array();
301
-        foreach ($results as $result) {
302
-            $nice_result = $this->create_entity_from_wpdb_result(
303
-                $relation->get_other_model(),
304
-                $result,
305
-                $request
306
-            );
307
-            if ($relation instanceof \EE_HABTM_Relation) {
308
-                //put the unusual stuff (properties from the HABTM relation) first, and make sure
309
-                //if there are conflicts we prefer the properties from the main model
310
-                $join_model_result = $this->create_entity_from_wpdb_result(
311
-                    $relation->get_join_model(),
312
-                    $result,
313
-                    $request
314
-                );
315
-                $joined_result = array_merge($nice_result, $join_model_result);
316
-                //but keep the meta stuff from the main model
317
-                if (isset($nice_result['meta'])) {
318
-                    $joined_result['meta'] = $nice_result['meta'];
319
-                }
320
-                $nice_result = $joined_result;
321
-            }
322
-            $nice_results[] = $nice_result;
323
-        }
324
-        if ($relation instanceof \EE_Belongs_To_Relation) {
325
-            return array_shift($nice_results);
326
-        } else {
327
-            return $nice_results;
328
-        }
329
-    }
330
-
331
-
332
-
333
-    /**
334
-     * Gets the collection for given relation object
335
-     * The same as Read::get_entities_from_model(), except if the relation
336
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
337
-     * the join-model-object into the results
338
-     *
339
-     * @param string                  $id the ID of the thing we are fetching related stuff from
340
-     * @param \EE_Model_Relation_Base $relation
341
-     * @param \WP_REST_Request        $request
342
-     * @return array|\WP_Error
343
-     * @throws \EE_Error
344
-     */
345
-    public function get_entities_from_relation($id, $relation, $request)
346
-    {
347
-        if (! $relation->get_this_model()->has_primary_key_field()) {
348
-            throw new \EE_Error(
349
-                sprintf(
350
-                    __('Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
351
-                        'event_espresso'),
352
-                    $relation->get_this_model()->get_this_model_name()
353
-                )
354
-            );
355
-        }
356
-        return $this->_get_entities_from_relation(
357
-            array(
358
-                array(
359
-                    $relation->get_this_model()->primary_key_name() => $id,
360
-                ),
361
-            ),
362
-            $relation,
363
-            $request
364
-        );
365
-    }
366
-
367
-
368
-
369
-    /**
370
-     * Sets the headers that are based on the model and query params,
371
-     * like the total records. This should only be called on the original request
372
-     * from the client, not on subsequent internal
373
-     *
374
-     * @param \EEM_Base $model
375
-     * @param array     $query_params
376
-     * @return void
377
-     */
378
-    protected function _set_headers_from_query_params($model, $query_params)
379
-    {
380
-        $this->_set_debug_info('model query params', $query_params);
381
-        $this->_set_debug_info('missing caps',
382
-            Capabilities::get_missing_permissions_string($model, $query_params['caps']));
383
-        //normally the limit to a 2-part array, where the 2nd item is the limit
384
-        if (! isset($query_params['limit'])) {
385
-            $query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
386
-        }
387
-        if (is_array($query_params['limit'])) {
388
-            $limit_parts = $query_params['limit'];
389
-        } else {
390
-            $limit_parts = explode(',', $query_params['limit']);
391
-            if (count($limit_parts) == 1) {
392
-                $limit_parts = array(0, $limit_parts[0]);
393
-            }
394
-        }
395
-        //remove the group by and having parts of the query, as those will
396
-        //make the sql query return an array of values, instead of just a single value
397
-        unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
398
-        $count = $model->count($query_params, null, true);
399
-        $pages = $count / $limit_parts[1];
400
-        $this->_set_response_header('Total', $count, false);
401
-        $this->_set_response_header('PageSize', $limit_parts[1], false);
402
-        $this->_set_response_header('TotalPages', ceil($pages), false);
403
-    }
404
-
405
-
406
-
407
-    /**
408
-     * Changes database results into REST API entities
409
-     *
410
-     * @param \EEM_Base        $model
411
-     * @param array            $db_row     like results from $wpdb->get_results()
412
-     * @param \WP_REST_Request $rest_request
413
-     * @param string           $deprecated no longer used
414
-     * @return array ready for being converted into json for sending to client
415
-     */
416
-    public function create_entity_from_wpdb_result($model, $db_row, $rest_request, $deprecated = null)
417
-    {
418
-        if (! $rest_request instanceof \WP_REST_Request) {
419
-            //ok so this was called in the old style, where the 3rd arg was
420
-            //$include, and the 4th arg was $context
421
-            //now setup the request just to avoid fatal errors, although we won't be able
422
-            //to truly make use of it because it's kinda devoid of info
423
-            $rest_request = new \WP_REST_Request();
424
-            $rest_request->set_param('include', $rest_request);
425
-            $rest_request->set_param('caps', $deprecated);
426
-        }
427
-        if ($rest_request->get_param('caps') == null) {
428
-            $rest_request->set_param('caps', \EEM_Base::caps_read);
429
-        }
430
-        $entity_array = $this->_create_bare_entity_from_wpdb_results($model, $db_row);
431
-        $entity_array = $this->_add_extra_fields($model, $db_row, $entity_array);
432
-        $entity_array['_links'] = $this->_get_entity_links($model, $db_row, $entity_array);
433
-        $entity_array['_calculated_fields'] = $this->_get_entity_calculations($model, $db_row, $rest_request);
434
-        $entity_array = $this->_include_requested_models($model, $rest_request, $entity_array, $db_row);
435
-        $entity_array = apply_filters(
436
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
437
-            $entity_array,
438
-            $model,
439
-            $rest_request->get_param('caps'),
440
-            $rest_request,
441
-            $this
442
-        );
443
-        $result_without_inaccessible_fields = Capabilities::filter_out_inaccessible_entity_fields(
444
-            $entity_array,
445
-            $model,
446
-            $rest_request->get_param('caps'),
447
-            $this->get_model_version_info(),
448
-            $model->get_index_primary_key_string(
449
-                $model->deduce_fields_n_values_from_cols_n_values($db_row)
450
-            )
451
-        );
452
-        $this->_set_debug_info(
453
-            'inaccessible fields',
454
-            array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
455
-        );
456
-        return apply_filters(
457
-            'FHEE__Read__create_entity_from_wpdb_results__entity_return',
458
-            $result_without_inaccessible_fields,
459
-            $model,
460
-            $rest_request->get_param('caps')
461
-        );
462
-    }
463
-
464
-
465
-
466
-    /**
467
-     * Creates a REST entity array (JSON object we're going to return in the response, but
468
-     * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
469
-     * from $wpdb->get_row( $sql, ARRAY_A)
470
-     *
471
-     * @param \EEM_Base $model
472
-     * @param array     $db_row
473
-     * @return array entity mostly ready for converting to JSON and sending in the response
474
-     */
475
-    protected function _create_bare_entity_from_wpdb_results(\EEM_Base $model, $db_row)
476
-    {
477
-        $result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
478
-        $result = array_intersect_key($result,
479
-            $this->get_model_version_info()->fields_on_model_in_this_version($model));
480
-        foreach ($result as $field_name => $raw_field_value) {
481
-            $field_obj = $model->field_settings_for($field_name);
482
-            $field_value = $field_obj->prepare_for_set_from_db($raw_field_value);
483
-            if ($this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_ignored())) {
484
-                unset($result[$field_name]);
485
-            } elseif (
486
-            $this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_rendered_format())
487
-            ) {
488
-                $result[$field_name] = array(
489
-                    'raw'      => $field_obj->prepare_for_get($field_value),
490
-                    'rendered' => $field_obj->prepare_for_pretty_echoing($field_value),
491
-                );
492
-            } elseif (
493
-            $this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_pretty_format())
494
-            ) {
495
-                $result[$field_name] = array(
496
-                    'raw'    => $field_obj->prepare_for_get($field_value),
497
-                    'pretty' => $field_obj->prepare_for_pretty_echoing($field_value),
498
-                );
499
-            } elseif ($field_obj instanceof \EE_Datetime_Field) {
500
-                if ($field_value instanceof \DateTime) {
501
-                    $timezone = $field_value->getTimezone();
502
-                    $field_value->setTimezone(new \DateTimeZone('UTC'));
503
-                    $result[$field_name . '_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
504
-                        $field_obj,
505
-                        $field_value,
506
-                        $this->get_model_version_info()->requested_version()
507
-                    );
508
-                    $field_value->setTimezone($timezone);
509
-                    $result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
510
-                        $field_obj,
511
-                        $field_value,
512
-                        $this->get_model_version_info()->requested_version()
513
-                    );
514
-                }
515
-            } else {
516
-                $result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
517
-                    $field_obj,
518
-                    $field_obj->prepare_for_get($field_value),
519
-                    $this->get_model_version_info()->requested_version()
520
-                );
521
-            }
522
-        }
523
-        return $result;
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * Adds a few extra fields to the entity response
530
-     *
531
-     * @param \EEM_Base $model
532
-     * @param array     $db_row
533
-     * @param array     $entity_array
534
-     * @return array modified entity
535
-     */
536
-    protected function _add_extra_fields(\EEM_Base $model, $db_row, $entity_array)
537
-    {
538
-        if ($model instanceof \EEM_CPT_Base) {
539
-            $entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
540
-        }
541
-        return $entity_array;
542
-    }
543
-
544
-
545
-
546
-    /**
547
-     * Gets links we want to add to the response
548
-     *
549
-     * @global \WP_REST_Server $wp_rest_server
550
-     * @param \EEM_Base        $model
551
-     * @param array            $db_row
552
-     * @param array            $entity_array
553
-     * @return array the _links item in the entity
554
-     */
555
-    protected function _get_entity_links($model, $db_row, $entity_array)
556
-    {
557
-        //add basic links
558
-        $links = array();
559
-        if ($model->has_primary_key_field()) {
560
-            $links['self'] = array(
561
-                array(
562
-                    'href' => $this->get_versioned_link_to(
563
-                        \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
564
-                        . '/'
565
-                        . $entity_array[$model->primary_key_name()]
566
-                    ),
567
-                ),
568
-            );
569
-        }
570
-        $links['collection'] = array(
571
-            array(
572
-                'href' => $this->get_versioned_link_to(
573
-                    \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
574
-                ),
575
-            ),
576
-        );
577
-        //add links to related models
578
-        if ($model->has_primary_key_field()) {
579
-            foreach ($this->get_model_version_info()->relation_settings($model) as $relation_name => $relation_obj) {
580
-                $related_model_part = Read::get_related_entity_name($relation_name, $relation_obj);
581
-                $links[\EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
582
-                    array(
583
-                        'href'   => $this->get_versioned_link_to(
584
-                            \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
585
-                            . '/'
586
-                            . $entity_array[$model->primary_key_name()]
587
-                            . '/'
588
-                            . $related_model_part
589
-                        ),
590
-                        'single' => $relation_obj instanceof \EE_Belongs_To_Relation ? true : false,
591
-                    ),
592
-                );
593
-            }
594
-        }
595
-        return $links;
596
-    }
597
-
598
-
599
-
600
-    /**
601
-     * Adds the included models indicated in the request to the entity provided
602
-     *
603
-     * @param \EEM_Base        $model
604
-     * @param \WP_REST_Request $rest_request
605
-     * @param array            $entity_array
606
-     * @param array            $db_row
607
-     * @return array the modified entity
608
-     */
609
-    protected function _include_requested_models(
610
-        \EEM_Base $model,
611
-        \WP_REST_Request $rest_request,
612
-        $entity_array,
613
-        $db_row = array()
614
-    ) {
615
-        //if $db_row not included, hope the entity array has what we need
616
-        if (! $db_row) {
617
-            $db_row = $entity_array;
618
-        }
619
-        $includes_for_this_model = $this->explode_and_get_items_prefixed_with($rest_request->get_param('include'), '');
620
-        $includes_for_this_model = $this->_remove_model_names_from_array($includes_for_this_model);
621
-        //if they passed in * or didn't specify any includes, return everything
622
-        if (! in_array('*', $includes_for_this_model)
623
-            && ! empty($includes_for_this_model)
624
-        ) {
625
-            if ($model->has_primary_key_field()) {
626
-                //always include the primary key. ya just gotta know that at least
627
-                $includes_for_this_model[] = $model->primary_key_name();
628
-            }
629
-            if ($this->explode_and_get_items_prefixed_with($rest_request->get_param('calculate'), '')) {
630
-                $includes_for_this_model[] = '_calculated_fields';
631
-            }
632
-            $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
633
-        }
634
-        $relation_settings = $this->get_model_version_info()->relation_settings($model);
635
-        foreach ($relation_settings as $relation_name => $relation_obj) {
636
-            $related_fields_to_include = $this->explode_and_get_items_prefixed_with(
637
-                $rest_request->get_param('include'),
638
-                $relation_name
639
-            );
640
-            $related_fields_to_calculate = $this->explode_and_get_items_prefixed_with(
641
-                $rest_request->get_param('calculate'),
642
-                $relation_name
643
-            );
644
-            //did they specify they wanted to include a related model, or
645
-            //specific fields from a related model?
646
-            //or did they specify to calculate a field from a related model?
647
-            if ($related_fields_to_include || $related_fields_to_calculate) {
648
-                //if so, we should include at least some part of the related model
649
-                $pretend_related_request = new \WP_REST_Request();
650
-                $pretend_related_request->set_query_params(
651
-                    array(
652
-                        'caps'      => $rest_request->get_param('caps'),
653
-                        'include'   => $related_fields_to_include,
654
-                        'calculate' => $related_fields_to_calculate,
655
-                    )
656
-                );
657
-                $pretend_related_request->add_header('no_rest_headers', true);
658
-                $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
659
-                    $model->get_index_primary_key_string(
660
-                        $model->deduce_fields_n_values_from_cols_n_values($db_row)
661
-                    )
662
-                );
663
-                $related_results = $this->_get_entities_from_relation(
664
-                    $primary_model_query_params,
665
-                    $relation_obj,
666
-                    $pretend_related_request
667
-                );
668
-                $entity_array[Read::get_related_entity_name($relation_name, $relation_obj)] = $related_results
669
-                                                                                              instanceof
670
-                                                                                              \WP_Error
671
-                    ? null
672
-                    : $related_results;
673
-            }
674
-        }
675
-        return $entity_array;
676
-    }
677
-
678
-
679
-
680
-    /**
681
-     * Returns a new array with all the names of models removed. Eg
682
-     * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
683
-     *
684
-     * @param array $arr
685
-     * @return array
686
-     */
687
-    private function _remove_model_names_from_array($arr)
688
-    {
689
-        return array_diff($arr, array_keys(\EE_Registry::instance()->non_abstract_db_models));
690
-    }
691
-
692
-
693
-
694
-    /**
695
-     * Gets the calculated fields for the response
696
-     *
697
-     * @param \EEM_Base        $model
698
-     * @param array            $wpdb_row
699
-     * @param \WP_REST_Request $rest_request
700
-     * @return \stdClass the _calculations item in the entity
701
-     */
702
-    protected function _get_entity_calculations($model, $wpdb_row, $rest_request)
703
-    {
704
-        $calculated_fields = $this->explode_and_get_items_prefixed_with(
705
-            $rest_request->get_param('calculate'),
706
-            ''
707
-        );
708
-        //note: setting calculate=* doesn't do anything
709
-        $calculated_fields_to_return = new \stdClass();
710
-        foreach ($calculated_fields as $field_to_calculate) {
711
-            try {
712
-                $calculated_fields_to_return->$field_to_calculate = Model_Data_Translator::prepare_field_value_for_json(
713
-                    null,
714
-                    $this->_fields_calculator->retrieve_calculated_field_value(
715
-                        $model,
716
-                        $field_to_calculate,
717
-                        $wpdb_row,
718
-                        $rest_request,
719
-                        $this
720
-                    ),
721
-                    $this->get_model_version_info()->requested_version()
722
-                );
723
-            } catch (Rest_Exception $e) {
724
-                //if we don't have permission to read it, just leave it out. but let devs know about the problem
725
-                $this->_set_response_header(
726
-                    'Notices-Field-Calculation-Errors['
727
-                    . $e->get_string_code()
728
-                    . ']['
729
-                    . $model->get_this_model_name()
730
-                    . ']['
731
-                    . $field_to_calculate
732
-                    . ']',
733
-                    $e->getMessage(),
734
-                    true
735
-                );
736
-            }
737
-        }
738
-        return $calculated_fields_to_return;
739
-    }
740
-
741
-
742
-
743
-    /**
744
-     * Gets the full URL to the resource, taking the requested version into account
745
-     *
746
-     * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
747
-     * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
748
-     */
749
-    public function get_versioned_link_to($link_part_after_version_and_slash)
750
-    {
751
-        return rest_url(
752
-            \EED_Core_Rest_Api::ee_api_namespace
753
-            . $this->get_model_version_info()->requested_version()
754
-            . '/'
755
-            . $link_part_after_version_and_slash
756
-        );
757
-    }
758
-
759
-
760
-
761
-    /**
762
-     * Gets the correct lowercase name for the relation in the API according
763
-     * to the relation's type
764
-     *
765
-     * @param string                  $relation_name
766
-     * @param \EE_Model_Relation_Base $relation_obj
767
-     * @return string
768
-     */
769
-    public static function get_related_entity_name($relation_name, $relation_obj)
770
-    {
771
-        if ($relation_obj instanceof \EE_Belongs_To_Relation) {
772
-            return strtolower($relation_name);
773
-        } else {
774
-            return \EEH_Inflector::pluralize_and_lower($relation_name);
775
-        }
776
-    }
777
-
778
-
779
-
780
-    /**
781
-     * Gets the one model object with the specified id for the specified model
782
-     *
783
-     * @param \EEM_Base        $model
784
-     * @param \WP_REST_Request $request
785
-     * @return array|\WP_Error
786
-     */
787
-    public function get_entity_from_model($model, $request)
788
-    {
789
-        $query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
790
-        if ($model instanceof \EEM_Soft_Delete_Base) {
791
-            $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
792
-        }
793
-        $restricted_query_params = $query_params;
794
-        $restricted_query_params['caps'] = $this->validate_context($request->get_param('caps'));
795
-        $this->_set_debug_info('model query params', $restricted_query_params);
796
-        $model_rows = $model->get_all_wpdb_results($restricted_query_params);
797
-        if (! empty ($model_rows)) {
798
-            return $this->create_entity_from_wpdb_result(
799
-                $model,
800
-                array_shift($model_rows),
801
-                $request);
802
-        } else {
803
-            //ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
804
-            $lowercase_model_name = strtolower($model->get_this_model_name());
805
-            $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
806
-            if (! empty($model_rows_found_sans_restrictions)) {
807
-                //you got shafted- it existed but we didn't want to tell you!
808
-                return new \WP_Error(
809
-                    'rest_user_cannot_read',
810
-                    sprintf(
811
-                        __('Sorry, you cannot read this %1$s. Missing permissions are: %2$s', 'event_espresso'),
812
-                        strtolower($model->get_this_model_name()),
813
-                        Capabilities::get_missing_permissions_string(
814
-                            $model,
815
-                            $this->validate_context($request->get_param('caps')))
816
-                    ),
817
-                    array('status' => 403)
818
-                );
819
-            } else {
820
-                //it's not you. It just doesn't exist
821
-                return new \WP_Error(
822
-                    sprintf('rest_%s_invalid_id', $lowercase_model_name),
823
-                    sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
824
-                    array('status' => 404)
825
-                );
826
-            }
827
-        }
828
-    }
829
-
830
-
831
-
832
-    /**
833
-     * If a context is provided which isn't valid, maybe it was added in a future
834
-     * version so just treat it as a default read
835
-     *
836
-     * @param string $context
837
-     * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
838
-     */
839
-    public function validate_context($context)
840
-    {
841
-        if (! $context) {
842
-            $context = \EEM_Base::caps_read;
843
-        }
844
-        $valid_contexts = \EEM_Base::valid_cap_contexts();
845
-        if (in_array($context, $valid_contexts)) {
846
-            return $context;
847
-        } else {
848
-            return \EEM_Base::caps_read;
849
-        }
850
-    }
851
-
852
-
853
-
854
-    /**
855
-     * Verifies the passed in value is an allowable default where conditions value.
856
-     *
857
-     * @param $default_query_params
858
-     * @return string
859
-     */
860
-    public function validate_default_query_params($default_query_params)
861
-    {
862
-        $valid_default_where_conditions_for_api_calls = array(
863
-            \EEM_Base::default_where_conditions_all,
864
-            \EEM_Base::default_where_conditions_minimum_all,
865
-            \EEM_Base::default_where_conditions_minimum_others,
866
-        );
867
-        if (! $default_query_params) {
868
-            $default_query_params = \EEM_Base::default_where_conditions_all;
869
-        }
870
-        if (
871
-        in_array(
872
-            $default_query_params,
873
-            $valid_default_where_conditions_for_api_calls,
874
-            true
875
-        )
876
-        ) {
877
-            return $default_query_params;
878
-        } else {
879
-            return \EEM_Base::default_where_conditions_all;
880
-        }
881
-    }
882
-
883
-
884
-
885
-    /**
886
-     * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
887
-     * Note: right now the query parameter keys for fields (and related fields)
888
-     * can be left as-is, but it's quite possible this will change someday.
889
-     * Also, this method's contents might be candidate for moving to Model_Data_Translator
890
-     *
891
-     * @param \EEM_Base $model
892
-     * @param array     $query_parameters from $_GET parameter @see Read:handle_request_get_all
893
-     * @return array like what EEM_Base::get_all() expects or FALSE to indicate
894
-     *                                    that absolutely no results should be returned
895
-     * @throws \EE_Error
896
-     */
897
-    public function create_model_query_params($model, $query_parameters)
898
-    {
899
-        $model_query_params = array();
900
-        if (isset($query_parameters['where'])) {
901
-            $model_query_params[0] = Model_Data_Translator::prepare_conditions_query_params_for_models(
902
-                $query_parameters['where'],
903
-                $model,
904
-                $this->get_model_version_info()->requested_version()
905
-            );
906
-        }
907
-        if (isset($query_parameters['order_by'])) {
908
-            $order_by = $query_parameters['order_by'];
909
-        } elseif (isset($query_parameters['orderby'])) {
910
-            $order_by = $query_parameters['orderby'];
911
-        } else {
912
-            $order_by = null;
913
-        }
914
-        if ($order_by !== null) {
915
-            if (is_array($order_by)) {
916
-                $order_by = Model_Data_Translator::prepare_field_names_in_array_keys_from_json($order_by);
917
-            } else {
918
-                //it's a single item
919
-                $order_by = Model_Data_Translator::prepare_field_name_from_json($order_by);
920
-            }
921
-            $model_query_params['order_by'] = $order_by;
922
-        }
923
-        if (isset($query_parameters['group_by'])) {
924
-            $group_by = $query_parameters['group_by'];
925
-        } elseif (isset($query_parameters['groupby'])) {
926
-            $group_by = $query_parameters['groupby'];
927
-        } else {
928
-            $group_by = array_keys($model->get_combined_primary_key_fields());
929
-        }
930
-        //make sure they're all real names
931
-        if (is_array($group_by)) {
932
-            $group_by = Model_Data_Translator::prepare_field_names_from_json($group_by);
933
-        }
934
-        if ($group_by !== null) {
935
-            $model_query_params['group_by'] = $group_by;
936
-        }
937
-        if (isset($query_parameters['having'])) {
938
-            $model_query_params['having'] = Model_Data_Translator::prepare_conditions_query_params_for_models(
939
-                $query_parameters['having'],
940
-                $model,
941
-                $this->get_model_version_info()->requested_version()
942
-            );
943
-        }
944
-        if (isset($query_parameters['order'])) {
945
-            $model_query_params['order'] = $query_parameters['order'];
946
-        }
947
-        if (isset($query_parameters['mine'])) {
948
-            $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
949
-        }
950
-        if (isset($query_parameters['limit'])) {
951
-            //limit should be either a string like '23' or '23,43', or an array with two items in it
952
-            if (! is_array($query_parameters['limit'])) {
953
-                $limit_array = explode(',', (string)$query_parameters['limit']);
954
-            } else {
955
-                $limit_array = $query_parameters['limit'];
956
-            }
957
-            $sanitized_limit = array();
958
-            foreach ($limit_array as $key => $limit_part) {
959
-                if ($this->_debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
960
-                    throw new \EE_Error(
961
-                        sprintf(
962
-                            __('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.',
963
-                                'event_espresso'),
964
-                            wp_json_encode($query_parameters['limit'])
965
-                        )
966
-                    );
967
-                }
968
-                $sanitized_limit[] = (int)$limit_part;
969
-            }
970
-            $model_query_params['limit'] = implode(',', $sanitized_limit);
971
-        } else {
972
-            $model_query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
973
-        }
974
-        if (isset($query_parameters['caps'])) {
975
-            $model_query_params['caps'] = $this->validate_context($query_parameters['caps']);
976
-        } else {
977
-            $model_query_params['caps'] = \EEM_Base::caps_read;
978
-        }
979
-        if (isset($query_parameters['default_where_conditions'])) {
980
-            $model_query_params['default_where_conditions'] = $this->validate_default_query_params($query_parameters['default_where_conditions']);
981
-        }
982
-        return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
983
-    }
984
-
985
-
986
-
987
-    /**
988
-     * Changes the REST-style query params for use in the models
989
-     *
990
-     * @deprecated
991
-     * @param \EEM_Base $model
992
-     * @param array     $query_params sub-array from @see EEM_Base::get_all()
993
-     * @return array
994
-     */
995
-    public function prepare_rest_query_params_key_for_models($model, $query_params)
996
-    {
997
-        $model_ready_query_params = array();
998
-        foreach ($query_params as $key => $value) {
999
-            if (is_array($value)) {
1000
-                $model_ready_query_params[$key] = $this->prepare_rest_query_params_key_for_models($model, $value);
1001
-            } else {
1002
-                $model_ready_query_params[$key] = $value;
1003
-            }
1004
-        }
1005
-        return $model_ready_query_params;
1006
-    }
1007
-
1008
-
1009
-
1010
-    /**
1011
-     * @deprecated
1012
-     * @param $model
1013
-     * @param $query_params
1014
-     * @return array
1015
-     */
1016
-    public function prepare_rest_query_params_values_for_models($model, $query_params)
1017
-    {
1018
-        $model_ready_query_params = array();
1019
-        foreach ($query_params as $key => $value) {
1020
-            if (is_array($value)) {
1021
-                $model_ready_query_params[$key] = $this->prepare_rest_query_params_values_for_models($model, $value);
1022
-            } else {
1023
-                $model_ready_query_params[$key] = $value;
1024
-            }
1025
-        }
1026
-        return $model_ready_query_params;
1027
-    }
1028
-
1029
-
1030
-
1031
-    /**
1032
-     * Explodes the string on commas, and only returns items with $prefix followed by a period.
1033
-     * If no prefix is specified, returns items with no period.
1034
-     *
1035
-     * @param string|array $string_to_explode eg "jibba,jabba, blah, blaabla" or array('jibba', 'jabba' )
1036
-     * @param string       $prefix            "Event" or "foobar"
1037
-     * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1038
-     *                                        we only return strings starting with that and a period; if no prefix was
1039
-     *                                        specified we return all items containing NO periods
1040
-     */
1041
-    public function explode_and_get_items_prefixed_with($string_to_explode, $prefix)
1042
-    {
1043
-        if (is_string($string_to_explode)) {
1044
-            $exploded_contents = explode(',', $string_to_explode);
1045
-        } else if (is_array($string_to_explode)) {
1046
-            $exploded_contents = $string_to_explode;
1047
-        } else {
1048
-            $exploded_contents = array();
1049
-        }
1050
-        //if the string was empty, we want an empty array
1051
-        $exploded_contents = array_filter($exploded_contents);
1052
-        $contents_with_prefix = array();
1053
-        foreach ($exploded_contents as $item) {
1054
-            $item = trim($item);
1055
-            //if no prefix was provided, so we look for items with no "." in them
1056
-            if (! $prefix) {
1057
-                //does this item have a period?
1058
-                if (strpos($item, '.') === false) {
1059
-                    //if not, then its what we're looking for
1060
-                    $contents_with_prefix[] = $item;
1061
-                }
1062
-            } else if (strpos($item, $prefix . '.') === 0) {
1063
-                //this item has the prefix and a period, grab it
1064
-                $contents_with_prefix[] = substr(
1065
-                    $item,
1066
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1067
-                );
1068
-            } else if ($item === $prefix) {
1069
-                //this item is JUST the prefix
1070
-                //so let's grab everything after, which is a blank string
1071
-                $contents_with_prefix[] = '';
1072
-            }
1073
-        }
1074
-        return $contents_with_prefix;
1075
-    }
1076
-
1077
-
1078
-
1079
-    /**
1080
-     * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1081
-     * Deprecated because its return values were really quite confusing- sometimes it returned
1082
-     * an empty array (when the include string was blank or '*') or sometimes it returned
1083
-     * array('*') (when you provided a model and a model of that kind was found).
1084
-     * Parses the $include_string so we fetch all the field names relating to THIS model
1085
-     * (ie have NO period in them), or for the provided model (ie start with the model
1086
-     * name and then a period).
1087
-     * @param string $include_string @see Read:handle_request_get_all
1088
-     * @param string $model_name
1089
-     * @return array of fields for this model. If $model_name is provided, then
1090
-     *                               the fields for that model, with the model's name removed from each.
1091
-     *                               If $include_string was blank or '*' returns an empty array
1092
-     */
1093
-    public function extract_includes_for_this_model($include_string, $model_name = null)
1094
-    {
1095
-        if (is_array($include_string)) {
1096
-            $include_string = implode(',', $include_string);
1097
-        }
1098
-        if ($include_string === '*' || $include_string === '') {
1099
-            return array();
1100
-        }
1101
-        $includes = explode(',', $include_string);
1102
-        $extracted_fields_to_include = array();
1103
-        if ($model_name) {
1104
-            foreach ($includes as $field_to_include) {
1105
-                $field_to_include = trim($field_to_include);
1106
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1107
-                    //found the model name at the exact start
1108
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1109
-                    $extracted_fields_to_include[] = $field_sans_model_name;
1110
-                } elseif ($field_to_include == $model_name) {
1111
-                    $extracted_fields_to_include[] = '*';
1112
-                }
1113
-            }
1114
-        } else {
1115
-            //look for ones with no period
1116
-            foreach ($includes as $field_to_include) {
1117
-                $field_to_include = trim($field_to_include);
1118
-                if (
1119
-                    strpos($field_to_include, '.') === false
1120
-                    && ! $this->get_model_version_info()->is_model_name_in_this_version($field_to_include)
1121
-                ) {
1122
-                    $extracted_fields_to_include[] = $field_to_include;
1123
-                }
1124
-            }
1125
-        }
1126
-        return $extracted_fields_to_include;
1127
-    }
28
+	/**
29
+	 * @var Calculated_Model_Fields
30
+	 */
31
+	protected $_fields_calculator;
32
+
33
+
34
+
35
+	/**
36
+	 * Read constructor.
37
+	 */
38
+	public function __construct()
39
+	{
40
+		parent::__construct();
41
+		$this->_fields_calculator = new Calculated_Model_Fields();
42
+	}
43
+
44
+
45
+
46
+	/**
47
+	 * Handles requests to get all (or a filtered subset) of entities for a particular model
48
+	 *
49
+	 * @param \WP_REST_Request $request
50
+	 * @return \WP_REST_Response|\WP_Error
51
+	 */
52
+	public static function handle_request_get_all(\WP_REST_Request $request)
53
+	{
54
+		$controller = new Read();
55
+		try {
56
+			$matches = $controller->parse_route(
57
+				$request->get_route(),
58
+				'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)~',
59
+				array('version', 'model')
60
+			);
61
+			$controller->set_requested_version($matches['version']);
62
+			$model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
63
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
64
+				return $controller->send_response(
65
+					new \WP_Error(
66
+						'endpoint_parsing_error',
67
+						sprintf(
68
+							__('There is no model for endpoint %s. Please contact event espresso support',
69
+								'event_espresso'),
70
+							$model_name_singular
71
+						)
72
+					)
73
+				);
74
+			}
75
+			return $controller->send_response(
76
+				$controller->get_entities_from_model(
77
+					$controller->get_model_version_info()->load_model($model_name_singular),
78
+					$request
79
+				)
80
+			);
81
+		} catch (\Exception $e) {
82
+			return $controller->send_response($e);
83
+		}
84
+	}
85
+
86
+
87
+
88
+	/**
89
+	 * Gets a single entity related to the model indicated in the path and its id
90
+	 *
91
+	 * @param \WP_REST_Request $request
92
+	 * @return \WP_REST_Response|\WP_Error
93
+	 */
94
+	public static function handle_request_get_one(\WP_REST_Request $request)
95
+	{
96
+		$controller = new Read();
97
+		try {
98
+			$matches = $controller->parse_route(
99
+				$request->get_route(),
100
+				'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)~',
101
+				array('version', 'model', 'id'));
102
+			$controller->set_requested_version($matches['version']);
103
+			$model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
104
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
105
+				return $controller->send_response(
106
+					new \WP_Error(
107
+						'endpoint_parsing_error',
108
+						sprintf(
109
+							__('There is no model for endpoint %s. Please contact event espresso support',
110
+								'event_espresso'),
111
+							$model_name_singular
112
+						)
113
+					)
114
+				);
115
+			}
116
+			return $controller->send_response(
117
+				$controller->get_entity_from_model(
118
+					$controller->get_model_version_info()->load_model($model_name_singular),
119
+					$request
120
+				)
121
+			);
122
+		} catch (\Exception $e) {
123
+			return $controller->send_response($e);
124
+		}
125
+	}
126
+
127
+
128
+
129
+	/**
130
+	 * Gets all the related entities (or if its a belongs-to relation just the one)
131
+	 * to the item with the given id
132
+	 *
133
+	 * @param \WP_REST_Request $request
134
+	 * @return \WP_REST_Response|\WP_Error
135
+	 */
136
+	public static function handle_request_get_related(\WP_REST_Request $request)
137
+	{
138
+		$controller = new Read();
139
+		try {
140
+			$matches = $controller->parse_route(
141
+				$request->get_route(),
142
+				'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)/(.*)~',
143
+				array('version', 'model', 'id', 'related_model')
144
+			);
145
+			$controller->set_requested_version($matches['version']);
146
+			$main_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
147
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
148
+				return $controller->send_response(
149
+					new \WP_Error(
150
+						'endpoint_parsing_error',
151
+						sprintf(
152
+							__('There is no model for endpoint %s. Please contact event espresso support',
153
+								'event_espresso'),
154
+							$main_model_name_singular
155
+						)
156
+					)
157
+				);
158
+			}
159
+			$main_model = $controller->get_model_version_info()->load_model($main_model_name_singular);
160
+			//assume the related model name is plural and try to find the model's name
161
+			$related_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['related_model']);
162
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
163
+				//so the word didn't singularize well. Maybe that's just because it's a singular word?
164
+				$related_model_name_singular = \EEH_Inflector::humanize($matches['related_model']);
165
+			}
166
+			if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
167
+				return $controller->send_response(
168
+					new \WP_Error(
169
+						'endpoint_parsing_error',
170
+						sprintf(
171
+							__('There is no model for endpoint %s. Please contact event espresso support',
172
+								'event_espresso'),
173
+							$related_model_name_singular
174
+						)
175
+					)
176
+				);
177
+			}
178
+			return $controller->send_response(
179
+				$controller->get_entities_from_relation(
180
+					$request->get_param('id'),
181
+					$main_model->related_settings_for($related_model_name_singular),
182
+					$request
183
+				)
184
+			);
185
+		} catch (\Exception $e) {
186
+			return $controller->send_response($e);
187
+		}
188
+	}
189
+
190
+
191
+
192
+	/**
193
+	 * Gets a collection for the given model and filters
194
+	 *
195
+	 * @param \EEM_Base        $model
196
+	 * @param \WP_REST_Request $request
197
+	 * @return array|\WP_Error
198
+	 */
199
+	public function get_entities_from_model($model, $request)
200
+	{
201
+		$query_params = $this->create_model_query_params($model, $request->get_params());
202
+		if (! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
203
+			$model_name_plural = \EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
204
+			return new \WP_Error(
205
+				sprintf('rest_%s_cannot_list', $model_name_plural),
206
+				sprintf(
207
+					__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
208
+					$model_name_plural,
209
+					Capabilities::get_missing_permissions_string($model, $query_params['caps'])
210
+				),
211
+				array('status' => 403)
212
+			);
213
+		}
214
+		if (! $request->get_header('no_rest_headers')) {
215
+			$this->_set_headers_from_query_params($model, $query_params);
216
+		}
217
+		/** @type array $results */
218
+		$results = $model->get_all_wpdb_results($query_params);
219
+		$nice_results = array();
220
+		foreach ($results as $result) {
221
+			$nice_results[] = $this->create_entity_from_wpdb_result(
222
+				$model,
223
+				$result,
224
+				$request
225
+			);
226
+		}
227
+		return $nice_results;
228
+	}
229
+
230
+
231
+
232
+	/**
233
+	 * @param array                   $primary_model_query_params query params for finding the item from which
234
+	 *                                                            relations will be based
235
+	 * @param \EE_Model_Relation_Base $relation
236
+	 * @param \WP_REST_Request        $request
237
+	 * @return \WP_Error|array
238
+	 */
239
+	protected function _get_entities_from_relation($primary_model_query_params, $relation, $request)
240
+	{
241
+		$context = $this->validate_context($request->get_param('caps'));
242
+		$model = $relation->get_this_model();
243
+		$related_model = $relation->get_other_model();
244
+		if (! isset($primary_model_query_params[0])) {
245
+			$primary_model_query_params[0] = array();
246
+		}
247
+		//check if they can access the 1st model object
248
+		$primary_model_query_params = array(
249
+			0       => $primary_model_query_params[0],
250
+			'limit' => 1,
251
+		);
252
+		if ($model instanceof \EEM_Soft_Delete_Base) {
253
+			$primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($primary_model_query_params);
254
+		}
255
+		$restricted_query_params = $primary_model_query_params;
256
+		$restricted_query_params['caps'] = $context;
257
+		$this->_set_debug_info('main model query params', $restricted_query_params);
258
+		$this->_set_debug_info('missing caps', Capabilities::get_missing_permissions_string($related_model, $context));
259
+		if (
260
+		! (
261
+			Capabilities::current_user_has_partial_access_to($related_model, $context)
262
+			&& $model->exists($restricted_query_params)
263
+		)
264
+		) {
265
+			if ($relation instanceof \EE_Belongs_To_Relation) {
266
+				$related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
267
+			} else {
268
+				$related_model_name_maybe_plural = \EEH_Inflector::pluralize_and_lower($related_model->get_this_model_name());
269
+			}
270
+			return new \WP_Error(
271
+				sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
272
+				sprintf(
273
+					__('Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
274
+						'event_espresso'),
275
+					$related_model_name_maybe_plural,
276
+					$relation->get_this_model()->get_this_model_name(),
277
+					implode(
278
+						',',
279
+						array_keys(
280
+							Capabilities::get_missing_permissions($related_model, $context)
281
+						)
282
+					)
283
+				),
284
+				array('status' => 403)
285
+			);
286
+		}
287
+		$query_params = $this->create_model_query_params($relation->get_other_model(), $request->get_params());
288
+		foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
289
+			$query_params[0][$relation->get_this_model()->get_this_model_name()
290
+							 . '.'
291
+							 . $where_condition_key] = $where_condition_value;
292
+		}
293
+		$query_params['default_where_conditions'] = 'none';
294
+		$query_params['caps'] = $context;
295
+		if (! $request->get_header('no_rest_headers')) {
296
+			$this->_set_headers_from_query_params($relation->get_other_model(), $query_params);
297
+		}
298
+		/** @type array $results */
299
+		$results = $relation->get_other_model()->get_all_wpdb_results($query_params);
300
+		$nice_results = array();
301
+		foreach ($results as $result) {
302
+			$nice_result = $this->create_entity_from_wpdb_result(
303
+				$relation->get_other_model(),
304
+				$result,
305
+				$request
306
+			);
307
+			if ($relation instanceof \EE_HABTM_Relation) {
308
+				//put the unusual stuff (properties from the HABTM relation) first, and make sure
309
+				//if there are conflicts we prefer the properties from the main model
310
+				$join_model_result = $this->create_entity_from_wpdb_result(
311
+					$relation->get_join_model(),
312
+					$result,
313
+					$request
314
+				);
315
+				$joined_result = array_merge($nice_result, $join_model_result);
316
+				//but keep the meta stuff from the main model
317
+				if (isset($nice_result['meta'])) {
318
+					$joined_result['meta'] = $nice_result['meta'];
319
+				}
320
+				$nice_result = $joined_result;
321
+			}
322
+			$nice_results[] = $nice_result;
323
+		}
324
+		if ($relation instanceof \EE_Belongs_To_Relation) {
325
+			return array_shift($nice_results);
326
+		} else {
327
+			return $nice_results;
328
+		}
329
+	}
330
+
331
+
332
+
333
+	/**
334
+	 * Gets the collection for given relation object
335
+	 * The same as Read::get_entities_from_model(), except if the relation
336
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
337
+	 * the join-model-object into the results
338
+	 *
339
+	 * @param string                  $id the ID of the thing we are fetching related stuff from
340
+	 * @param \EE_Model_Relation_Base $relation
341
+	 * @param \WP_REST_Request        $request
342
+	 * @return array|\WP_Error
343
+	 * @throws \EE_Error
344
+	 */
345
+	public function get_entities_from_relation($id, $relation, $request)
346
+	{
347
+		if (! $relation->get_this_model()->has_primary_key_field()) {
348
+			throw new \EE_Error(
349
+				sprintf(
350
+					__('Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
351
+						'event_espresso'),
352
+					$relation->get_this_model()->get_this_model_name()
353
+				)
354
+			);
355
+		}
356
+		return $this->_get_entities_from_relation(
357
+			array(
358
+				array(
359
+					$relation->get_this_model()->primary_key_name() => $id,
360
+				),
361
+			),
362
+			$relation,
363
+			$request
364
+		);
365
+	}
366
+
367
+
368
+
369
+	/**
370
+	 * Sets the headers that are based on the model and query params,
371
+	 * like the total records. This should only be called on the original request
372
+	 * from the client, not on subsequent internal
373
+	 *
374
+	 * @param \EEM_Base $model
375
+	 * @param array     $query_params
376
+	 * @return void
377
+	 */
378
+	protected function _set_headers_from_query_params($model, $query_params)
379
+	{
380
+		$this->_set_debug_info('model query params', $query_params);
381
+		$this->_set_debug_info('missing caps',
382
+			Capabilities::get_missing_permissions_string($model, $query_params['caps']));
383
+		//normally the limit to a 2-part array, where the 2nd item is the limit
384
+		if (! isset($query_params['limit'])) {
385
+			$query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
386
+		}
387
+		if (is_array($query_params['limit'])) {
388
+			$limit_parts = $query_params['limit'];
389
+		} else {
390
+			$limit_parts = explode(',', $query_params['limit']);
391
+			if (count($limit_parts) == 1) {
392
+				$limit_parts = array(0, $limit_parts[0]);
393
+			}
394
+		}
395
+		//remove the group by and having parts of the query, as those will
396
+		//make the sql query return an array of values, instead of just a single value
397
+		unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
398
+		$count = $model->count($query_params, null, true);
399
+		$pages = $count / $limit_parts[1];
400
+		$this->_set_response_header('Total', $count, false);
401
+		$this->_set_response_header('PageSize', $limit_parts[1], false);
402
+		$this->_set_response_header('TotalPages', ceil($pages), false);
403
+	}
404
+
405
+
406
+
407
+	/**
408
+	 * Changes database results into REST API entities
409
+	 *
410
+	 * @param \EEM_Base        $model
411
+	 * @param array            $db_row     like results from $wpdb->get_results()
412
+	 * @param \WP_REST_Request $rest_request
413
+	 * @param string           $deprecated no longer used
414
+	 * @return array ready for being converted into json for sending to client
415
+	 */
416
+	public function create_entity_from_wpdb_result($model, $db_row, $rest_request, $deprecated = null)
417
+	{
418
+		if (! $rest_request instanceof \WP_REST_Request) {
419
+			//ok so this was called in the old style, where the 3rd arg was
420
+			//$include, and the 4th arg was $context
421
+			//now setup the request just to avoid fatal errors, although we won't be able
422
+			//to truly make use of it because it's kinda devoid of info
423
+			$rest_request = new \WP_REST_Request();
424
+			$rest_request->set_param('include', $rest_request);
425
+			$rest_request->set_param('caps', $deprecated);
426
+		}
427
+		if ($rest_request->get_param('caps') == null) {
428
+			$rest_request->set_param('caps', \EEM_Base::caps_read);
429
+		}
430
+		$entity_array = $this->_create_bare_entity_from_wpdb_results($model, $db_row);
431
+		$entity_array = $this->_add_extra_fields($model, $db_row, $entity_array);
432
+		$entity_array['_links'] = $this->_get_entity_links($model, $db_row, $entity_array);
433
+		$entity_array['_calculated_fields'] = $this->_get_entity_calculations($model, $db_row, $rest_request);
434
+		$entity_array = $this->_include_requested_models($model, $rest_request, $entity_array, $db_row);
435
+		$entity_array = apply_filters(
436
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
437
+			$entity_array,
438
+			$model,
439
+			$rest_request->get_param('caps'),
440
+			$rest_request,
441
+			$this
442
+		);
443
+		$result_without_inaccessible_fields = Capabilities::filter_out_inaccessible_entity_fields(
444
+			$entity_array,
445
+			$model,
446
+			$rest_request->get_param('caps'),
447
+			$this->get_model_version_info(),
448
+			$model->get_index_primary_key_string(
449
+				$model->deduce_fields_n_values_from_cols_n_values($db_row)
450
+			)
451
+		);
452
+		$this->_set_debug_info(
453
+			'inaccessible fields',
454
+			array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
455
+		);
456
+		return apply_filters(
457
+			'FHEE__Read__create_entity_from_wpdb_results__entity_return',
458
+			$result_without_inaccessible_fields,
459
+			$model,
460
+			$rest_request->get_param('caps')
461
+		);
462
+	}
463
+
464
+
465
+
466
+	/**
467
+	 * Creates a REST entity array (JSON object we're going to return in the response, but
468
+	 * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
469
+	 * from $wpdb->get_row( $sql, ARRAY_A)
470
+	 *
471
+	 * @param \EEM_Base $model
472
+	 * @param array     $db_row
473
+	 * @return array entity mostly ready for converting to JSON and sending in the response
474
+	 */
475
+	protected function _create_bare_entity_from_wpdb_results(\EEM_Base $model, $db_row)
476
+	{
477
+		$result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
478
+		$result = array_intersect_key($result,
479
+			$this->get_model_version_info()->fields_on_model_in_this_version($model));
480
+		foreach ($result as $field_name => $raw_field_value) {
481
+			$field_obj = $model->field_settings_for($field_name);
482
+			$field_value = $field_obj->prepare_for_set_from_db($raw_field_value);
483
+			if ($this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_ignored())) {
484
+				unset($result[$field_name]);
485
+			} elseif (
486
+			$this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_rendered_format())
487
+			) {
488
+				$result[$field_name] = array(
489
+					'raw'      => $field_obj->prepare_for_get($field_value),
490
+					'rendered' => $field_obj->prepare_for_pretty_echoing($field_value),
491
+				);
492
+			} elseif (
493
+			$this->is_subclass_of_one($field_obj, $this->get_model_version_info()->fields_that_have_pretty_format())
494
+			) {
495
+				$result[$field_name] = array(
496
+					'raw'    => $field_obj->prepare_for_get($field_value),
497
+					'pretty' => $field_obj->prepare_for_pretty_echoing($field_value),
498
+				);
499
+			} elseif ($field_obj instanceof \EE_Datetime_Field) {
500
+				if ($field_value instanceof \DateTime) {
501
+					$timezone = $field_value->getTimezone();
502
+					$field_value->setTimezone(new \DateTimeZone('UTC'));
503
+					$result[$field_name . '_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
504
+						$field_obj,
505
+						$field_value,
506
+						$this->get_model_version_info()->requested_version()
507
+					);
508
+					$field_value->setTimezone($timezone);
509
+					$result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
510
+						$field_obj,
511
+						$field_value,
512
+						$this->get_model_version_info()->requested_version()
513
+					);
514
+				}
515
+			} else {
516
+				$result[$field_name] = Model_Data_Translator::prepare_field_value_for_json(
517
+					$field_obj,
518
+					$field_obj->prepare_for_get($field_value),
519
+					$this->get_model_version_info()->requested_version()
520
+				);
521
+			}
522
+		}
523
+		return $result;
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * Adds a few extra fields to the entity response
530
+	 *
531
+	 * @param \EEM_Base $model
532
+	 * @param array     $db_row
533
+	 * @param array     $entity_array
534
+	 * @return array modified entity
535
+	 */
536
+	protected function _add_extra_fields(\EEM_Base $model, $db_row, $entity_array)
537
+	{
538
+		if ($model instanceof \EEM_CPT_Base) {
539
+			$entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
540
+		}
541
+		return $entity_array;
542
+	}
543
+
544
+
545
+
546
+	/**
547
+	 * Gets links we want to add to the response
548
+	 *
549
+	 * @global \WP_REST_Server $wp_rest_server
550
+	 * @param \EEM_Base        $model
551
+	 * @param array            $db_row
552
+	 * @param array            $entity_array
553
+	 * @return array the _links item in the entity
554
+	 */
555
+	protected function _get_entity_links($model, $db_row, $entity_array)
556
+	{
557
+		//add basic links
558
+		$links = array();
559
+		if ($model->has_primary_key_field()) {
560
+			$links['self'] = array(
561
+				array(
562
+					'href' => $this->get_versioned_link_to(
563
+						\EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
564
+						. '/'
565
+						. $entity_array[$model->primary_key_name()]
566
+					),
567
+				),
568
+			);
569
+		}
570
+		$links['collection'] = array(
571
+			array(
572
+				'href' => $this->get_versioned_link_to(
573
+					\EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
574
+				),
575
+			),
576
+		);
577
+		//add links to related models
578
+		if ($model->has_primary_key_field()) {
579
+			foreach ($this->get_model_version_info()->relation_settings($model) as $relation_name => $relation_obj) {
580
+				$related_model_part = Read::get_related_entity_name($relation_name, $relation_obj);
581
+				$links[\EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
582
+					array(
583
+						'href'   => $this->get_versioned_link_to(
584
+							\EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
585
+							. '/'
586
+							. $entity_array[$model->primary_key_name()]
587
+							. '/'
588
+							. $related_model_part
589
+						),
590
+						'single' => $relation_obj instanceof \EE_Belongs_To_Relation ? true : false,
591
+					),
592
+				);
593
+			}
594
+		}
595
+		return $links;
596
+	}
597
+
598
+
599
+
600
+	/**
601
+	 * Adds the included models indicated in the request to the entity provided
602
+	 *
603
+	 * @param \EEM_Base        $model
604
+	 * @param \WP_REST_Request $rest_request
605
+	 * @param array            $entity_array
606
+	 * @param array            $db_row
607
+	 * @return array the modified entity
608
+	 */
609
+	protected function _include_requested_models(
610
+		\EEM_Base $model,
611
+		\WP_REST_Request $rest_request,
612
+		$entity_array,
613
+		$db_row = array()
614
+	) {
615
+		//if $db_row not included, hope the entity array has what we need
616
+		if (! $db_row) {
617
+			$db_row = $entity_array;
618
+		}
619
+		$includes_for_this_model = $this->explode_and_get_items_prefixed_with($rest_request->get_param('include'), '');
620
+		$includes_for_this_model = $this->_remove_model_names_from_array($includes_for_this_model);
621
+		//if they passed in * or didn't specify any includes, return everything
622
+		if (! in_array('*', $includes_for_this_model)
623
+			&& ! empty($includes_for_this_model)
624
+		) {
625
+			if ($model->has_primary_key_field()) {
626
+				//always include the primary key. ya just gotta know that at least
627
+				$includes_for_this_model[] = $model->primary_key_name();
628
+			}
629
+			if ($this->explode_and_get_items_prefixed_with($rest_request->get_param('calculate'), '')) {
630
+				$includes_for_this_model[] = '_calculated_fields';
631
+			}
632
+			$entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
633
+		}
634
+		$relation_settings = $this->get_model_version_info()->relation_settings($model);
635
+		foreach ($relation_settings as $relation_name => $relation_obj) {
636
+			$related_fields_to_include = $this->explode_and_get_items_prefixed_with(
637
+				$rest_request->get_param('include'),
638
+				$relation_name
639
+			);
640
+			$related_fields_to_calculate = $this->explode_and_get_items_prefixed_with(
641
+				$rest_request->get_param('calculate'),
642
+				$relation_name
643
+			);
644
+			//did they specify they wanted to include a related model, or
645
+			//specific fields from a related model?
646
+			//or did they specify to calculate a field from a related model?
647
+			if ($related_fields_to_include || $related_fields_to_calculate) {
648
+				//if so, we should include at least some part of the related model
649
+				$pretend_related_request = new \WP_REST_Request();
650
+				$pretend_related_request->set_query_params(
651
+					array(
652
+						'caps'      => $rest_request->get_param('caps'),
653
+						'include'   => $related_fields_to_include,
654
+						'calculate' => $related_fields_to_calculate,
655
+					)
656
+				);
657
+				$pretend_related_request->add_header('no_rest_headers', true);
658
+				$primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
659
+					$model->get_index_primary_key_string(
660
+						$model->deduce_fields_n_values_from_cols_n_values($db_row)
661
+					)
662
+				);
663
+				$related_results = $this->_get_entities_from_relation(
664
+					$primary_model_query_params,
665
+					$relation_obj,
666
+					$pretend_related_request
667
+				);
668
+				$entity_array[Read::get_related_entity_name($relation_name, $relation_obj)] = $related_results
669
+																							  instanceof
670
+																							  \WP_Error
671
+					? null
672
+					: $related_results;
673
+			}
674
+		}
675
+		return $entity_array;
676
+	}
677
+
678
+
679
+
680
+	/**
681
+	 * Returns a new array with all the names of models removed. Eg
682
+	 * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
683
+	 *
684
+	 * @param array $arr
685
+	 * @return array
686
+	 */
687
+	private function _remove_model_names_from_array($arr)
688
+	{
689
+		return array_diff($arr, array_keys(\EE_Registry::instance()->non_abstract_db_models));
690
+	}
691
+
692
+
693
+
694
+	/**
695
+	 * Gets the calculated fields for the response
696
+	 *
697
+	 * @param \EEM_Base        $model
698
+	 * @param array            $wpdb_row
699
+	 * @param \WP_REST_Request $rest_request
700
+	 * @return \stdClass the _calculations item in the entity
701
+	 */
702
+	protected function _get_entity_calculations($model, $wpdb_row, $rest_request)
703
+	{
704
+		$calculated_fields = $this->explode_and_get_items_prefixed_with(
705
+			$rest_request->get_param('calculate'),
706
+			''
707
+		);
708
+		//note: setting calculate=* doesn't do anything
709
+		$calculated_fields_to_return = new \stdClass();
710
+		foreach ($calculated_fields as $field_to_calculate) {
711
+			try {
712
+				$calculated_fields_to_return->$field_to_calculate = Model_Data_Translator::prepare_field_value_for_json(
713
+					null,
714
+					$this->_fields_calculator->retrieve_calculated_field_value(
715
+						$model,
716
+						$field_to_calculate,
717
+						$wpdb_row,
718
+						$rest_request,
719
+						$this
720
+					),
721
+					$this->get_model_version_info()->requested_version()
722
+				);
723
+			} catch (Rest_Exception $e) {
724
+				//if we don't have permission to read it, just leave it out. but let devs know about the problem
725
+				$this->_set_response_header(
726
+					'Notices-Field-Calculation-Errors['
727
+					. $e->get_string_code()
728
+					. ']['
729
+					. $model->get_this_model_name()
730
+					. ']['
731
+					. $field_to_calculate
732
+					. ']',
733
+					$e->getMessage(),
734
+					true
735
+				);
736
+			}
737
+		}
738
+		return $calculated_fields_to_return;
739
+	}
740
+
741
+
742
+
743
+	/**
744
+	 * Gets the full URL to the resource, taking the requested version into account
745
+	 *
746
+	 * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
747
+	 * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
748
+	 */
749
+	public function get_versioned_link_to($link_part_after_version_and_slash)
750
+	{
751
+		return rest_url(
752
+			\EED_Core_Rest_Api::ee_api_namespace
753
+			. $this->get_model_version_info()->requested_version()
754
+			. '/'
755
+			. $link_part_after_version_and_slash
756
+		);
757
+	}
758
+
759
+
760
+
761
+	/**
762
+	 * Gets the correct lowercase name for the relation in the API according
763
+	 * to the relation's type
764
+	 *
765
+	 * @param string                  $relation_name
766
+	 * @param \EE_Model_Relation_Base $relation_obj
767
+	 * @return string
768
+	 */
769
+	public static function get_related_entity_name($relation_name, $relation_obj)
770
+	{
771
+		if ($relation_obj instanceof \EE_Belongs_To_Relation) {
772
+			return strtolower($relation_name);
773
+		} else {
774
+			return \EEH_Inflector::pluralize_and_lower($relation_name);
775
+		}
776
+	}
777
+
778
+
779
+
780
+	/**
781
+	 * Gets the one model object with the specified id for the specified model
782
+	 *
783
+	 * @param \EEM_Base        $model
784
+	 * @param \WP_REST_Request $request
785
+	 * @return array|\WP_Error
786
+	 */
787
+	public function get_entity_from_model($model, $request)
788
+	{
789
+		$query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
790
+		if ($model instanceof \EEM_Soft_Delete_Base) {
791
+			$query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
792
+		}
793
+		$restricted_query_params = $query_params;
794
+		$restricted_query_params['caps'] = $this->validate_context($request->get_param('caps'));
795
+		$this->_set_debug_info('model query params', $restricted_query_params);
796
+		$model_rows = $model->get_all_wpdb_results($restricted_query_params);
797
+		if (! empty ($model_rows)) {
798
+			return $this->create_entity_from_wpdb_result(
799
+				$model,
800
+				array_shift($model_rows),
801
+				$request);
802
+		} else {
803
+			//ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
804
+			$lowercase_model_name = strtolower($model->get_this_model_name());
805
+			$model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
806
+			if (! empty($model_rows_found_sans_restrictions)) {
807
+				//you got shafted- it existed but we didn't want to tell you!
808
+				return new \WP_Error(
809
+					'rest_user_cannot_read',
810
+					sprintf(
811
+						__('Sorry, you cannot read this %1$s. Missing permissions are: %2$s', 'event_espresso'),
812
+						strtolower($model->get_this_model_name()),
813
+						Capabilities::get_missing_permissions_string(
814
+							$model,
815
+							$this->validate_context($request->get_param('caps')))
816
+					),
817
+					array('status' => 403)
818
+				);
819
+			} else {
820
+				//it's not you. It just doesn't exist
821
+				return new \WP_Error(
822
+					sprintf('rest_%s_invalid_id', $lowercase_model_name),
823
+					sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
824
+					array('status' => 404)
825
+				);
826
+			}
827
+		}
828
+	}
829
+
830
+
831
+
832
+	/**
833
+	 * If a context is provided which isn't valid, maybe it was added in a future
834
+	 * version so just treat it as a default read
835
+	 *
836
+	 * @param string $context
837
+	 * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
838
+	 */
839
+	public function validate_context($context)
840
+	{
841
+		if (! $context) {
842
+			$context = \EEM_Base::caps_read;
843
+		}
844
+		$valid_contexts = \EEM_Base::valid_cap_contexts();
845
+		if (in_array($context, $valid_contexts)) {
846
+			return $context;
847
+		} else {
848
+			return \EEM_Base::caps_read;
849
+		}
850
+	}
851
+
852
+
853
+
854
+	/**
855
+	 * Verifies the passed in value is an allowable default where conditions value.
856
+	 *
857
+	 * @param $default_query_params
858
+	 * @return string
859
+	 */
860
+	public function validate_default_query_params($default_query_params)
861
+	{
862
+		$valid_default_where_conditions_for_api_calls = array(
863
+			\EEM_Base::default_where_conditions_all,
864
+			\EEM_Base::default_where_conditions_minimum_all,
865
+			\EEM_Base::default_where_conditions_minimum_others,
866
+		);
867
+		if (! $default_query_params) {
868
+			$default_query_params = \EEM_Base::default_where_conditions_all;
869
+		}
870
+		if (
871
+		in_array(
872
+			$default_query_params,
873
+			$valid_default_where_conditions_for_api_calls,
874
+			true
875
+		)
876
+		) {
877
+			return $default_query_params;
878
+		} else {
879
+			return \EEM_Base::default_where_conditions_all;
880
+		}
881
+	}
882
+
883
+
884
+
885
+	/**
886
+	 * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
887
+	 * Note: right now the query parameter keys for fields (and related fields)
888
+	 * can be left as-is, but it's quite possible this will change someday.
889
+	 * Also, this method's contents might be candidate for moving to Model_Data_Translator
890
+	 *
891
+	 * @param \EEM_Base $model
892
+	 * @param array     $query_parameters from $_GET parameter @see Read:handle_request_get_all
893
+	 * @return array like what EEM_Base::get_all() expects or FALSE to indicate
894
+	 *                                    that absolutely no results should be returned
895
+	 * @throws \EE_Error
896
+	 */
897
+	public function create_model_query_params($model, $query_parameters)
898
+	{
899
+		$model_query_params = array();
900
+		if (isset($query_parameters['where'])) {
901
+			$model_query_params[0] = Model_Data_Translator::prepare_conditions_query_params_for_models(
902
+				$query_parameters['where'],
903
+				$model,
904
+				$this->get_model_version_info()->requested_version()
905
+			);
906
+		}
907
+		if (isset($query_parameters['order_by'])) {
908
+			$order_by = $query_parameters['order_by'];
909
+		} elseif (isset($query_parameters['orderby'])) {
910
+			$order_by = $query_parameters['orderby'];
911
+		} else {
912
+			$order_by = null;
913
+		}
914
+		if ($order_by !== null) {
915
+			if (is_array($order_by)) {
916
+				$order_by = Model_Data_Translator::prepare_field_names_in_array_keys_from_json($order_by);
917
+			} else {
918
+				//it's a single item
919
+				$order_by = Model_Data_Translator::prepare_field_name_from_json($order_by);
920
+			}
921
+			$model_query_params['order_by'] = $order_by;
922
+		}
923
+		if (isset($query_parameters['group_by'])) {
924
+			$group_by = $query_parameters['group_by'];
925
+		} elseif (isset($query_parameters['groupby'])) {
926
+			$group_by = $query_parameters['groupby'];
927
+		} else {
928
+			$group_by = array_keys($model->get_combined_primary_key_fields());
929
+		}
930
+		//make sure they're all real names
931
+		if (is_array($group_by)) {
932
+			$group_by = Model_Data_Translator::prepare_field_names_from_json($group_by);
933
+		}
934
+		if ($group_by !== null) {
935
+			$model_query_params['group_by'] = $group_by;
936
+		}
937
+		if (isset($query_parameters['having'])) {
938
+			$model_query_params['having'] = Model_Data_Translator::prepare_conditions_query_params_for_models(
939
+				$query_parameters['having'],
940
+				$model,
941
+				$this->get_model_version_info()->requested_version()
942
+			);
943
+		}
944
+		if (isset($query_parameters['order'])) {
945
+			$model_query_params['order'] = $query_parameters['order'];
946
+		}
947
+		if (isset($query_parameters['mine'])) {
948
+			$model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
949
+		}
950
+		if (isset($query_parameters['limit'])) {
951
+			//limit should be either a string like '23' or '23,43', or an array with two items in it
952
+			if (! is_array($query_parameters['limit'])) {
953
+				$limit_array = explode(',', (string)$query_parameters['limit']);
954
+			} else {
955
+				$limit_array = $query_parameters['limit'];
956
+			}
957
+			$sanitized_limit = array();
958
+			foreach ($limit_array as $key => $limit_part) {
959
+				if ($this->_debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
960
+					throw new \EE_Error(
961
+						sprintf(
962
+							__('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.',
963
+								'event_espresso'),
964
+							wp_json_encode($query_parameters['limit'])
965
+						)
966
+					);
967
+				}
968
+				$sanitized_limit[] = (int)$limit_part;
969
+			}
970
+			$model_query_params['limit'] = implode(',', $sanitized_limit);
971
+		} else {
972
+			$model_query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
973
+		}
974
+		if (isset($query_parameters['caps'])) {
975
+			$model_query_params['caps'] = $this->validate_context($query_parameters['caps']);
976
+		} else {
977
+			$model_query_params['caps'] = \EEM_Base::caps_read;
978
+		}
979
+		if (isset($query_parameters['default_where_conditions'])) {
980
+			$model_query_params['default_where_conditions'] = $this->validate_default_query_params($query_parameters['default_where_conditions']);
981
+		}
982
+		return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
983
+	}
984
+
985
+
986
+
987
+	/**
988
+	 * Changes the REST-style query params for use in the models
989
+	 *
990
+	 * @deprecated
991
+	 * @param \EEM_Base $model
992
+	 * @param array     $query_params sub-array from @see EEM_Base::get_all()
993
+	 * @return array
994
+	 */
995
+	public function prepare_rest_query_params_key_for_models($model, $query_params)
996
+	{
997
+		$model_ready_query_params = array();
998
+		foreach ($query_params as $key => $value) {
999
+			if (is_array($value)) {
1000
+				$model_ready_query_params[$key] = $this->prepare_rest_query_params_key_for_models($model, $value);
1001
+			} else {
1002
+				$model_ready_query_params[$key] = $value;
1003
+			}
1004
+		}
1005
+		return $model_ready_query_params;
1006
+	}
1007
+
1008
+
1009
+
1010
+	/**
1011
+	 * @deprecated
1012
+	 * @param $model
1013
+	 * @param $query_params
1014
+	 * @return array
1015
+	 */
1016
+	public function prepare_rest_query_params_values_for_models($model, $query_params)
1017
+	{
1018
+		$model_ready_query_params = array();
1019
+		foreach ($query_params as $key => $value) {
1020
+			if (is_array($value)) {
1021
+				$model_ready_query_params[$key] = $this->prepare_rest_query_params_values_for_models($model, $value);
1022
+			} else {
1023
+				$model_ready_query_params[$key] = $value;
1024
+			}
1025
+		}
1026
+		return $model_ready_query_params;
1027
+	}
1028
+
1029
+
1030
+
1031
+	/**
1032
+	 * Explodes the string on commas, and only returns items with $prefix followed by a period.
1033
+	 * If no prefix is specified, returns items with no period.
1034
+	 *
1035
+	 * @param string|array $string_to_explode eg "jibba,jabba, blah, blaabla" or array('jibba', 'jabba' )
1036
+	 * @param string       $prefix            "Event" or "foobar"
1037
+	 * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1038
+	 *                                        we only return strings starting with that and a period; if no prefix was
1039
+	 *                                        specified we return all items containing NO periods
1040
+	 */
1041
+	public function explode_and_get_items_prefixed_with($string_to_explode, $prefix)
1042
+	{
1043
+		if (is_string($string_to_explode)) {
1044
+			$exploded_contents = explode(',', $string_to_explode);
1045
+		} else if (is_array($string_to_explode)) {
1046
+			$exploded_contents = $string_to_explode;
1047
+		} else {
1048
+			$exploded_contents = array();
1049
+		}
1050
+		//if the string was empty, we want an empty array
1051
+		$exploded_contents = array_filter($exploded_contents);
1052
+		$contents_with_prefix = array();
1053
+		foreach ($exploded_contents as $item) {
1054
+			$item = trim($item);
1055
+			//if no prefix was provided, so we look for items with no "." in them
1056
+			if (! $prefix) {
1057
+				//does this item have a period?
1058
+				if (strpos($item, '.') === false) {
1059
+					//if not, then its what we're looking for
1060
+					$contents_with_prefix[] = $item;
1061
+				}
1062
+			} else if (strpos($item, $prefix . '.') === 0) {
1063
+				//this item has the prefix and a period, grab it
1064
+				$contents_with_prefix[] = substr(
1065
+					$item,
1066
+					strpos($item, $prefix . '.') + strlen($prefix . '.')
1067
+				);
1068
+			} else if ($item === $prefix) {
1069
+				//this item is JUST the prefix
1070
+				//so let's grab everything after, which is a blank string
1071
+				$contents_with_prefix[] = '';
1072
+			}
1073
+		}
1074
+		return $contents_with_prefix;
1075
+	}
1076
+
1077
+
1078
+
1079
+	/**
1080
+	 * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1081
+	 * Deprecated because its return values were really quite confusing- sometimes it returned
1082
+	 * an empty array (when the include string was blank or '*') or sometimes it returned
1083
+	 * array('*') (when you provided a model and a model of that kind was found).
1084
+	 * Parses the $include_string so we fetch all the field names relating to THIS model
1085
+	 * (ie have NO period in them), or for the provided model (ie start with the model
1086
+	 * name and then a period).
1087
+	 * @param string $include_string @see Read:handle_request_get_all
1088
+	 * @param string $model_name
1089
+	 * @return array of fields for this model. If $model_name is provided, then
1090
+	 *                               the fields for that model, with the model's name removed from each.
1091
+	 *                               If $include_string was blank or '*' returns an empty array
1092
+	 */
1093
+	public function extract_includes_for_this_model($include_string, $model_name = null)
1094
+	{
1095
+		if (is_array($include_string)) {
1096
+			$include_string = implode(',', $include_string);
1097
+		}
1098
+		if ($include_string === '*' || $include_string === '') {
1099
+			return array();
1100
+		}
1101
+		$includes = explode(',', $include_string);
1102
+		$extracted_fields_to_include = array();
1103
+		if ($model_name) {
1104
+			foreach ($includes as $field_to_include) {
1105
+				$field_to_include = trim($field_to_include);
1106
+				if (strpos($field_to_include, $model_name . '.') === 0) {
1107
+					//found the model name at the exact start
1108
+					$field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1109
+					$extracted_fields_to_include[] = $field_sans_model_name;
1110
+				} elseif ($field_to_include == $model_name) {
1111
+					$extracted_fields_to_include[] = '*';
1112
+				}
1113
+			}
1114
+		} else {
1115
+			//look for ones with no period
1116
+			foreach ($includes as $field_to_include) {
1117
+				$field_to_include = trim($field_to_include);
1118
+				if (
1119
+					strpos($field_to_include, '.') === false
1120
+					&& ! $this->get_model_version_info()->is_model_name_in_this_version($field_to_include)
1121
+				) {
1122
+					$extracted_fields_to_include[] = $field_to_include;
1123
+				}
1124
+			}
1125
+		}
1126
+		return $extracted_fields_to_include;
1127
+	}
1128 1128
 }
1129 1129
 
1130 1130
 
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
 use EventEspresso\core\libraries\rest_api\Rest_Exception;
7 7
 use EventEspresso\core\libraries\rest_api\Model_Data_Translator;
8 8
 
9
-if (! defined('EVENT_ESPRESSO_VERSION')) {
9
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
10 10
     exit('No direct script access allowed');
11 11
 }
12 12
 
@@ -55,12 +55,12 @@  discard block
 block discarded – undo
55 55
         try {
56 56
             $matches = $controller->parse_route(
57 57
                 $request->get_route(),
58
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)~',
58
+                '~'.\EED_Core_Rest_Api::ee_api_namespace_for_regex.'(.*)~',
59 59
                 array('version', 'model')
60 60
             );
61 61
             $controller->set_requested_version($matches['version']);
62 62
             $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
63
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
63
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
64 64
                 return $controller->send_response(
65 65
                     new \WP_Error(
66 66
                         'endpoint_parsing_error',
@@ -97,11 +97,11 @@  discard block
 block discarded – undo
97 97
         try {
98 98
             $matches = $controller->parse_route(
99 99
                 $request->get_route(),
100
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)~',
100
+                '~'.\EED_Core_Rest_Api::ee_api_namespace_for_regex.'(.*)/(.*)~',
101 101
                 array('version', 'model', 'id'));
102 102
             $controller->set_requested_version($matches['version']);
103 103
             $model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
104
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
104
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($model_name_singular)) {
105 105
                 return $controller->send_response(
106 106
                     new \WP_Error(
107 107
                         'endpoint_parsing_error',
@@ -139,12 +139,12 @@  discard block
 block discarded – undo
139 139
         try {
140 140
             $matches = $controller->parse_route(
141 141
                 $request->get_route(),
142
-                '~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)/(.*)~',
142
+                '~'.\EED_Core_Rest_Api::ee_api_namespace_for_regex.'(.*)/(.*)/(.*)~',
143 143
                 array('version', 'model', 'id', 'related_model')
144 144
             );
145 145
             $controller->set_requested_version($matches['version']);
146 146
             $main_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['model']);
147
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
147
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($main_model_name_singular)) {
148 148
                 return $controller->send_response(
149 149
                     new \WP_Error(
150 150
                         'endpoint_parsing_error',
@@ -159,11 +159,11 @@  discard block
 block discarded – undo
159 159
             $main_model = $controller->get_model_version_info()->load_model($main_model_name_singular);
160 160
             //assume the related model name is plural and try to find the model's name
161 161
             $related_model_name_singular = \EEH_Inflector::singularize_and_upper($matches['related_model']);
162
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
162
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
163 163
                 //so the word didn't singularize well. Maybe that's just because it's a singular word?
164 164
                 $related_model_name_singular = \EEH_Inflector::humanize($matches['related_model']);
165 165
             }
166
-            if (! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
166
+            if ( ! $controller->get_model_version_info()->is_model_name_in_this_version($related_model_name_singular)) {
167 167
                 return $controller->send_response(
168 168
                     new \WP_Error(
169 169
                         'endpoint_parsing_error',
@@ -199,7 +199,7 @@  discard block
 block discarded – undo
199 199
     public function get_entities_from_model($model, $request)
200 200
     {
201 201
         $query_params = $this->create_model_query_params($model, $request->get_params());
202
-        if (! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
202
+        if ( ! Capabilities::current_user_has_partial_access_to($model, $query_params['caps'])) {
203 203
             $model_name_plural = \EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
204 204
             return new \WP_Error(
205 205
                 sprintf('rest_%s_cannot_list', $model_name_plural),
@@ -211,7 +211,7 @@  discard block
 block discarded – undo
211 211
                 array('status' => 403)
212 212
             );
213 213
         }
214
-        if (! $request->get_header('no_rest_headers')) {
214
+        if ( ! $request->get_header('no_rest_headers')) {
215 215
             $this->_set_headers_from_query_params($model, $query_params);
216 216
         }
217 217
         /** @type array $results */
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
         $context = $this->validate_context($request->get_param('caps'));
242 242
         $model = $relation->get_this_model();
243 243
         $related_model = $relation->get_other_model();
244
-        if (! isset($primary_model_query_params[0])) {
244
+        if ( ! isset($primary_model_query_params[0])) {
245 245
             $primary_model_query_params[0] = array();
246 246
         }
247 247
         //check if they can access the 1st model object
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
         }
293 293
         $query_params['default_where_conditions'] = 'none';
294 294
         $query_params['caps'] = $context;
295
-        if (! $request->get_header('no_rest_headers')) {
295
+        if ( ! $request->get_header('no_rest_headers')) {
296 296
             $this->_set_headers_from_query_params($relation->get_other_model(), $query_params);
297 297
         }
298 298
         /** @type array $results */
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
      */
345 345
     public function get_entities_from_relation($id, $relation, $request)
346 346
     {
347
-        if (! $relation->get_this_model()->has_primary_key_field()) {
347
+        if ( ! $relation->get_this_model()->has_primary_key_field()) {
348 348
             throw new \EE_Error(
349 349
                 sprintf(
350 350
                     __('Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
         $this->_set_debug_info('missing caps',
382 382
             Capabilities::get_missing_permissions_string($model, $query_params['caps']));
383 383
         //normally the limit to a 2-part array, where the 2nd item is the limit
384
-        if (! isset($query_params['limit'])) {
384
+        if ( ! isset($query_params['limit'])) {
385 385
             $query_params['limit'] = \EED_Core_Rest_Api::get_default_query_limit();
386 386
         }
387 387
         if (is_array($query_params['limit'])) {
@@ -415,7 +415,7 @@  discard block
 block discarded – undo
415 415
      */
416 416
     public function create_entity_from_wpdb_result($model, $db_row, $rest_request, $deprecated = null)
417 417
     {
418
-        if (! $rest_request instanceof \WP_REST_Request) {
418
+        if ( ! $rest_request instanceof \WP_REST_Request) {
419 419
             //ok so this was called in the old style, where the 3rd arg was
420 420
             //$include, and the 4th arg was $context
421 421
             //now setup the request just to avoid fatal errors, although we won't be able
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
                 if ($field_value instanceof \DateTime) {
501 501
                     $timezone = $field_value->getTimezone();
502 502
                     $field_value->setTimezone(new \DateTimeZone('UTC'));
503
-                    $result[$field_name . '_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
503
+                    $result[$field_name.'_gmt'] = Model_Data_Translator::prepare_field_value_for_json(
504 504
                         $field_obj,
505 505
                         $field_value,
506 506
                         $this->get_model_version_info()->requested_version()
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
         if ($model->has_primary_key_field()) {
579 579
             foreach ($this->get_model_version_info()->relation_settings($model) as $relation_name => $relation_obj) {
580 580
                 $related_model_part = Read::get_related_entity_name($relation_name, $relation_obj);
581
-                $links[\EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
581
+                $links[\EED_Core_Rest_Api::ee_api_link_namespace.$related_model_part] = array(
582 582
                     array(
583 583
                         'href'   => $this->get_versioned_link_to(
584 584
                             \EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
@@ -613,13 +613,13 @@  discard block
 block discarded – undo
613 613
         $db_row = array()
614 614
     ) {
615 615
         //if $db_row not included, hope the entity array has what we need
616
-        if (! $db_row) {
616
+        if ( ! $db_row) {
617 617
             $db_row = $entity_array;
618 618
         }
619 619
         $includes_for_this_model = $this->explode_and_get_items_prefixed_with($rest_request->get_param('include'), '');
620 620
         $includes_for_this_model = $this->_remove_model_names_from_array($includes_for_this_model);
621 621
         //if they passed in * or didn't specify any includes, return everything
622
-        if (! in_array('*', $includes_for_this_model)
622
+        if ( ! in_array('*', $includes_for_this_model)
623 623
             && ! empty($includes_for_this_model)
624 624
         ) {
625 625
             if ($model->has_primary_key_field()) {
@@ -794,7 +794,7 @@  discard block
 block discarded – undo
794 794
         $restricted_query_params['caps'] = $this->validate_context($request->get_param('caps'));
795 795
         $this->_set_debug_info('model query params', $restricted_query_params);
796 796
         $model_rows = $model->get_all_wpdb_results($restricted_query_params);
797
-        if (! empty ($model_rows)) {
797
+        if ( ! empty ($model_rows)) {
798 798
             return $this->create_entity_from_wpdb_result(
799 799
                 $model,
800 800
                 array_shift($model_rows),
@@ -803,7 +803,7 @@  discard block
 block discarded – undo
803 803
             //ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
804 804
             $lowercase_model_name = strtolower($model->get_this_model_name());
805 805
             $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
806
-            if (! empty($model_rows_found_sans_restrictions)) {
806
+            if ( ! empty($model_rows_found_sans_restrictions)) {
807 807
                 //you got shafted- it existed but we didn't want to tell you!
808 808
                 return new \WP_Error(
809 809
                     'rest_user_cannot_read',
@@ -838,7 +838,7 @@  discard block
 block discarded – undo
838 838
      */
839 839
     public function validate_context($context)
840 840
     {
841
-        if (! $context) {
841
+        if ( ! $context) {
842 842
             $context = \EEM_Base::caps_read;
843 843
         }
844 844
         $valid_contexts = \EEM_Base::valid_cap_contexts();
@@ -864,7 +864,7 @@  discard block
 block discarded – undo
864 864
             \EEM_Base::default_where_conditions_minimum_all,
865 865
             \EEM_Base::default_where_conditions_minimum_others,
866 866
         );
867
-        if (! $default_query_params) {
867
+        if ( ! $default_query_params) {
868 868
             $default_query_params = \EEM_Base::default_where_conditions_all;
869 869
         }
870 870
         if (
@@ -949,14 +949,14 @@  discard block
 block discarded – undo
949 949
         }
950 950
         if (isset($query_parameters['limit'])) {
951 951
             //limit should be either a string like '23' or '23,43', or an array with two items in it
952
-            if (! is_array($query_parameters['limit'])) {
953
-                $limit_array = explode(',', (string)$query_parameters['limit']);
952
+            if ( ! is_array($query_parameters['limit'])) {
953
+                $limit_array = explode(',', (string) $query_parameters['limit']);
954 954
             } else {
955 955
                 $limit_array = $query_parameters['limit'];
956 956
             }
957 957
             $sanitized_limit = array();
958 958
             foreach ($limit_array as $key => $limit_part) {
959
-                if ($this->_debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
959
+                if ($this->_debug_mode && ( ! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
960 960
                     throw new \EE_Error(
961 961
                         sprintf(
962 962
                             __('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.',
@@ -965,7 +965,7 @@  discard block
 block discarded – undo
965 965
                         )
966 966
                     );
967 967
                 }
968
-                $sanitized_limit[] = (int)$limit_part;
968
+                $sanitized_limit[] = (int) $limit_part;
969 969
             }
970 970
             $model_query_params['limit'] = implode(',', $sanitized_limit);
971 971
         } else {
@@ -1053,17 +1053,17 @@  discard block
 block discarded – undo
1053 1053
         foreach ($exploded_contents as $item) {
1054 1054
             $item = trim($item);
1055 1055
             //if no prefix was provided, so we look for items with no "." in them
1056
-            if (! $prefix) {
1056
+            if ( ! $prefix) {
1057 1057
                 //does this item have a period?
1058 1058
                 if (strpos($item, '.') === false) {
1059 1059
                     //if not, then its what we're looking for
1060 1060
                     $contents_with_prefix[] = $item;
1061 1061
                 }
1062
-            } else if (strpos($item, $prefix . '.') === 0) {
1062
+            } else if (strpos($item, $prefix.'.') === 0) {
1063 1063
                 //this item has the prefix and a period, grab it
1064 1064
                 $contents_with_prefix[] = substr(
1065 1065
                     $item,
1066
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1066
+                    strpos($item, $prefix.'.') + strlen($prefix.'.')
1067 1067
                 );
1068 1068
             } else if ($item === $prefix) {
1069 1069
                 //this item is JUST the prefix
@@ -1103,9 +1103,9 @@  discard block
 block discarded – undo
1103 1103
         if ($model_name) {
1104 1104
             foreach ($includes as $field_to_include) {
1105 1105
                 $field_to_include = trim($field_to_include);
1106
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1106
+                if (strpos($field_to_include, $model_name.'.') === 0) {
1107 1107
                     //found the model name at the exact start
1108
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1108
+                    $field_sans_model_name = str_replace($model_name.'.', '', $field_to_include);
1109 1109
                     $extracted_fields_to_include[] = $field_sans_model_name;
1110 1110
                 } elseif ($field_to_include == $model_name) {
1111 1111
                     $extracted_fields_to_include[] = '*';
Please login to merge, or discard this patch.
core/EE_Payment_Processor.core.php 1 patch
Indentation   +734 added lines, -734 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 EE_Registry::instance()->load_class('Processor_Base');
5 5
 
@@ -16,737 +16,737 @@  discard block
 block discarded – undo
16 16
 class EE_Payment_Processor extends EE_Processor_Base
17 17
 {
18 18
 
19
-    /**
20
-     * @var EE_Payment_Processor $_instance
21
-     * @access    private
22
-     */
23
-    private static $_instance;
24
-
25
-
26
-
27
-    /**
28
-     * @singleton method used to instantiate class object
29
-     * @access    public
30
-     * @return EE_Payment_Processor instance
31
-     */
32
-    public static function instance()
33
-    {
34
-        // check if class object is instantiated
35
-        if ( ! self::$_instance instanceof EE_Payment_Processor) {
36
-            self::$_instance = new self();
37
-        }
38
-        return self::$_instance;
39
-    }
40
-
41
-
42
-
43
-    /**
44
-     *private constructor to prevent direct creation
45
-     *
46
-     * @Constructor
47
-     * @access private
48
-     */
49
-    private function __construct()
50
-    {
51
-        do_action('AHEE__EE_Payment_Processor__construct');
52
-        add_action('http_api_curl', array($this, '_curl_requests_to_paypal_use_tls'), 10, 3);
53
-    }
54
-
55
-
56
-
57
-    /**
58
-     * Using the selected gateway, processes the payment for that transaction, and updates the transaction
59
-     * appropriately. Saves the payment that is generated
60
-     *
61
-     * @param EE_Payment_Method    $payment_method
62
-     * @param EE_Transaction       $transaction
63
-     * @param float                $amount       if only part of the transaction is to be paid for, how much.
64
-     *                                           Leave null if payment is for the full amount owing
65
-     * @param EE_Billing_Info_Form $billing_form (or probably null, if it's an offline or offsite payment method).
66
-     *                                           Receive_form_submission() should have
67
-     *                                           already been called on the billing form
68
-     *                                           (ie, its inputs should have their normalized values set).
69
-     * @param string               $return_url   string used mostly by offsite gateways to specify
70
-     *                                           where to go AFTER the offsite gateway
71
-     * @param string               $method       like 'CART', indicates who the client who called this was
72
-     * @param bool                 $by_admin     TRUE if payment is being attempted from the admin
73
-     * @param boolean              $update_txn   whether or not to call
74
-     *                                           EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
75
-     * @param string               $cancel_url   URL to return to if off-site payments are cancelled
76
-     * @return \EE_Payment
77
-     * @throws \EE_Error
78
-     */
79
-    public function process_payment(
80
-        EE_Payment_Method $payment_method,
81
-        EE_Transaction $transaction,
82
-        $amount = null,
83
-        $billing_form = null,
84
-        $return_url = null,
85
-        $method = 'CART',
86
-        $by_admin = false,
87
-        $update_txn = true,
88
-        $cancel_url = ''
89
-    ) {
90
-        if ((float)$amount < 0) {
91
-            throw new EE_Error(
92
-                sprintf(
93
-                    __(
94
-                        'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
95
-                        'event_espresso'
96
-                    ),
97
-                    $amount,
98
-                    $transaction->ID()
99
-                )
100
-            );
101
-        }
102
-        // verify payment method
103
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
104
-        // verify transaction
105
-        EEM_Transaction::instance()->ensure_is_obj($transaction);
106
-        $transaction->set_payment_method_ID($payment_method->ID());
107
-        // verify payment method type
108
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
109
-            $payment = $payment_method->type_obj()->process_payment(
110
-                $transaction,
111
-                min($amount, $transaction->remaining()),//make sure we don't overcharge
112
-                $billing_form,
113
-                $return_url,
114
-                add_query_arg(array('ee_cancel_payment' => true), $cancel_url),
115
-                $method,
116
-                $by_admin
117
-            );
118
-            // check if payment method uses an off-site gateway
119
-            if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
120
-                // don't process payments for off-site gateways yet because no payment has occurred yet
121
-                $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
122
-            }
123
-            return $payment;
124
-        } else {
125
-            EE_Error::add_error(
126
-                sprintf(
127
-                    __('A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.', 'event_espresso'),
128
-                    '<br/>',
129
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
130
-                ), __FILE__, __FUNCTION__, __LINE__
131
-            );
132
-            return null;
133
-        }
134
-    }
135
-
136
-
137
-
138
-    /**
139
-     * @param EE_Transaction|int $transaction
140
-     * @param EE_Payment_Method  $payment_method
141
-     * @throws EE_Error
142
-     * @return string
143
-     */
144
-    public function get_ipn_url_for_payment_method($transaction, $payment_method)
145
-    {
146
-        /** @type \EE_Transaction $transaction */
147
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
148
-        $primary_reg = $transaction->primary_registration();
149
-        if ( ! $primary_reg instanceof EE_Registration) {
150
-            throw new EE_Error(
151
-                sprintf(
152
-                    __(
153
-                        "Cannot get IPN URL for transaction with ID %d because it has no primary registration",
154
-                        "event_espresso"
155
-                    ),
156
-                    $transaction->ID()
157
-                )
158
-            );
159
-        }
160
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
161
-        $url = add_query_arg(
162
-            array(
163
-                'e_reg_url_link'    => $primary_reg->reg_url_link(),
164
-                'ee_payment_method' => $payment_method->slug(),
165
-            ),
166
-            EE_Registry::instance()->CFG->core->txn_page_url()
167
-        );
168
-        return $url;
169
-    }
170
-
171
-
172
-
173
-    /**
174
-     * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
175
-     * we can easily find what registration the IPN is for and what payment method.
176
-     * However, if not, we'll give all payment methods a chance to claim it and process it.
177
-     * If a payment is found for the IPN info, it is saved.
178
-     *
179
-     * @param array              $_req_data            eg $_REQUEST
180
-     * @param EE_Transaction|int $transaction          optional (or a transactions id)
181
-     * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
182
-     * @param boolean            $update_txn           whether or not to call
183
-     *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
184
-     * @param bool               $separate_IPN_request whether the IPN uses a separate request ( true like PayPal )
185
-     *                                                 or is processed manually ( false like Mijireh )
186
-     * @throws EE_Error
187
-     * @throws Exception
188
-     * @return EE_Payment
189
-     */
190
-    public function process_ipn(
191
-        $_req_data,
192
-        $transaction = null,
193
-        $payment_method = null,
194
-        $update_txn = true,
195
-        $separate_IPN_request = true
196
-    ) {
197
-        EE_Registry::instance()->load_model('Change_Log');
198
-        $_req_data = $this->_remove_unusable_characters_from_array((array)$_req_data);
199
-        EE_Processor_Base::set_IPN($separate_IPN_request);
200
-        $obj_for_log = null;
201
-        if ($transaction instanceof EE_Transaction) {
202
-            $obj_for_log = $transaction;
203
-            if ($payment_method instanceof EE_Payment_Method) {
204
-                $obj_for_log = EEM_Payment::instance()->get_one(
205
-                    array(
206
-                        array('TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()),
207
-                        'order_by' => array('PAY_timestamp' => 'desc'),
208
-                    )
209
-                );
210
-            }
211
-        } else if ($payment_method instanceof EE_Payment) {
212
-            $obj_for_log = $payment_method;
213
-        }
214
-        $log = EEM_Change_Log::instance()->log(
215
-            EEM_Change_Log::type_gateway,
216
-            array('IPN data received' => $_req_data),
217
-            $obj_for_log
218
-        );
219
-        try {
220
-            /**
221
-             * @var EE_Payment $payment
222
-             */
223
-            $payment = null;
224
-            if ($transaction && $payment_method) {
225
-                /** @type EE_Transaction $transaction */
226
-                $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
227
-                /** @type EE_Payment_Method $payment_method */
228
-                $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
229
-                if ($payment_method->type_obj() instanceof EE_PMT_Base) {
230
-                    try {
231
-                        $payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
232
-                        $log->set_object($payment);
233
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
234
-                        EEM_Change_Log::instance()->log(
235
-                            EEM_Change_Log::type_gateway,
236
-                            array(
237
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
238
-                                'current_url' => EEH_URL::current_url(),
239
-                                'payment'     => $e->getPaymentProperties(),
240
-                                'IPN_data'    => $e->getIpnData(),
241
-                            ),
242
-                            $obj_for_log
243
-                        );
244
-                        return $e->getPayment();
245
-                    }
246
-                } else {
247
-                    // not a payment
248
-                    EE_Error::add_error(
249
-                        sprintf(
250
-                            __('A valid payment method could not be determined due to a technical issue.%sPlease refresh your browser and try again or contact %s for assistance.', 'event_espresso'),
251
-                            '<br/>',
252
-                            EE_Registry::instance()->CFG->organization->get_pretty('email')
253
-                        ),
254
-                        __FILE__, __FUNCTION__, __LINE__
255
-                    );
256
-                }
257
-            } else {
258
-                //that's actually pretty ok. The IPN just wasn't able
259
-                //to identify which transaction or payment method this was for
260
-                // give all active payment methods a chance to claim it
261
-                $active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
262
-                foreach ($active_payment_methods as $active_payment_method) {
263
-                    try {
264
-                        $payment = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
265
-                        $payment_method = $active_payment_method;
266
-                        EEM_Change_Log::instance()->log(
267
-                            EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment
268
-                        );
269
-                        break;
270
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
271
-                        EEM_Change_Log::instance()->log(
272
-                            EEM_Change_Log::type_gateway,
273
-                            array(
274
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
275
-                                'current_url' => EEH_URL::current_url(),
276
-                                'payment'     => $e->getPaymentProperties(),
277
-                                'IPN_data'    => $e->getIpnData(),
278
-                            ),
279
-                            $obj_for_log
280
-                        );
281
-                        return $e->getPayment();
282
-                    } catch (EE_Error $e) {
283
-                        //that's fine- it apparently couldn't handle the IPN
284
-                    }
285
-                }
286
-            }
287
-            // 			EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
288
-            if ($payment instanceof EE_Payment) {
289
-                $payment->save();
290
-                //  update the TXN
291
-                $this->update_txn_based_on_payment($transaction, $payment, $update_txn, $separate_IPN_request);
292
-            } else {
293
-                //we couldn't find the payment for this IPN... let's try and log at least SOMETHING
294
-                if ($payment_method) {
295
-                    EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment_method);
296
-                } elseif ($transaction) {
297
-                    EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $transaction);
298
-                }
299
-            }
300
-            return $payment;
301
-        } catch (EE_Error $e) {
302
-            do_action(
303
-                'AHEE__log', __FILE__, __FUNCTION__, sprintf(
304
-                    __('Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"', 'event_espresso'),
305
-                    print_r($transaction, true),
306
-                    print_r($_req_data, true),
307
-                    $e->getMessage()
308
-                )
309
-            );
310
-            throw $e;
311
-        }
312
-    }
313
-
314
-
315
-
316
-    /**
317
-     * Removes any non-printable illegal characters from the input,
318
-     * which might cause a raucous when trying to insert into the database
319
-     *
320
-     * @param  array $request_data
321
-     * @return array
322
-     */
323
-    protected function _remove_unusable_characters_from_array(array $request_data)
324
-    {
325
-        $return_data = array();
326
-        foreach ($request_data as $key => $value) {
327
-            $return_data[$this->_remove_unusable_characters($key)] = $this->_remove_unusable_characters($value);
328
-        }
329
-        return $return_data;
330
-    }
331
-
332
-
333
-
334
-    /**
335
-     * Removes any non-printable illegal characters from the input,
336
-     * which might cause a raucous when trying to insert into the database
337
-     *
338
-     * @param string $request_data
339
-     * @return string
340
-     */
341
-    protected function _remove_unusable_characters($request_data)
342
-    {
343
-        return preg_replace('/[^[:print:]]/', '', $request_data);
344
-    }
345
-
346
-
347
-
348
-    /**
349
-     * Should be called just before displaying the payment attempt results to the user,
350
-     * when the payment attempt has finished. Some payment methods may have special
351
-     * logic to perform here. For example, if process_payment() happens on a special request
352
-     * and then the user is redirected to a page that displays the payment's status, this
353
-     * should be called while loading the page that displays the payment's status. If the user is
354
-     * sent to an offsite payment provider, this should be called upon returning from that offsite payment
355
-     * provider.
356
-     *
357
-     * @param EE_Transaction|int $transaction
358
-     * @param bool               $update_txn whether or not to call
359
-     *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
360
-     * @throws \EE_Error
361
-     * @return EE_Payment
362
-     * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
363
-     *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
364
-     */
365
-    public function finalize_payment_for($transaction, $update_txn = true)
366
-    {
367
-        /** @var $transaction EE_Transaction */
368
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
369
-        $last_payment_method = $transaction->payment_method();
370
-        if ($last_payment_method instanceof EE_Payment_Method) {
371
-            $payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
372
-            $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
373
-            return $payment;
374
-        } else {
375
-            return null;
376
-        }
377
-    }
378
-
379
-
380
-
381
-    /**
382
-     * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
383
-     *
384
-     * @param EE_Payment_Method $payment_method
385
-     * @param EE_Payment        $payment_to_refund
386
-     * @param array             $refund_info
387
-     * @return EE_Payment
388
-     * @throws \EE_Error
389
-     */
390
-    public function process_refund(
391
-        EE_Payment_Method $payment_method,
392
-        EE_Payment $payment_to_refund,
393
-        $refund_info = array()
394
-    ) {
395
-        if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
396
-            $payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
397
-            $this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
398
-        }
399
-        return $payment_to_refund;
400
-    }
401
-
402
-
403
-
404
-    /**
405
-     * This should be called each time there may have been an update to a
406
-     * payment on a transaction (ie, we asked for a payment to process a
407
-     * payment for a transaction, or we told a payment method about an IPN, or
408
-     * we told a payment method to
409
-     * "finalize_payment_for" (a transaction), or we told a payment method to
410
-     * process a refund. This should handle firing the correct hooks to
411
-     * indicate
412
-     * what exactly happened and updating the transaction appropriately). This
413
-     * could be integrated directly into EE_Transaction upon save, but we want
414
-     * this logic to be separate from 'normal' plain-jane saving and updating
415
-     * of transactions and payments, and to be tied to payment processing.
416
-     * Note: this method DOES NOT save the payment passed into it. It is the responsibility
417
-     * of previous code to decide whether or not to save (because the payment passed into
418
-     * this method might be a temporary, never-to-be-saved payment from an offline gateway,
419
-     * in which case we only want that payment object for some temporary usage during this request,
420
-     * but we don't want it to be saved).
421
-     *
422
-     * @param EE_Transaction|int $transaction
423
-     * @param EE_Payment         $payment
424
-     * @param boolean            $update_txn
425
-     *                        whether or not to call
426
-     *                        EE_Transaction_Processor::
427
-     *                        update_transaction_and_registrations_after_checkout_or_payment()
428
-     *                        (you can save 1 DB query if you know you're going
429
-     *                        to save it later instead)
430
-     * @param bool               $IPN
431
-     *                        if processing IPNs or other similar payment
432
-     *                        related activities that occur in alternate
433
-     *                        requests than the main one that is processing the
434
-     *                        TXN, then set this to true to check whether the
435
-     *                        TXN is locked before updating
436
-     * @throws \EE_Error
437
-     */
438
-    public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
439
-    {
440
-        $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
441
-        /** @type EE_Transaction $transaction */
442
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
443
-        // can we freely update the TXN at this moment?
444
-        if ($IPN && $transaction->is_locked()) {
445
-            // don't update the transaction at this exact moment
446
-            // because the TXN is active in another request
447
-            EE_Cron_Tasks::schedule_update_transaction_with_payment(
448
-                time(),
449
-                $transaction->ID(),
450
-                $payment->ID()
451
-            );
452
-        } else {
453
-            // verify payment and that it has been saved
454
-            if ($payment instanceof EE_Payment && $payment->ID()) {
455
-                if (
456
-                    $payment->payment_method() instanceof EE_Payment_Method
457
-                    && $payment->payment_method()->type_obj() instanceof EE_PMT_Base
458
-                ) {
459
-                    $payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
460
-                    // update TXN registrations with payment info
461
-                    $this->process_registration_payments($transaction, $payment);
462
-                }
463
-                $do_action = $payment->just_approved()
464
-                    ? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
465
-                    : $do_action;
466
-            } else {
467
-                // send out notifications
468
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
469
-                $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
470
-            }
471
-            if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
472
-                /** @type EE_Transaction_Payments $transaction_payments */
473
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
474
-                // set new value for total paid
475
-                $transaction_payments->calculate_total_payments_and_update_status($transaction);
476
-                // call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
477
-                if ($update_txn) {
478
-                    $this->_post_payment_processing($transaction, $payment, $IPN);
479
-                }
480
-            }
481
-            // granular hook for others to use.
482
-            do_action($do_action, $transaction, $payment);
483
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
484
-            //global hook for others to use.
485
-            do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
486
-        }
487
-    }
488
-
489
-
490
-
491
-    /**
492
-     * update registrations REG_paid field after successful payment and link registrations with payment
493
-     *
494
-     * @param EE_Transaction    $transaction
495
-     * @param EE_Payment        $payment
496
-     * @param EE_Registration[] $registrations
497
-     * @throws \EE_Error
498
-     */
499
-    public function process_registration_payments(
500
-        EE_Transaction $transaction,
501
-        EE_Payment $payment,
502
-        $registrations = array()
503
-    ) {
504
-        // only process if payment was successful
505
-        if ($payment->status() !== EEM_Payment::status_id_approved) {
506
-            return;
507
-        }
508
-        //EEM_Registration::instance()->show_next_x_db_queries();
509
-        if (empty($registrations)) {
510
-            // find registrations with monies owing that can receive a payment
511
-            $registrations = $transaction->registrations(
512
-                array(
513
-                    array(
514
-                        // only these reg statuses can receive payments
515
-                        'STS_ID'           => array('IN', EEM_Registration::reg_statuses_that_allow_payment()),
516
-                        'REG_final_price'  => array('!=', 0),
517
-                        'REG_final_price*' => array('!=', 'REG_paid', true),
518
-                    ),
519
-                )
520
-            );
521
-        }
522
-        // still nothing ??!??
523
-        if (empty($registrations)) {
524
-            return;
525
-        }
526
-        // todo: break out the following logic into a separate strategy class
527
-        // todo: named something like "Sequential_Reg_Payment_Strategy"
528
-        // todo: which would apply payments using the capitalist "first come first paid" approach
529
-        // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
530
-        // todo: which would be the socialist "everybody gets a piece of pie" approach,
531
-        // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
532
-        $refund = $payment->is_a_refund();
533
-        // how much is available to apply to registrations?
534
-        $available_payment_amount = abs($payment->amount());
535
-        foreach ($registrations as $registration) {
536
-            if ($registration instanceof EE_Registration) {
537
-                // nothing left?
538
-                if ($available_payment_amount <= 0) {
539
-                    break;
540
-                }
541
-                if ($refund) {
542
-                    $available_payment_amount = $this->process_registration_refund($registration, $payment, $available_payment_amount);
543
-                } else {
544
-                    $available_payment_amount = $this->process_registration_payment($registration, $payment, $available_payment_amount);
545
-                }
546
-            }
547
-        }
548
-        if ($available_payment_amount > 0 && apply_filters('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', false)) {
549
-            EE_Error::add_attention(
550
-                sprintf(
551
-                    __('A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
552
-                        'event_espresso'),
553
-                    EEH_Template::format_currency($available_payment_amount),
554
-                    implode(', ', array_keys($registrations)),
555
-                    '<br/>',
556
-                    EEH_Template::format_currency($payment->amount())
557
-                ),
558
-                __FILE__, __FUNCTION__, __LINE__
559
-            );
560
-        }
561
-    }
562
-
563
-
564
-
565
-    /**
566
-     * update registration REG_paid field after successful payment and link registration with payment
567
-     *
568
-     * @param EE_Registration $registration
569
-     * @param EE_Payment      $payment
570
-     * @param float           $available_payment_amount
571
-     * @return float
572
-     * @throws \EE_Error
573
-     */
574
-    public function process_registration_payment(
575
-        EE_Registration $registration,
576
-        EE_Payment $payment,
577
-        $available_payment_amount = 0.00
578
-    ) {
579
-        $owing = $registration->final_price() - $registration->paid();
580
-        if ($owing > 0) {
581
-            // don't allow payment amount to exceed the available payment amount, OR the amount owing
582
-            $payment_amount = min($available_payment_amount, $owing);
583
-            // update $available_payment_amount
584
-            $available_payment_amount -= $payment_amount;
585
-            //calculate and set new REG_paid
586
-            $registration->set_paid($registration->paid() + $payment_amount);
587
-            // now save it
588
-            $this->_apply_registration_payment($registration, $payment, $payment_amount);
589
-        }
590
-        return $available_payment_amount;
591
-    }
592
-
593
-
594
-
595
-    /**
596
-     * update registration REG_paid field after successful payment and link registration with payment
597
-     *
598
-     * @param EE_Registration $registration
599
-     * @param EE_Payment      $payment
600
-     * @param float           $payment_amount
601
-     * @return void
602
-     * @throws \EE_Error
603
-     */
604
-    protected function _apply_registration_payment(
605
-        EE_Registration $registration,
606
-        EE_Payment $payment,
607
-        $payment_amount = 0.00
608
-    ) {
609
-        // find any existing reg payment records for this registration and payment
610
-        $existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
611
-            array(array('REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()))
612
-        );
613
-        // if existing registration payment exists
614
-        if ($existing_reg_payment instanceof EE_Registration_Payment) {
615
-            // then update that record
616
-            $existing_reg_payment->set_amount($payment_amount);
617
-            $existing_reg_payment->save();
618
-        } else {
619
-            // or add new relation between registration and payment and set amount
620
-            $registration->_add_relation_to($payment, 'Payment', array('RPY_amount' => $payment_amount));
621
-            // make it stick
622
-            $registration->save();
623
-        }
624
-    }
625
-
626
-
627
-
628
-    /**
629
-     * update registration REG_paid field after refund and link registration with payment
630
-     *
631
-     * @param EE_Registration $registration
632
-     * @param EE_Payment      $payment
633
-     * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
634
-     * @return float
635
-     * @throws \EE_Error
636
-     */
637
-    public function process_registration_refund(
638
-        EE_Registration $registration,
639
-        EE_Payment $payment,
640
-        $available_refund_amount = 0.00
641
-    ) {
642
-        //EEH_Debug_Tools::printr( $payment->amount(), '$payment->amount()', __FILE__, __LINE__ );
643
-        if ($registration->paid() > 0) {
644
-            // ensure $available_refund_amount is NOT negative
645
-            $available_refund_amount = (float)abs($available_refund_amount);
646
-            // don't allow refund amount to exceed the available payment amount, OR the amount paid
647
-            $refund_amount = min($available_refund_amount, (float)$registration->paid());
648
-            // update $available_payment_amount
649
-            $available_refund_amount -= $refund_amount;
650
-            //calculate and set new REG_paid
651
-            $registration->set_paid($registration->paid() - $refund_amount);
652
-            // convert payment amount back to a negative value for storage in the db
653
-            $refund_amount = (float)abs($refund_amount) * -1;
654
-            // now save it
655
-            $this->_apply_registration_payment($registration, $payment, $refund_amount);
656
-        }
657
-        return $available_refund_amount;
658
-    }
659
-
660
-
661
-
662
-    /**
663
-     * Process payments and transaction after payment process completed.
664
-     * ultimately this will send the TXN and payment details off so that notifications can be sent out.
665
-     * if this request happens to be processing an IPN,
666
-     * then we will also set the Payment Options Reg Step to completed,
667
-     * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
668
-     *
669
-     * @param EE_Transaction $transaction
670
-     * @param EE_Payment     $payment
671
-     * @param bool           $IPN
672
-     * @throws \EE_Error
673
-     */
674
-    protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
675
-    {
676
-        /** @type EE_Transaction_Processor $transaction_processor */
677
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
678
-        // is the Payment Options Reg Step completed ?
679
-        $payment_options_step_completed = $transaction->reg_step_completed('payment_options');
680
-        // if the Payment Options Reg Step is completed...
681
-        $revisit = $payment_options_step_completed === true ? true : false;
682
-        // then this is kinda sorta a revisit with regards to payments at least
683
-        $transaction_processor->set_revisit($revisit);
684
-        // if this is an IPN, let's consider the Payment Options Reg Step completed if not already
685
-        if (
686
-            $IPN
687
-            && $payment_options_step_completed !== true
688
-            && ($payment->is_approved() || $payment->is_pending())
689
-        ) {
690
-            $payment_options_step_completed = $transaction->set_reg_step_completed(
691
-                'payment_options'
692
-            );
693
-        }
694
-        // maybe update status, but don't save transaction just yet
695
-        $transaction->update_status_based_on_total_paid(false);
696
-        // check if 'finalize_registration' step has been completed...
697
-        $finalized = $transaction->reg_step_completed('finalize_registration');
698
-        //  if this is an IPN and the final step has not been initiated
699
-        if ($IPN && $payment_options_step_completed && $finalized === false) {
700
-            // and if it hasn't already been set as being started...
701
-            $finalized = $transaction->set_reg_step_initiated('finalize_registration');
702
-        }
703
-        $transaction->save();
704
-        // because the above will return false if the final step was not fully completed, we need to check again...
705
-        if ($IPN && $finalized !== false) {
706
-            // and if we are all good to go, then send out notifications
707
-            add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
708
-            //ok, now process the transaction according to the payment
709
-            $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($transaction, $payment);
710
-        }
711
-        // DEBUG LOG
712
-        $payment_method = $payment->payment_method();
713
-        if ($payment_method instanceof EE_Payment_Method) {
714
-            $payment_method_type_obj = $payment_method->type_obj();
715
-            if ($payment_method_type_obj instanceof EE_PMT_Base) {
716
-                $gateway = $payment_method_type_obj->get_gateway();
717
-                if ($gateway instanceof EE_Gateway) {
718
-                    $gateway->log(
719
-                        array(
720
-                            'message'               => __('Post Payment Transaction Details', 'event_espresso'),
721
-                            'transaction'           => $transaction->model_field_array(),
722
-                            'finalized'             => $finalized,
723
-                            'IPN'                   => $IPN,
724
-                            'deliver_notifications' => has_filter(
725
-                                'FHEE__EED_Messages___maybe_registration__deliver_notifications'
726
-                            ),
727
-                        ),
728
-                        $payment
729
-                    );
730
-                }
731
-            }
732
-        }
733
-    }
734
-
735
-
736
-
737
-    /**
738
-     * Force posts to PayPal to use TLS v1.2. See:
739
-     * https://core.trac.wordpress.org/ticket/36320
740
-     * https://core.trac.wordpress.org/ticket/34924#comment:15
741
-     * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
742
-     * This will affect paypal standard, pro, express, and payflow.
743
-     */
744
-    public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
745
-    {
746
-        if (strstr($url, 'https://') && strstr($url, '.paypal.com')) {
747
-            //Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
748
-            //instead of the constant because it might not be defined
749
-            curl_setopt($handle, CURLOPT_SSLVERSION, 1);
750
-        }
751
-    }
19
+	/**
20
+	 * @var EE_Payment_Processor $_instance
21
+	 * @access    private
22
+	 */
23
+	private static $_instance;
24
+
25
+
26
+
27
+	/**
28
+	 * @singleton method used to instantiate class object
29
+	 * @access    public
30
+	 * @return EE_Payment_Processor instance
31
+	 */
32
+	public static function instance()
33
+	{
34
+		// check if class object is instantiated
35
+		if ( ! self::$_instance instanceof EE_Payment_Processor) {
36
+			self::$_instance = new self();
37
+		}
38
+		return self::$_instance;
39
+	}
40
+
41
+
42
+
43
+	/**
44
+	 *private constructor to prevent direct creation
45
+	 *
46
+	 * @Constructor
47
+	 * @access private
48
+	 */
49
+	private function __construct()
50
+	{
51
+		do_action('AHEE__EE_Payment_Processor__construct');
52
+		add_action('http_api_curl', array($this, '_curl_requests_to_paypal_use_tls'), 10, 3);
53
+	}
54
+
55
+
56
+
57
+	/**
58
+	 * Using the selected gateway, processes the payment for that transaction, and updates the transaction
59
+	 * appropriately. Saves the payment that is generated
60
+	 *
61
+	 * @param EE_Payment_Method    $payment_method
62
+	 * @param EE_Transaction       $transaction
63
+	 * @param float                $amount       if only part of the transaction is to be paid for, how much.
64
+	 *                                           Leave null if payment is for the full amount owing
65
+	 * @param EE_Billing_Info_Form $billing_form (or probably null, if it's an offline or offsite payment method).
66
+	 *                                           Receive_form_submission() should have
67
+	 *                                           already been called on the billing form
68
+	 *                                           (ie, its inputs should have their normalized values set).
69
+	 * @param string               $return_url   string used mostly by offsite gateways to specify
70
+	 *                                           where to go AFTER the offsite gateway
71
+	 * @param string               $method       like 'CART', indicates who the client who called this was
72
+	 * @param bool                 $by_admin     TRUE if payment is being attempted from the admin
73
+	 * @param boolean              $update_txn   whether or not to call
74
+	 *                                           EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
75
+	 * @param string               $cancel_url   URL to return to if off-site payments are cancelled
76
+	 * @return \EE_Payment
77
+	 * @throws \EE_Error
78
+	 */
79
+	public function process_payment(
80
+		EE_Payment_Method $payment_method,
81
+		EE_Transaction $transaction,
82
+		$amount = null,
83
+		$billing_form = null,
84
+		$return_url = null,
85
+		$method = 'CART',
86
+		$by_admin = false,
87
+		$update_txn = true,
88
+		$cancel_url = ''
89
+	) {
90
+		if ((float)$amount < 0) {
91
+			throw new EE_Error(
92
+				sprintf(
93
+					__(
94
+						'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
95
+						'event_espresso'
96
+					),
97
+					$amount,
98
+					$transaction->ID()
99
+				)
100
+			);
101
+		}
102
+		// verify payment method
103
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
104
+		// verify transaction
105
+		EEM_Transaction::instance()->ensure_is_obj($transaction);
106
+		$transaction->set_payment_method_ID($payment_method->ID());
107
+		// verify payment method type
108
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
109
+			$payment = $payment_method->type_obj()->process_payment(
110
+				$transaction,
111
+				min($amount, $transaction->remaining()),//make sure we don't overcharge
112
+				$billing_form,
113
+				$return_url,
114
+				add_query_arg(array('ee_cancel_payment' => true), $cancel_url),
115
+				$method,
116
+				$by_admin
117
+			);
118
+			// check if payment method uses an off-site gateway
119
+			if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
120
+				// don't process payments for off-site gateways yet because no payment has occurred yet
121
+				$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
122
+			}
123
+			return $payment;
124
+		} else {
125
+			EE_Error::add_error(
126
+				sprintf(
127
+					__('A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.', 'event_espresso'),
128
+					'<br/>',
129
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
130
+				), __FILE__, __FUNCTION__, __LINE__
131
+			);
132
+			return null;
133
+		}
134
+	}
135
+
136
+
137
+
138
+	/**
139
+	 * @param EE_Transaction|int $transaction
140
+	 * @param EE_Payment_Method  $payment_method
141
+	 * @throws EE_Error
142
+	 * @return string
143
+	 */
144
+	public function get_ipn_url_for_payment_method($transaction, $payment_method)
145
+	{
146
+		/** @type \EE_Transaction $transaction */
147
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
148
+		$primary_reg = $transaction->primary_registration();
149
+		if ( ! $primary_reg instanceof EE_Registration) {
150
+			throw new EE_Error(
151
+				sprintf(
152
+					__(
153
+						"Cannot get IPN URL for transaction with ID %d because it has no primary registration",
154
+						"event_espresso"
155
+					),
156
+					$transaction->ID()
157
+				)
158
+			);
159
+		}
160
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
161
+		$url = add_query_arg(
162
+			array(
163
+				'e_reg_url_link'    => $primary_reg->reg_url_link(),
164
+				'ee_payment_method' => $payment_method->slug(),
165
+			),
166
+			EE_Registry::instance()->CFG->core->txn_page_url()
167
+		);
168
+		return $url;
169
+	}
170
+
171
+
172
+
173
+	/**
174
+	 * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
175
+	 * we can easily find what registration the IPN is for and what payment method.
176
+	 * However, if not, we'll give all payment methods a chance to claim it and process it.
177
+	 * If a payment is found for the IPN info, it is saved.
178
+	 *
179
+	 * @param array              $_req_data            eg $_REQUEST
180
+	 * @param EE_Transaction|int $transaction          optional (or a transactions id)
181
+	 * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
182
+	 * @param boolean            $update_txn           whether or not to call
183
+	 *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
184
+	 * @param bool               $separate_IPN_request whether the IPN uses a separate request ( true like PayPal )
185
+	 *                                                 or is processed manually ( false like Mijireh )
186
+	 * @throws EE_Error
187
+	 * @throws Exception
188
+	 * @return EE_Payment
189
+	 */
190
+	public function process_ipn(
191
+		$_req_data,
192
+		$transaction = null,
193
+		$payment_method = null,
194
+		$update_txn = true,
195
+		$separate_IPN_request = true
196
+	) {
197
+		EE_Registry::instance()->load_model('Change_Log');
198
+		$_req_data = $this->_remove_unusable_characters_from_array((array)$_req_data);
199
+		EE_Processor_Base::set_IPN($separate_IPN_request);
200
+		$obj_for_log = null;
201
+		if ($transaction instanceof EE_Transaction) {
202
+			$obj_for_log = $transaction;
203
+			if ($payment_method instanceof EE_Payment_Method) {
204
+				$obj_for_log = EEM_Payment::instance()->get_one(
205
+					array(
206
+						array('TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()),
207
+						'order_by' => array('PAY_timestamp' => 'desc'),
208
+					)
209
+				);
210
+			}
211
+		} else if ($payment_method instanceof EE_Payment) {
212
+			$obj_for_log = $payment_method;
213
+		}
214
+		$log = EEM_Change_Log::instance()->log(
215
+			EEM_Change_Log::type_gateway,
216
+			array('IPN data received' => $_req_data),
217
+			$obj_for_log
218
+		);
219
+		try {
220
+			/**
221
+			 * @var EE_Payment $payment
222
+			 */
223
+			$payment = null;
224
+			if ($transaction && $payment_method) {
225
+				/** @type EE_Transaction $transaction */
226
+				$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
227
+				/** @type EE_Payment_Method $payment_method */
228
+				$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
229
+				if ($payment_method->type_obj() instanceof EE_PMT_Base) {
230
+					try {
231
+						$payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
232
+						$log->set_object($payment);
233
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
234
+						EEM_Change_Log::instance()->log(
235
+							EEM_Change_Log::type_gateway,
236
+							array(
237
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
238
+								'current_url' => EEH_URL::current_url(),
239
+								'payment'     => $e->getPaymentProperties(),
240
+								'IPN_data'    => $e->getIpnData(),
241
+							),
242
+							$obj_for_log
243
+						);
244
+						return $e->getPayment();
245
+					}
246
+				} else {
247
+					// not a payment
248
+					EE_Error::add_error(
249
+						sprintf(
250
+							__('A valid payment method could not be determined due to a technical issue.%sPlease refresh your browser and try again or contact %s for assistance.', 'event_espresso'),
251
+							'<br/>',
252
+							EE_Registry::instance()->CFG->organization->get_pretty('email')
253
+						),
254
+						__FILE__, __FUNCTION__, __LINE__
255
+					);
256
+				}
257
+			} else {
258
+				//that's actually pretty ok. The IPN just wasn't able
259
+				//to identify which transaction or payment method this was for
260
+				// give all active payment methods a chance to claim it
261
+				$active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
262
+				foreach ($active_payment_methods as $active_payment_method) {
263
+					try {
264
+						$payment = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
265
+						$payment_method = $active_payment_method;
266
+						EEM_Change_Log::instance()->log(
267
+							EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment
268
+						);
269
+						break;
270
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
271
+						EEM_Change_Log::instance()->log(
272
+							EEM_Change_Log::type_gateway,
273
+							array(
274
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
275
+								'current_url' => EEH_URL::current_url(),
276
+								'payment'     => $e->getPaymentProperties(),
277
+								'IPN_data'    => $e->getIpnData(),
278
+							),
279
+							$obj_for_log
280
+						);
281
+						return $e->getPayment();
282
+					} catch (EE_Error $e) {
283
+						//that's fine- it apparently couldn't handle the IPN
284
+					}
285
+				}
286
+			}
287
+			// 			EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
288
+			if ($payment instanceof EE_Payment) {
289
+				$payment->save();
290
+				//  update the TXN
291
+				$this->update_txn_based_on_payment($transaction, $payment, $update_txn, $separate_IPN_request);
292
+			} else {
293
+				//we couldn't find the payment for this IPN... let's try and log at least SOMETHING
294
+				if ($payment_method) {
295
+					EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment_method);
296
+				} elseif ($transaction) {
297
+					EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $transaction);
298
+				}
299
+			}
300
+			return $payment;
301
+		} catch (EE_Error $e) {
302
+			do_action(
303
+				'AHEE__log', __FILE__, __FUNCTION__, sprintf(
304
+					__('Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"', 'event_espresso'),
305
+					print_r($transaction, true),
306
+					print_r($_req_data, true),
307
+					$e->getMessage()
308
+				)
309
+			);
310
+			throw $e;
311
+		}
312
+	}
313
+
314
+
315
+
316
+	/**
317
+	 * Removes any non-printable illegal characters from the input,
318
+	 * which might cause a raucous when trying to insert into the database
319
+	 *
320
+	 * @param  array $request_data
321
+	 * @return array
322
+	 */
323
+	protected function _remove_unusable_characters_from_array(array $request_data)
324
+	{
325
+		$return_data = array();
326
+		foreach ($request_data as $key => $value) {
327
+			$return_data[$this->_remove_unusable_characters($key)] = $this->_remove_unusable_characters($value);
328
+		}
329
+		return $return_data;
330
+	}
331
+
332
+
333
+
334
+	/**
335
+	 * Removes any non-printable illegal characters from the input,
336
+	 * which might cause a raucous when trying to insert into the database
337
+	 *
338
+	 * @param string $request_data
339
+	 * @return string
340
+	 */
341
+	protected function _remove_unusable_characters($request_data)
342
+	{
343
+		return preg_replace('/[^[:print:]]/', '', $request_data);
344
+	}
345
+
346
+
347
+
348
+	/**
349
+	 * Should be called just before displaying the payment attempt results to the user,
350
+	 * when the payment attempt has finished. Some payment methods may have special
351
+	 * logic to perform here. For example, if process_payment() happens on a special request
352
+	 * and then the user is redirected to a page that displays the payment's status, this
353
+	 * should be called while loading the page that displays the payment's status. If the user is
354
+	 * sent to an offsite payment provider, this should be called upon returning from that offsite payment
355
+	 * provider.
356
+	 *
357
+	 * @param EE_Transaction|int $transaction
358
+	 * @param bool               $update_txn whether or not to call
359
+	 *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
360
+	 * @throws \EE_Error
361
+	 * @return EE_Payment
362
+	 * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
363
+	 *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
364
+	 */
365
+	public function finalize_payment_for($transaction, $update_txn = true)
366
+	{
367
+		/** @var $transaction EE_Transaction */
368
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
369
+		$last_payment_method = $transaction->payment_method();
370
+		if ($last_payment_method instanceof EE_Payment_Method) {
371
+			$payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
372
+			$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
373
+			return $payment;
374
+		} else {
375
+			return null;
376
+		}
377
+	}
378
+
379
+
380
+
381
+	/**
382
+	 * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
383
+	 *
384
+	 * @param EE_Payment_Method $payment_method
385
+	 * @param EE_Payment        $payment_to_refund
386
+	 * @param array             $refund_info
387
+	 * @return EE_Payment
388
+	 * @throws \EE_Error
389
+	 */
390
+	public function process_refund(
391
+		EE_Payment_Method $payment_method,
392
+		EE_Payment $payment_to_refund,
393
+		$refund_info = array()
394
+	) {
395
+		if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
396
+			$payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
397
+			$this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
398
+		}
399
+		return $payment_to_refund;
400
+	}
401
+
402
+
403
+
404
+	/**
405
+	 * This should be called each time there may have been an update to a
406
+	 * payment on a transaction (ie, we asked for a payment to process a
407
+	 * payment for a transaction, or we told a payment method about an IPN, or
408
+	 * we told a payment method to
409
+	 * "finalize_payment_for" (a transaction), or we told a payment method to
410
+	 * process a refund. This should handle firing the correct hooks to
411
+	 * indicate
412
+	 * what exactly happened and updating the transaction appropriately). This
413
+	 * could be integrated directly into EE_Transaction upon save, but we want
414
+	 * this logic to be separate from 'normal' plain-jane saving and updating
415
+	 * of transactions and payments, and to be tied to payment processing.
416
+	 * Note: this method DOES NOT save the payment passed into it. It is the responsibility
417
+	 * of previous code to decide whether or not to save (because the payment passed into
418
+	 * this method might be a temporary, never-to-be-saved payment from an offline gateway,
419
+	 * in which case we only want that payment object for some temporary usage during this request,
420
+	 * but we don't want it to be saved).
421
+	 *
422
+	 * @param EE_Transaction|int $transaction
423
+	 * @param EE_Payment         $payment
424
+	 * @param boolean            $update_txn
425
+	 *                        whether or not to call
426
+	 *                        EE_Transaction_Processor::
427
+	 *                        update_transaction_and_registrations_after_checkout_or_payment()
428
+	 *                        (you can save 1 DB query if you know you're going
429
+	 *                        to save it later instead)
430
+	 * @param bool               $IPN
431
+	 *                        if processing IPNs or other similar payment
432
+	 *                        related activities that occur in alternate
433
+	 *                        requests than the main one that is processing the
434
+	 *                        TXN, then set this to true to check whether the
435
+	 *                        TXN is locked before updating
436
+	 * @throws \EE_Error
437
+	 */
438
+	public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
439
+	{
440
+		$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
441
+		/** @type EE_Transaction $transaction */
442
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
443
+		// can we freely update the TXN at this moment?
444
+		if ($IPN && $transaction->is_locked()) {
445
+			// don't update the transaction at this exact moment
446
+			// because the TXN is active in another request
447
+			EE_Cron_Tasks::schedule_update_transaction_with_payment(
448
+				time(),
449
+				$transaction->ID(),
450
+				$payment->ID()
451
+			);
452
+		} else {
453
+			// verify payment and that it has been saved
454
+			if ($payment instanceof EE_Payment && $payment->ID()) {
455
+				if (
456
+					$payment->payment_method() instanceof EE_Payment_Method
457
+					&& $payment->payment_method()->type_obj() instanceof EE_PMT_Base
458
+				) {
459
+					$payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
460
+					// update TXN registrations with payment info
461
+					$this->process_registration_payments($transaction, $payment);
462
+				}
463
+				$do_action = $payment->just_approved()
464
+					? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
465
+					: $do_action;
466
+			} else {
467
+				// send out notifications
468
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
469
+				$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
470
+			}
471
+			if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
472
+				/** @type EE_Transaction_Payments $transaction_payments */
473
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
474
+				// set new value for total paid
475
+				$transaction_payments->calculate_total_payments_and_update_status($transaction);
476
+				// call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
477
+				if ($update_txn) {
478
+					$this->_post_payment_processing($transaction, $payment, $IPN);
479
+				}
480
+			}
481
+			// granular hook for others to use.
482
+			do_action($do_action, $transaction, $payment);
483
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
484
+			//global hook for others to use.
485
+			do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
486
+		}
487
+	}
488
+
489
+
490
+
491
+	/**
492
+	 * update registrations REG_paid field after successful payment and link registrations with payment
493
+	 *
494
+	 * @param EE_Transaction    $transaction
495
+	 * @param EE_Payment        $payment
496
+	 * @param EE_Registration[] $registrations
497
+	 * @throws \EE_Error
498
+	 */
499
+	public function process_registration_payments(
500
+		EE_Transaction $transaction,
501
+		EE_Payment $payment,
502
+		$registrations = array()
503
+	) {
504
+		// only process if payment was successful
505
+		if ($payment->status() !== EEM_Payment::status_id_approved) {
506
+			return;
507
+		}
508
+		//EEM_Registration::instance()->show_next_x_db_queries();
509
+		if (empty($registrations)) {
510
+			// find registrations with monies owing that can receive a payment
511
+			$registrations = $transaction->registrations(
512
+				array(
513
+					array(
514
+						// only these reg statuses can receive payments
515
+						'STS_ID'           => array('IN', EEM_Registration::reg_statuses_that_allow_payment()),
516
+						'REG_final_price'  => array('!=', 0),
517
+						'REG_final_price*' => array('!=', 'REG_paid', true),
518
+					),
519
+				)
520
+			);
521
+		}
522
+		// still nothing ??!??
523
+		if (empty($registrations)) {
524
+			return;
525
+		}
526
+		// todo: break out the following logic into a separate strategy class
527
+		// todo: named something like "Sequential_Reg_Payment_Strategy"
528
+		// todo: which would apply payments using the capitalist "first come first paid" approach
529
+		// todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
530
+		// todo: which would be the socialist "everybody gets a piece of pie" approach,
531
+		// todo: which would be better for deposits, where you want a bit of the payment applied to each registration
532
+		$refund = $payment->is_a_refund();
533
+		// how much is available to apply to registrations?
534
+		$available_payment_amount = abs($payment->amount());
535
+		foreach ($registrations as $registration) {
536
+			if ($registration instanceof EE_Registration) {
537
+				// nothing left?
538
+				if ($available_payment_amount <= 0) {
539
+					break;
540
+				}
541
+				if ($refund) {
542
+					$available_payment_amount = $this->process_registration_refund($registration, $payment, $available_payment_amount);
543
+				} else {
544
+					$available_payment_amount = $this->process_registration_payment($registration, $payment, $available_payment_amount);
545
+				}
546
+			}
547
+		}
548
+		if ($available_payment_amount > 0 && apply_filters('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', false)) {
549
+			EE_Error::add_attention(
550
+				sprintf(
551
+					__('A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
552
+						'event_espresso'),
553
+					EEH_Template::format_currency($available_payment_amount),
554
+					implode(', ', array_keys($registrations)),
555
+					'<br/>',
556
+					EEH_Template::format_currency($payment->amount())
557
+				),
558
+				__FILE__, __FUNCTION__, __LINE__
559
+			);
560
+		}
561
+	}
562
+
563
+
564
+
565
+	/**
566
+	 * update registration REG_paid field after successful payment and link registration with payment
567
+	 *
568
+	 * @param EE_Registration $registration
569
+	 * @param EE_Payment      $payment
570
+	 * @param float           $available_payment_amount
571
+	 * @return float
572
+	 * @throws \EE_Error
573
+	 */
574
+	public function process_registration_payment(
575
+		EE_Registration $registration,
576
+		EE_Payment $payment,
577
+		$available_payment_amount = 0.00
578
+	) {
579
+		$owing = $registration->final_price() - $registration->paid();
580
+		if ($owing > 0) {
581
+			// don't allow payment amount to exceed the available payment amount, OR the amount owing
582
+			$payment_amount = min($available_payment_amount, $owing);
583
+			// update $available_payment_amount
584
+			$available_payment_amount -= $payment_amount;
585
+			//calculate and set new REG_paid
586
+			$registration->set_paid($registration->paid() + $payment_amount);
587
+			// now save it
588
+			$this->_apply_registration_payment($registration, $payment, $payment_amount);
589
+		}
590
+		return $available_payment_amount;
591
+	}
592
+
593
+
594
+
595
+	/**
596
+	 * update registration REG_paid field after successful payment and link registration with payment
597
+	 *
598
+	 * @param EE_Registration $registration
599
+	 * @param EE_Payment      $payment
600
+	 * @param float           $payment_amount
601
+	 * @return void
602
+	 * @throws \EE_Error
603
+	 */
604
+	protected function _apply_registration_payment(
605
+		EE_Registration $registration,
606
+		EE_Payment $payment,
607
+		$payment_amount = 0.00
608
+	) {
609
+		// find any existing reg payment records for this registration and payment
610
+		$existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
611
+			array(array('REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()))
612
+		);
613
+		// if existing registration payment exists
614
+		if ($existing_reg_payment instanceof EE_Registration_Payment) {
615
+			// then update that record
616
+			$existing_reg_payment->set_amount($payment_amount);
617
+			$existing_reg_payment->save();
618
+		} else {
619
+			// or add new relation between registration and payment and set amount
620
+			$registration->_add_relation_to($payment, 'Payment', array('RPY_amount' => $payment_amount));
621
+			// make it stick
622
+			$registration->save();
623
+		}
624
+	}
625
+
626
+
627
+
628
+	/**
629
+	 * update registration REG_paid field after refund and link registration with payment
630
+	 *
631
+	 * @param EE_Registration $registration
632
+	 * @param EE_Payment      $payment
633
+	 * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
634
+	 * @return float
635
+	 * @throws \EE_Error
636
+	 */
637
+	public function process_registration_refund(
638
+		EE_Registration $registration,
639
+		EE_Payment $payment,
640
+		$available_refund_amount = 0.00
641
+	) {
642
+		//EEH_Debug_Tools::printr( $payment->amount(), '$payment->amount()', __FILE__, __LINE__ );
643
+		if ($registration->paid() > 0) {
644
+			// ensure $available_refund_amount is NOT negative
645
+			$available_refund_amount = (float)abs($available_refund_amount);
646
+			// don't allow refund amount to exceed the available payment amount, OR the amount paid
647
+			$refund_amount = min($available_refund_amount, (float)$registration->paid());
648
+			// update $available_payment_amount
649
+			$available_refund_amount -= $refund_amount;
650
+			//calculate and set new REG_paid
651
+			$registration->set_paid($registration->paid() - $refund_amount);
652
+			// convert payment amount back to a negative value for storage in the db
653
+			$refund_amount = (float)abs($refund_amount) * -1;
654
+			// now save it
655
+			$this->_apply_registration_payment($registration, $payment, $refund_amount);
656
+		}
657
+		return $available_refund_amount;
658
+	}
659
+
660
+
661
+
662
+	/**
663
+	 * Process payments and transaction after payment process completed.
664
+	 * ultimately this will send the TXN and payment details off so that notifications can be sent out.
665
+	 * if this request happens to be processing an IPN,
666
+	 * then we will also set the Payment Options Reg Step to completed,
667
+	 * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
668
+	 *
669
+	 * @param EE_Transaction $transaction
670
+	 * @param EE_Payment     $payment
671
+	 * @param bool           $IPN
672
+	 * @throws \EE_Error
673
+	 */
674
+	protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
675
+	{
676
+		/** @type EE_Transaction_Processor $transaction_processor */
677
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
678
+		// is the Payment Options Reg Step completed ?
679
+		$payment_options_step_completed = $transaction->reg_step_completed('payment_options');
680
+		// if the Payment Options Reg Step is completed...
681
+		$revisit = $payment_options_step_completed === true ? true : false;
682
+		// then this is kinda sorta a revisit with regards to payments at least
683
+		$transaction_processor->set_revisit($revisit);
684
+		// if this is an IPN, let's consider the Payment Options Reg Step completed if not already
685
+		if (
686
+			$IPN
687
+			&& $payment_options_step_completed !== true
688
+			&& ($payment->is_approved() || $payment->is_pending())
689
+		) {
690
+			$payment_options_step_completed = $transaction->set_reg_step_completed(
691
+				'payment_options'
692
+			);
693
+		}
694
+		// maybe update status, but don't save transaction just yet
695
+		$transaction->update_status_based_on_total_paid(false);
696
+		// check if 'finalize_registration' step has been completed...
697
+		$finalized = $transaction->reg_step_completed('finalize_registration');
698
+		//  if this is an IPN and the final step has not been initiated
699
+		if ($IPN && $payment_options_step_completed && $finalized === false) {
700
+			// and if it hasn't already been set as being started...
701
+			$finalized = $transaction->set_reg_step_initiated('finalize_registration');
702
+		}
703
+		$transaction->save();
704
+		// because the above will return false if the final step was not fully completed, we need to check again...
705
+		if ($IPN && $finalized !== false) {
706
+			// and if we are all good to go, then send out notifications
707
+			add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
708
+			//ok, now process the transaction according to the payment
709
+			$transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($transaction, $payment);
710
+		}
711
+		// DEBUG LOG
712
+		$payment_method = $payment->payment_method();
713
+		if ($payment_method instanceof EE_Payment_Method) {
714
+			$payment_method_type_obj = $payment_method->type_obj();
715
+			if ($payment_method_type_obj instanceof EE_PMT_Base) {
716
+				$gateway = $payment_method_type_obj->get_gateway();
717
+				if ($gateway instanceof EE_Gateway) {
718
+					$gateway->log(
719
+						array(
720
+							'message'               => __('Post Payment Transaction Details', 'event_espresso'),
721
+							'transaction'           => $transaction->model_field_array(),
722
+							'finalized'             => $finalized,
723
+							'IPN'                   => $IPN,
724
+							'deliver_notifications' => has_filter(
725
+								'FHEE__EED_Messages___maybe_registration__deliver_notifications'
726
+							),
727
+						),
728
+						$payment
729
+					);
730
+				}
731
+			}
732
+		}
733
+	}
734
+
735
+
736
+
737
+	/**
738
+	 * Force posts to PayPal to use TLS v1.2. See:
739
+	 * https://core.trac.wordpress.org/ticket/36320
740
+	 * https://core.trac.wordpress.org/ticket/34924#comment:15
741
+	 * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
742
+	 * This will affect paypal standard, pro, express, and payflow.
743
+	 */
744
+	public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
745
+	{
746
+		if (strstr($url, 'https://') && strstr($url, '.paypal.com')) {
747
+			//Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
748
+			//instead of the constant because it might not be defined
749
+			curl_setopt($handle, CURLOPT_SSLVERSION, 1);
750
+		}
751
+	}
752 752
 }
Please login to merge, or discard this patch.
core/libraries/payment_methods/EEI_Payment_Method_Interfaces.php 1 patch
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -5,7 +5,7 @@  discard block
 block discarded – undo
5 5
  *
6 6
  * allows gateways to be used by different systems other than Event Espresso
7 7
  */
8
-interface EEI_Payment extends EEI_Base{
8
+interface EEI_Payment extends EEI_Base {
9 9
 
10 10
 	/**
11 11
 	 * @return string indicating which the payment is approved, pending, cancelled or failed
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
 /**
154 154
  * Interface EEI_Payment_Method
155 155
  */
156
-interface EEI_Payment_Method{
156
+interface EEI_Payment_Method {
157 157
 
158 158
 }
159 159
 
@@ -172,7 +172,7 @@  discard block
 block discarded – undo
172 172
 	 * @param string $model_name
173 173
 	 * @return EE_Log
174 174
 	 */
175
-	public function gateway_log($message,$id,$model_name);
175
+	public function gateway_log($message, $id, $model_name);
176 176
 }
177 177
 
178 178
 
Please login to merge, or discard this patch.
payment_methods/Paypal_Express/EEG_Paypal_Express.gateway.php 2 patches
Indentation   +98 added lines, -100 removed lines patch added patch discarded remove patch
@@ -44,77 +44,76 @@  discard block
 block discarded – undo
44 44
 	 */
45 45
 	protected $_image_url;
46 46
 
47
-    /**
48
-     * gateway URL variable
49
-     *
50
-     * @var string
51
-     */
52
-    protected $_base_gateway_url = '';
53
-
54
-
55
-
56
-    /**
57
-     * EEG_Paypal_Express constructor.
58
-     */
59
-    public function __construct()
60
-    {
61
-        $this->_currencies_supported = array(
62
-            'USD',
63
-            'AUD',
64
-            'BRL',
65
-            'CAD',
66
-            'CZK',
67
-            'DKK',
68
-            'EUR',
69
-            'HKD',
70
-            'HUF',
71
-            'ILS',
72
-            'JPY',
73
-            'MYR',
74
-            'MXN',
75
-            'NOK',
76
-            'NZD',
77
-            'PHP',
78
-            'PLN',
79
-            'GBP',
80
-            'RUB',
81
-            'SGD',
82
-            'SEK',
83
-            'CHF',
84
-            'TWD',
85
-            'THB',
86
-            'TRY'
87
-        );
88
-        parent::__construct();
89
-    }
90
-
91
-
92
-
93
-    /**
94
-	 * Sets the gateway URL variable based on whether debug mode is enabled or not.
47
+	/**
48
+	 * gateway URL variable
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $_base_gateway_url = '';
53
+
54
+
55
+
56
+	/**
57
+	 * EEG_Paypal_Express constructor.
58
+	 */
59
+	public function __construct()
60
+	{
61
+		$this->_currencies_supported = array(
62
+			'USD',
63
+			'AUD',
64
+			'BRL',
65
+			'CAD',
66
+			'CZK',
67
+			'DKK',
68
+			'EUR',
69
+			'HKD',
70
+			'HUF',
71
+			'ILS',
72
+			'JPY',
73
+			'MYR',
74
+			'MXN',
75
+			'NOK',
76
+			'NZD',
77
+			'PHP',
78
+			'PLN',
79
+			'GBP',
80
+			'RUB',
81
+			'SGD',
82
+			'SEK',
83
+			'CHF',
84
+			'TWD',
85
+			'THB',
86
+			'TRY'
87
+		);
88
+		parent::__construct();
89
+	}
90
+
95 91
 
92
+
93
+	/**
94
+	 * Sets the gateway URL variable based on whether debug mode is enabled or not.
96 95
 	 *
97 96
 *@param array $settings_array
98 97
 	 */
99 98
 	public function set_settings( $settings_array ) {
100 99
 		parent::set_settings($settings_array);
101 100
 		// Redirect URL.
102
-        $this->_base_gateway_url = $this->_debug_mode
103
-            ? 'https://api-3t.sandbox.paypal.com/nvp'
104
-            : 'https://api-3t.paypal.com/nvp';
101
+		$this->_base_gateway_url = $this->_debug_mode
102
+			? 'https://api-3t.sandbox.paypal.com/nvp'
103
+			: 'https://api-3t.paypal.com/nvp';
105 104
 	}
106 105
 
107 106
 
108 107
 
109
-    /**
110
-     * @param EEI_Payment $payment
111
-     * @param array       $billing_info
112
-     * @param string      $return_url
113
-     * @param string      $notify_url
114
-     * @param string      $cancel_url
115
-     * @return \EE_Payment|\EEI_Payment
116
-     * @throws \EE_Error
117
-     */
108
+	/**
109
+	 * @param EEI_Payment $payment
110
+	 * @param array       $billing_info
111
+	 * @param string      $return_url
112
+	 * @param string      $notify_url
113
+	 * @param string      $cancel_url
114
+	 * @return \EE_Payment|\EEI_Payment
115
+	 * @throws \EE_Error
116
+	 */
118 117
 	public function set_redirection_info( $payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL ) {
119 118
 		if ( ! $payment instanceof EEI_Payment ) {
120 119
 			$payment->set_gateway_response( __( 'Error. No associated payment was found.', 'event_espresso' ) );
@@ -202,9 +201,9 @@  discard block
 block discarded – undo
202 201
 				$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER'.$item_num] = $item_num + 1;
203 202
 				// Item quantity.
204 203
 				$token_request_dtls['L_PAYMENTREQUEST_0_QTY'.$item_num] = 1;
205
-                // Digital item is sold.
206
-                $token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY'.$item_num] = 'Physical';
207
-                $item_num++;
204
+				// Digital item is sold.
205
+				$token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY'.$item_num] = 'Physical';
206
+				$item_num++;
208 207
 			}
209 208
 		} else {
210 209
 			// Just one Item.
@@ -272,7 +271,6 @@  discard block
 block discarded – undo
272 271
 
273 272
 
274 273
 	/**
275
-
276 274
 	 *  @param array $update_info {
277 275
 	 *	  @type string $gateway_txn_id
278 276
 	 *	  @type string status an EEMI_Payment status
@@ -292,8 +290,8 @@  discard block
 block discarded – undo
292 290
 				return $payment;
293 291
 			}
294 292
 			$primary_registrant = $transaction->primary_registration();
295
-            $payment_details = $payment->details();
296
-            // Check if we still have the token.
293
+			$payment_details = $payment->details();
294
+			// Check if we still have the token.
297 295
 			if ( ! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN']) ) {
298 296
 				$payment->set_status( $this->_pay_model->failed_status() );
299 297
 				return $payment;
@@ -402,36 +400,36 @@  discard block
 block discarded – undo
402 400
 	 */
403 401
 	public function _ppExpress_check_response( $request_response ) {
404 402
 		if (empty($request_response['body']) || is_wp_error( $request_response ) ) {
405
-            // If we got here then there was an error in this request.
406
-            return array('status' => false, 'args' => $request_response);
407
-        }
408
-        $response_args = array();
409
-        parse_str( urldecode($request_response['body']), $response_args );
410
-        if ( ! isset($response_args['ACK'])) {
411
-            return array('status' => false, 'args' => $request_response);
412
-        }
413
-        if (
414
-            $response_args['ACK'] === 'Success'
415
-            && (
416
-                isset($response_args['PAYERID'])
417
-                || isset($response_args['PAYMENTINFO_0_TRANSACTIONID'])
418
-                || (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed')
419
-                || isset($response_args['TOKEN'])
420
-            )
421
-        ) {
422
-            // Response status OK, return response parameters for further processing.
423
-            return array('status' => true, 'args' => $response_args);
424
-        } else {
425
-            $errors = $this->_get_errors($response_args);
426
-            return array('status' => false, 'args' => $errors);
427
-        }
403
+			// If we got here then there was an error in this request.
404
+			return array('status' => false, 'args' => $request_response);
405
+		}
406
+		$response_args = array();
407
+		parse_str( urldecode($request_response['body']), $response_args );
408
+		if ( ! isset($response_args['ACK'])) {
409
+			return array('status' => false, 'args' => $request_response);
410
+		}
411
+		if (
412
+			$response_args['ACK'] === 'Success'
413
+			&& (
414
+				isset($response_args['PAYERID'])
415
+				|| isset($response_args['PAYMENTINFO_0_TRANSACTIONID'])
416
+				|| (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed')
417
+				|| isset($response_args['TOKEN'])
418
+			)
419
+		) {
420
+			// Response status OK, return response parameters for further processing.
421
+			return array('status' => true, 'args' => $response_args);
422
+		} else {
423
+			$errors = $this->_get_errors($response_args);
424
+			return array('status' => false, 'args' => $errors);
425
+		}
428 426
 	}
429 427
 
430 428
 
431 429
 	/**
432
-     *  Log a "Cleared" request.
433
-     *
434
-     * @param array $request
430
+	 *  Log a "Cleared" request.
431
+	 *
432
+	 * @param array $request
435 433
 	 * @param EEI_Payment  $payment
436 434
 	 * @param string  		$info
437 435
 	 * @return void
@@ -454,17 +452,17 @@  discard block
 block discarded – undo
454 452
 		$n = 0;
455 453
 		while ( isset($data_array["L_ERRORCODE{$n}"]) ) {
456 454
 			$l_error_code = isset($data_array["L_ERRORCODE{$n}"])
457
-                ? $data_array["L_ERRORCODE{$n}"]
458
-                : '';
455
+				? $data_array["L_ERRORCODE{$n}"]
456
+				: '';
459 457
 			$l_severity_code = isset($data_array["L_SEVERITYCODE{$n}"])
460
-                ? $data_array["L_SEVERITYCODE{$n}"]
461
-                : '';
458
+				? $data_array["L_SEVERITYCODE{$n}"]
459
+				: '';
462 460
 			$l_short_message = isset($data_array["L_SHORTMESSAGE{$n}"])
463
-                ? $data_array["L_SHORTMESSAGE{$n}"]
464
-                : '';
461
+				? $data_array["L_SHORTMESSAGE{$n}"]
462
+				: '';
465 463
 			$l_long_message = isset($data_array["L_LONGMESSAGE{$n}"])
466
-                ? $data_array["L_LONGMESSAGE{$n}"]
467
-                : '';
464
+				? $data_array["L_LONGMESSAGE{$n}"]
465
+				: '';
468 466
 
469 467
 			if ( $n === 0 ) {
470 468
 				$errors = array(
Please login to merge, or discard this patch.
Spacing   +97 added lines, -97 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if ( ! defined( 'EVENT_ESPRESSO_VERSION' )) { exit('NO direct script access allowed'); }
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { exit('NO direct script access allowed'); }
2 2
 
3 3
 /**
4 4
  * ----------------------------------------------
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 	 *
97 97
 *@param array $settings_array
98 98
 	 */
99
-	public function set_settings( $settings_array ) {
99
+	public function set_settings($settings_array) {
100 100
 		parent::set_settings($settings_array);
101 101
 		// Redirect URL.
102 102
         $this->_base_gateway_url = $this->_debug_mode
@@ -115,19 +115,19 @@  discard block
 block discarded – undo
115 115
      * @return \EE_Payment|\EEI_Payment
116 116
      * @throws \EE_Error
117 117
      */
118
-	public function set_redirection_info( $payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL ) {
119
-		if ( ! $payment instanceof EEI_Payment ) {
120
-			$payment->set_gateway_response( __( 'Error. No associated payment was found.', 'event_espresso' ) );
121
-			$payment->set_status( $this->_pay_model->failed_status() );
118
+	public function set_redirection_info($payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL) {
119
+		if ( ! $payment instanceof EEI_Payment) {
120
+			$payment->set_gateway_response(__('Error. No associated payment was found.', 'event_espresso'));
121
+			$payment->set_status($this->_pay_model->failed_status());
122 122
 			return $payment;
123 123
 		}
124 124
 		$transaction = $payment->transaction();
125
-		if ( ! $transaction instanceof EEI_Transaction ) {
126
-			$payment->set_gateway_response( __( 'Could not process this payment because it has no associated transaction.', 'event_espresso' ) );
127
-			$payment->set_status( $this->_pay_model->failed_status() );
125
+		if ( ! $transaction instanceof EEI_Transaction) {
126
+			$payment->set_gateway_response(__('Could not process this payment because it has no associated transaction.', 'event_espresso'));
127
+			$payment->set_status($this->_pay_model->failed_status());
128 128
 			return $payment;
129 129
 		}
130
-		$order_description = substr( $this->_format_order_description($payment), 0, 127 );
130
+		$order_description = substr($this->_format_order_description($payment), 0, 127);
131 131
 		$primary_registration = $transaction->primary_registration();
132 132
 		$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee() : false;
133 133
 		$locale = explode('-', get_bloginfo('language'));
@@ -141,37 +141,37 @@  discard block
 block discarded – undo
141 141
 			'RETURNURL' => $return_url,
142 142
 			'CANCELURL' => $cancel_url,
143 143
 			'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
144
-			'SOLUTIONTYPE' => 'Sole',	// Buyer does not need to create a PayPal account to check out. This is referred to as PayPal Account Optional.
145
-			'BUTTONSOURCE' => 'EventEspresso_SP',//EE will blow up if you change this
144
+			'SOLUTIONTYPE' => 'Sole', // Buyer does not need to create a PayPal account to check out. This is referred to as PayPal Account Optional.
145
+			'BUTTONSOURCE' => 'EventEspresso_SP', //EE will blow up if you change this
146 146
 			'LOCALECODE' => $locale[1]	// Locale of the pages displayed by PayPal during Express Checkout.
147 147
 		);
148 148
 
149 149
 		// Show itemized list.
150
-		if ( $this->_money->compare_floats( $payment->amount(), $transaction->total(), '==' ) ) {
150
+		if ($this->_money->compare_floats($payment->amount(), $transaction->total(), '==')) {
151 151
 			$item_num = 0;
152 152
 			$itemized_sum = 0;
153 153
 			$total_line_items = $transaction->total_line_item();
154 154
 			// Go through each item in the list.
155
-			foreach ( $total_line_items->get_items() as $line_item ) {
156
-				if ( $line_item instanceof EE_Line_Item ) {
155
+			foreach ($total_line_items->get_items() as $line_item) {
156
+				if ($line_item instanceof EE_Line_Item) {
157 157
 					// PayPal doesn't like line items with 0.00 amount, so we may skip those.
158
-					if ( EEH_Money::compare_floats( $line_item->total(), '0.00', '==' ) ) {
158
+					if (EEH_Money::compare_floats($line_item->total(), '0.00', '==')) {
159 159
 						continue;
160 160
 					}
161 161
 
162 162
 					$unit_price = $line_item->unit_price();
163 163
 					$line_item_quantity = $line_item->quantity();
164 164
 					// This is a discount.
165
-					if ( $line_item->is_percent() ) {
165
+					if ($line_item->is_percent()) {
166 166
 						$unit_price = $line_item->total();
167 167
 						$line_item_quantity = 1;
168 168
 					}
169 169
 					// Item Name.
170
-					$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr($this->_format_line_item_name( $line_item, $payment), 0, 127);
170
+					$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr($this->_format_line_item_name($line_item, $payment), 0, 127);
171 171
 					// Item description.
172
-					$token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = substr($this->_format_line_item_desc( $line_item, $payment), 0, 127);
172
+					$token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = substr($this->_format_line_item_desc($line_item, $payment), 0, 127);
173 173
 					// Cost of individual item.
174
-					$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency( $unit_price );
174
+					$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency($unit_price);
175 175
 					// Item Number.
176 176
 					$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER'.$item_num] = $item_num + 1;
177 177
 					// Item quantity.
@@ -188,16 +188,16 @@  discard block
 block discarded – undo
188 188
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
189 189
 			$token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
190 190
 
191
-			$itemized_sum_diff_from_txn_total = round( $transaction->total() - $itemized_sum - $total_line_items->get_total_tax(), 2 );
191
+			$itemized_sum_diff_from_txn_total = round($transaction->total() - $itemized_sum - $total_line_items->get_total_tax(), 2);
192 192
 			// If we were not able to recognize some item like promotion, surcharge or cancellation,
193 193
 			// add the difference as an extra line item.
194
-			if ( $this->_money->compare_floats( $itemized_sum_diff_from_txn_total, 0, '!=' ) ) {
194
+			if ($this->_money->compare_floats($itemized_sum_diff_from_txn_total, 0, '!=')) {
195 195
 				// Item Name.
196
-				$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr( __( 'Other (promotion/surcharge/cancellation)', 'event_espresso' ), 0, 127 );
196
+				$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr(__('Other (promotion/surcharge/cancellation)', 'event_espresso'), 0, 127);
197 197
 				// Item description.
198 198
 				$token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = '';
199 199
 				// Cost of individual item.
200
-				$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency( $itemized_sum_diff_from_txn_total );
200
+				$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency($itemized_sum_diff_from_txn_total);
201 201
 				// Item Number.
202 202
 				$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER'.$item_num] = $item_num + 1;
203 203
 				// Item quantity.
@@ -209,11 +209,11 @@  discard block
 block discarded – undo
209 209
 		} else {
210 210
 			// Just one Item.
211 211
 			// Item Name.
212
-			$token_request_dtls['L_PAYMENTREQUEST_0_NAME0'] = substr( $this->_format_partial_payment_line_item_name($payment), 0, 127 );
212
+			$token_request_dtls['L_PAYMENTREQUEST_0_NAME0'] = substr($this->_format_partial_payment_line_item_name($payment), 0, 127);
213 213
 			// Item description.
214
-			$token_request_dtls['L_PAYMENTREQUEST_0_DESC0'] = substr( $this->_format_partial_payment_line_item_desc($payment), 0, 127 );
214
+			$token_request_dtls['L_PAYMENTREQUEST_0_DESC0'] = substr($this->_format_partial_payment_line_item_desc($payment), 0, 127);
215 215
 			// Cost of individual item.
216
-			$token_request_dtls['L_PAYMENTREQUEST_0_AMT0'] = $this->format_currency( $payment->amount() );
216
+			$token_request_dtls['L_PAYMENTREQUEST_0_AMT0'] = $this->format_currency($payment->amount());
217 217
 			// Item Number.
218 218
 			$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER0'] = 1;
219 219
 			// Item quantity.
@@ -221,14 +221,14 @@  discard block
 block discarded – undo
221 221
 			// Digital item is sold.
222 222
 			$token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Physical';
223 223
 			// Item's sales S/H and tax amount.
224
-			$token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $this->format_currency( $payment->amount() );
224
+			$token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $this->format_currency($payment->amount());
225 225
 			$token_request_dtls['PAYMENTREQUEST_0_TAXAMT'] = '0';
226 226
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
227 227
 			$token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
228 228
 		}
229 229
 		// Automatically filling out shipping and contact information.
230
-		if ( $this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee ) {
231
-			$token_request_dtls['NOSHIPPING'] = '2';	//  If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
230
+		if ($this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee) {
231
+			$token_request_dtls['NOSHIPPING'] = '2'; //  If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
232 232
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET'] = $primary_attendee->address();
233 233
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $primary_attendee->address2();
234 234
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCITY'] = $primary_attendee->city();
@@ -237,34 +237,34 @@  discard block
 block discarded – undo
237 237
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip();
238 238
 			$token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email();
239 239
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone();
240
-		} elseif ( ! $this->_request_shipping_addr ) {
240
+		} elseif ( ! $this->_request_shipping_addr) {
241 241
 			// Do not request shipping details on the PP Checkout page.
242 242
 			$token_request_dtls['NOSHIPPING'] = '1';
243 243
 			$token_request_dtls['REQCONFIRMSHIPPING'] = '0';
244 244
 
245 245
 		}
246 246
 		// Used a business/personal logo on the PayPal page.
247
-		if ( ! empty($this->_image_url) ) {
247
+		if ( ! empty($this->_image_url)) {
248 248
 			$token_request_dtls['LOGOIMG'] = $this->_image_url;
249 249
 		}
250 250
 		// Request PayPal token.
251
-		$token_request_response = $this->_ppExpress_request( $token_request_dtls, 'Payment Token', $payment );
252
-		$token_rstatus = $this->_ppExpress_check_response( $token_request_response );
253
-		$response_args = ( isset($token_rstatus['args']) && is_array($token_rstatus['args']) ) ? $token_rstatus['args'] : array();
254
-		if ( $token_rstatus['status'] ) {
251
+		$token_request_response = $this->_ppExpress_request($token_request_dtls, 'Payment Token', $payment);
252
+		$token_rstatus = $this->_ppExpress_check_response($token_request_response);
253
+		$response_args = (isset($token_rstatus['args']) && is_array($token_rstatus['args'])) ? $token_rstatus['args'] : array();
254
+		if ($token_rstatus['status']) {
255 255
 			// We got the Token so we may continue with the payment and redirect the client.
256
-			$payment->set_details( $response_args );
256
+			$payment->set_details($response_args);
257 257
 
258 258
 			$gateway_url = $this->_debug_mode ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
259
-			$payment->set_redirect_url( $gateway_url . '/checkoutnow?useraction=commit&cmd=_express-checkout&token=' . $response_args['TOKEN'] );
259
+			$payment->set_redirect_url($gateway_url.'/checkoutnow?useraction=commit&cmd=_express-checkout&token='.$response_args['TOKEN']);
260 260
 		} else {
261
-			if ( isset($response_args['L_ERRORCODE']) ) {
262
-				$payment->set_gateway_response( $response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE'] );
261
+			if (isset($response_args['L_ERRORCODE'])) {
262
+				$payment->set_gateway_response($response_args['L_ERRORCODE'].'; '.$response_args['L_SHORTMESSAGE']);
263 263
 			} else {
264
-				$payment->set_gateway_response( __( 'Error occurred while trying to setup the Express Checkout.', 'event_espresso' ) );
264
+				$payment->set_gateway_response(__('Error occurred while trying to setup the Express Checkout.', 'event_espresso'));
265 265
 			}
266
-			$payment->set_details( $response_args );
267
-			$payment->set_status( $this->_pay_model->failed_status() );
266
+			$payment->set_details($response_args);
267
+			$payment->set_status($this->_pay_model->failed_status());
268 268
 		}
269 269
 
270 270
 		return $payment;
@@ -280,22 +280,22 @@  discard block
 block discarded – undo
280 280
 	 *  @param EEI_Transaction $transaction
281 281
 	 *  @return EEI_Payment
282 282
 	 */
283
-	public function handle_payment_update( $update_info, $transaction ) {
283
+	public function handle_payment_update($update_info, $transaction) {
284 284
 		$payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : null;
285 285
 
286
-		if ( $payment instanceof EEI_Payment ) {
287
-			$this->log( array( 'Return from Authorization' => $update_info ), $payment );
286
+		if ($payment instanceof EEI_Payment) {
287
+			$this->log(array('Return from Authorization' => $update_info), $payment);
288 288
 			$transaction = $payment->transaction();
289
-			if ( ! $transaction instanceof EEI_Transaction ) {
290
-				$payment->set_gateway_response( __( 'Could not process this payment because it has no associated transaction.', 'event_espresso' ) );
291
-				$payment->set_status( $this->_pay_model->failed_status() );
289
+			if ( ! $transaction instanceof EEI_Transaction) {
290
+				$payment->set_gateway_response(__('Could not process this payment because it has no associated transaction.', 'event_espresso'));
291
+				$payment->set_status($this->_pay_model->failed_status());
292 292
 				return $payment;
293 293
 			}
294 294
 			$primary_registrant = $transaction->primary_registration();
295 295
             $payment_details = $payment->details();
296 296
             // Check if we still have the token.
297
-			if ( ! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN']) ) {
298
-				$payment->set_status( $this->_pay_model->failed_status() );
297
+			if ( ! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
298
+				$payment->set_status($this->_pay_model->failed_status());
299 299
 				return $payment;
300 300
 			}
301 301
 
@@ -304,10 +304,10 @@  discard block
 block discarded – undo
304 304
 				'TOKEN' => $payment_details['TOKEN']
305 305
 			);
306 306
 			// Request Customer Details.
307
-			$cdetails_request_response = $this->_ppExpress_request( $cdetails_request_dtls, 'Customer Details', $payment );
308
-			$cdetails_rstatus = $this->_ppExpress_check_response( $cdetails_request_response );
309
-			$cdata_response_args = ( isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args']) ) ? $cdetails_rstatus['args'] : array();
310
-			if ( $cdetails_rstatus['status'] ) {
307
+			$cdetails_request_response = $this->_ppExpress_request($cdetails_request_dtls, 'Customer Details', $payment);
308
+			$cdetails_rstatus = $this->_ppExpress_check_response($cdetails_request_response);
309
+			$cdata_response_args = (isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args'])) ? $cdetails_rstatus['args'] : array();
310
+			if ($cdetails_rstatus['status']) {
311 311
 				// We got the PayerID so now we can Complete the transaction.
312 312
 				$docheckout_request_dtls = array(
313 313
 					'METHOD' => 'DoExpressCheckoutPayment',
@@ -318,39 +318,39 @@  discard block
 block discarded – undo
318 318
 					'PAYMENTREQUEST_0_CURRENCYCODE' => $payment->currency_code()
319 319
 				);
320 320
 				// Payment Checkout/Capture.
321
-				$docheckout_request_response = $this->_ppExpress_request( $docheckout_request_dtls, 'Do Payment', $payment );
322
-				$docheckout_rstatus = $this->_ppExpress_check_response( $docheckout_request_response );
323
-				$docheckout_response_args = ( isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args']) ) ? $docheckout_rstatus['args'] : array();
324
-				if ( $docheckout_rstatus['status'] ) {
321
+				$docheckout_request_response = $this->_ppExpress_request($docheckout_request_dtls, 'Do Payment', $payment);
322
+				$docheckout_rstatus = $this->_ppExpress_check_response($docheckout_request_response);
323
+				$docheckout_response_args = (isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args'])) ? $docheckout_rstatus['args'] : array();
324
+				if ($docheckout_rstatus['status']) {
325 325
 					// All is well, payment approved.
326 326
 					$primary_registration_code = $primary_registrant instanceof EE_Registration ? $primary_registrant->reg_code() : '';
327
-					$payment->set_extra_accntng( $primary_registration_code );
328
-					$payment->set_amount( isset($docheckout_response_args['PAYMENTINFO_0_AMT']) ? (float) $docheckout_response_args['PAYMENTINFO_0_AMT'] : 0 );
329
-					$payment->set_txn_id_chq_nmbr( isset( $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'] ) ? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'] : null );
330
-					$payment->set_details( $cdata_response_args );
331
-					$payment->set_gateway_response( isset( $docheckout_response_args['PAYMENTINFO_0_ACK'] ) ? $docheckout_response_args['PAYMENTINFO_0_ACK'] : '' );
332
-					$payment->set_status( $this->_pay_model->approved_status() );
327
+					$payment->set_extra_accntng($primary_registration_code);
328
+					$payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT']) ? (float) $docheckout_response_args['PAYMENTINFO_0_AMT'] : 0);
329
+					$payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']) ? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'] : null);
330
+					$payment->set_details($cdata_response_args);
331
+					$payment->set_gateway_response(isset($docheckout_response_args['PAYMENTINFO_0_ACK']) ? $docheckout_response_args['PAYMENTINFO_0_ACK'] : '');
332
+					$payment->set_status($this->_pay_model->approved_status());
333 333
 				} else {
334
-					if ( isset($docheckout_response_args['L_ERRORCODE']) ) {
335
-						$payment->set_gateway_response( $docheckout_response_args['L_ERRORCODE'] . '; ' . $docheckout_response_args['L_SHORTMESSAGE'] );
334
+					if (isset($docheckout_response_args['L_ERRORCODE'])) {
335
+						$payment->set_gateway_response($docheckout_response_args['L_ERRORCODE'].'; '.$docheckout_response_args['L_SHORTMESSAGE']);
336 336
 					} else {
337
-						$payment->set_gateway_response( __( 'Error occurred while trying to Capture the funds.', 'event_espresso' ) );
337
+						$payment->set_gateway_response(__('Error occurred while trying to Capture the funds.', 'event_espresso'));
338 338
 					}
339
-					$payment->set_details( $docheckout_response_args );
340
-					$payment->set_status( $this->_pay_model->declined_status() );
339
+					$payment->set_details($docheckout_response_args);
340
+					$payment->set_status($this->_pay_model->declined_status());
341 341
 				}
342 342
 			} else {
343
-				if ( isset($cdata_response_args['L_ERRORCODE']) ) {
344
-					$payment->set_gateway_response( $cdata_response_args['L_ERRORCODE'] . '; ' . $cdata_response_args['L_SHORTMESSAGE'] );
343
+				if (isset($cdata_response_args['L_ERRORCODE'])) {
344
+					$payment->set_gateway_response($cdata_response_args['L_ERRORCODE'].'; '.$cdata_response_args['L_SHORTMESSAGE']);
345 345
 				} else {
346
-					$payment->set_gateway_response( __( 'Error occurred while trying to get payment Details from PayPal.', 'event_espresso' ) );
346
+					$payment->set_gateway_response(__('Error occurred while trying to get payment Details from PayPal.', 'event_espresso'));
347 347
 				}
348
-				$payment->set_details( $cdata_response_args );
349
-				$payment->set_status( $this->_pay_model->failed_status() );
348
+				$payment->set_details($cdata_response_args);
349
+				$payment->set_status($this->_pay_model->failed_status());
350 350
 			}
351 351
 		} else {
352
-			$payment->set_gateway_response( __( 'Error occurred while trying to process the payment.', 'event_espresso' ) );
353
-			$payment->set_status( $this->_pay_model->failed_status() );
352
+			$payment->set_gateway_response(__('Error occurred while trying to process the payment.', 'event_espresso'));
353
+			$payment->set_status($this->_pay_model->failed_status());
354 354
 		}
355 355
 
356 356
 		return $payment;
@@ -365,16 +365,16 @@  discard block
 block discarded – undo
365 365
 	 *  @param EEI_Payment  $payment
366 366
 	 *	@return mixed
367 367
 	 */
368
-	public function _ppExpress_request( $request_params, $request_text, $payment ) {
368
+	public function _ppExpress_request($request_params, $request_text, $payment) {
369 369
 		$request_dtls = array(
370 370
 			'VERSION' => '204.0',
371
-			'USER' => urlencode( $this->_api_username ),
372
-			'PWD' => urlencode( $this->_api_password ),
373
-			'SIGNATURE' => urlencode( $this->_api_signature )
371
+			'USER' => urlencode($this->_api_username),
372
+			'PWD' => urlencode($this->_api_password),
373
+			'SIGNATURE' => urlencode($this->_api_signature)
374 374
 		);
375
-		$dtls = array_merge( $request_dtls, $request_params );
375
+		$dtls = array_merge($request_dtls, $request_params);
376 376
 
377
-		$this->_log_clean_request( $dtls, $payment, $request_text . ' Request' );
377
+		$this->_log_clean_request($dtls, $payment, $request_text.' Request');
378 378
 		// Request Customer Details.
379 379
 		$request_response = wp_remote_post(
380 380
 			$this->_base_gateway_url,
@@ -384,11 +384,11 @@  discard block
 block discarded – undo
384 384
 				'httpversion' => '1.1',
385 385
 				'cookies' => array(),
386 386
 				'headers' => array(),
387
-				'body' => http_build_query( $dtls )
387
+				'body' => http_build_query($dtls)
388 388
 			)
389 389
 		);
390 390
 		// Log the response.
391
-		$this->log( array( $request_text . ' Response' => $request_response), $payment );
391
+		$this->log(array($request_text.' Response' => $request_response), $payment);
392 392
 
393 393
 		return $request_response;
394 394
 	}
@@ -400,13 +400,13 @@  discard block
 block discarded – undo
400 400
 	 *	@param mixed        $request_response
401 401
 	 *	@return array
402 402
 	 */
403
-	public function _ppExpress_check_response( $request_response ) {
404
-		if (empty($request_response['body']) || is_wp_error( $request_response ) ) {
403
+	public function _ppExpress_check_response($request_response) {
404
+		if (empty($request_response['body']) || is_wp_error($request_response)) {
405 405
             // If we got here then there was an error in this request.
406 406
             return array('status' => false, 'args' => $request_response);
407 407
         }
408 408
         $response_args = array();
409
-        parse_str( urldecode($request_response['body']), $response_args );
409
+        parse_str(urldecode($request_response['body']), $response_args);
410 410
         if ( ! isset($response_args['ACK'])) {
411 411
             return array('status' => false, 'args' => $request_response);
412 412
         }
@@ -436,10 +436,10 @@  discard block
 block discarded – undo
436 436
 	 * @param string  		$info
437 437
 	 * @return void
438 438
 	 */
439
-	private function _log_clean_request($request, $payment, $info ) {
439
+	private function _log_clean_request($request, $payment, $info) {
440 440
 		$cleaned_request_data = $request;
441 441
 		unset($cleaned_request_data['PWD'], $cleaned_request_data['USER'], $cleaned_request_data['SIGNATURE']);
442
-		$this->log( array($info => $cleaned_request_data), $payment );
442
+		$this->log(array($info => $cleaned_request_data), $payment);
443 443
 	}
444 444
 
445 445
 
@@ -449,10 +449,10 @@  discard block
 block discarded – undo
449 449
 	 *  @param array	$data_array
450 450
 	 *  @return array
451 451
 	 */
452
-	private function _get_errors( $data_array ) {
452
+	private function _get_errors($data_array) {
453 453
 		$errors = array();
454 454
 		$n = 0;
455
-		while ( isset($data_array["L_ERRORCODE{$n}"]) ) {
455
+		while (isset($data_array["L_ERRORCODE{$n}"])) {
456 456
 			$l_error_code = isset($data_array["L_ERRORCODE{$n}"])
457 457
                 ? $data_array["L_ERRORCODE{$n}"]
458 458
                 : '';
@@ -466,7 +466,7 @@  discard block
 block discarded – undo
466 466
                 ? $data_array["L_LONGMESSAGE{$n}"]
467 467
                 : '';
468 468
 
469
-			if ( $n === 0 ) {
469
+			if ($n === 0) {
470 470
 				$errors = array(
471 471
 					'L_ERRORCODE' => $l_error_code,
472 472
 					'L_SHORTMESSAGE' => $l_short_message,
@@ -474,10 +474,10 @@  discard block
 block discarded – undo
474 474
 					'L_SEVERITYCODE' => $l_severity_code
475 475
 				);
476 476
 			} else {
477
-				$errors['L_ERRORCODE'] .= ', ' . $l_error_code;
478
-				$errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message;
479
-				$errors['L_LONGMESSAGE'] .= ', ' . $l_long_message;
480
-				$errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code;
477
+				$errors['L_ERRORCODE'] .= ', '.$l_error_code;
478
+				$errors['L_SHORTMESSAGE'] .= ', '.$l_short_message;
479
+				$errors['L_LONGMESSAGE'] .= ', '.$l_long_message;
480
+				$errors['L_SEVERITYCODE'] .= ', '.$l_severity_code;
481 481
 			}
482 482
 
483 483
 			$n++;
Please login to merge, or discard this patch.
core/services/database/TableManager.php 2 patches
Indentation   +207 added lines, -209 removed lines patch added patch discarded remove patch
@@ -17,216 +17,214 @@
 block discarded – undo
17 17
 class TableManager extends \EE_Base
18 18
 {
19 19
 
20
-    /**
21
-     * @var TableAnalysis $table_analysis
22
-     */
23
-    private $table_analysis;
24
-
25
-
26
-
27
-    /**
28
-     * TableManager constructor.
29
-     *
30
-     * @param TableAnalysis $TableAnalysis
31
-     */
32
-    public function __construct(TableAnalysis $TableAnalysis)
33
-    {
34
-        $this->table_analysis = $TableAnalysis;
35
-    }
36
-
37
-
38
-
39
-    /**
40
-     * Gets the injected table analyzer, or throws an exception
41
-     *
42
-     * @return TableAnalysis
43
-     * @throws \EE_Error
44
-     */
45
-    protected function getTableAnalysis()
46
-    {
47
-        if ($this->table_analysis instanceof TableAnalysis) {
48
-            return $this->table_analysis;
49
-        } else {
50
-            throw new \EE_Error(
51
-                sprintf(
52
-                    __('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
53
-                    get_class($this)
54
-                )
55
-            );
56
-        }
57
-    }
58
-
59
-
60
-
61
-    /**
62
-     * @param string $table_name which can optionally start with $wpdb->prefix or not
63
-     * @param string $column_name
64
-     * @param string $column_info
65
-     * @return bool|false|int
66
-     */
67
-    public function addColumn($table_name, $column_name, $column_info = 'INT UNSIGNED NOT NULL')
68
-    {
69
-        if (apply_filters('FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', false)) {
70
-            return false;
71
-        }
72
-        global $wpdb;
73
-        $full_table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
74
-        $columns = $this->getTableColumns($table_name);
75
-        if ( ! in_array($column_name, $columns)) {
76
-            $alter_query = "ALTER TABLE {$full_table_name} ADD {$column_name} {$column_info}";
77
-            return $wpdb->query($alter_query);
78
-        }
79
-        return true;
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * Gets the name of all columns on the  table. $table_name can
86
-     * optionally start with $wpdb->prefix or not
87
-     *
88
-     * @global \wpdb $wpdb
89
-     * @param string $table_name
90
-     * @return array
91
-     */
92
-    public function getTableColumns($table_name)
93
-    {
94
-        global $wpdb;
95
-        $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
96
-        $field_array = array();
97
-        if ( ! empty($table_name)) {
98
-            $columns = $wpdb->get_results("SHOW COLUMNS FROM {$table_name} ");
99
-            if ($columns !== false) {
100
-                foreach ($columns as $column) {
101
-                    $field_array[] = $column->Field;
102
-                }
103
-            }
104
-        }
105
-        return $field_array;
106
-    }
107
-
108
-
109
-
110
-    /**
111
-     * Drops the specified table from the database. $table_name can
112
-     * optionally start with $wpdb->prefix or not
113
-     *
114
-     * @global \wpdb $wpdb
115
-     * @param string $table_name
116
-     * @return int
117
-     */
118
-    public function dropTable($table_name)
119
-    {
120
-        global $wpdb;
121
-        if ($this->getTableAnalysis()->tableExists($table_name)) {
122
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
123
-            return $wpdb->query("DROP TABLE IF EXISTS {$table_name}");
124
-        }
125
-        return 0;
126
-    }
127
-
128
-
129
-
130
-    /**
131
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
132
-     * each table name provided has a wpdb prefix attached, and that it exists.
133
-     * Returns the list actually deleted
134
-     *
135
-     * @global WPDB $wpdb
136
-     * @param array $table_names
137
-     * @return array of table names which we deleted
138
-     */
139
-    public function dropTables($table_names)
140
-    {
141
-        $tables_to_delete = array();
142
-        foreach ($table_names as $table_name) {
143
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
144
-            if ($this->getTableAnalysis()->tableExists($table_name)) {
145
-                $tables_to_delete[] = $table_name;
146
-            }
147
-        }
148
-        if( ! empty( $tables_to_delete ) ) {
149
-            global $wpdb;
150
-            $wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
151
-        }
152
-        return $tables_to_delete;
153
-    }
154
-
155
-
156
-
157
-    /**
158
-     * Drops the specified index from the specified table. $table_name can
159
-     * optionally start with $wpdb->prefix or not
160
-
161
-     *
20
+	/**
21
+	 * @var TableAnalysis $table_analysis
22
+	 */
23
+	private $table_analysis;
24
+
25
+
26
+
27
+	/**
28
+	 * TableManager constructor.
29
+	 *
30
+	 * @param TableAnalysis $TableAnalysis
31
+	 */
32
+	public function __construct(TableAnalysis $TableAnalysis)
33
+	{
34
+		$this->table_analysis = $TableAnalysis;
35
+	}
36
+
37
+
38
+
39
+	/**
40
+	 * Gets the injected table analyzer, or throws an exception
41
+	 *
42
+	 * @return TableAnalysis
43
+	 * @throws \EE_Error
44
+	 */
45
+	protected function getTableAnalysis()
46
+	{
47
+		if ($this->table_analysis instanceof TableAnalysis) {
48
+			return $this->table_analysis;
49
+		} else {
50
+			throw new \EE_Error(
51
+				sprintf(
52
+					__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
53
+					get_class($this)
54
+				)
55
+			);
56
+		}
57
+	}
58
+
59
+
60
+
61
+	/**
62
+	 * @param string $table_name which can optionally start with $wpdb->prefix or not
63
+	 * @param string $column_name
64
+	 * @param string $column_info
65
+	 * @return bool|false|int
66
+	 */
67
+	public function addColumn($table_name, $column_name, $column_info = 'INT UNSIGNED NOT NULL')
68
+	{
69
+		if (apply_filters('FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', false)) {
70
+			return false;
71
+		}
72
+		global $wpdb;
73
+		$full_table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
74
+		$columns = $this->getTableColumns($table_name);
75
+		if ( ! in_array($column_name, $columns)) {
76
+			$alter_query = "ALTER TABLE {$full_table_name} ADD {$column_name} {$column_info}";
77
+			return $wpdb->query($alter_query);
78
+		}
79
+		return true;
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * Gets the name of all columns on the  table. $table_name can
86
+	 * optionally start with $wpdb->prefix or not
87
+	 *
88
+	 * @global \wpdb $wpdb
89
+	 * @param string $table_name
90
+	 * @return array
91
+	 */
92
+	public function getTableColumns($table_name)
93
+	{
94
+		global $wpdb;
95
+		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
96
+		$field_array = array();
97
+		if ( ! empty($table_name)) {
98
+			$columns = $wpdb->get_results("SHOW COLUMNS FROM {$table_name} ");
99
+			if ($columns !== false) {
100
+				foreach ($columns as $column) {
101
+					$field_array[] = $column->Field;
102
+				}
103
+			}
104
+		}
105
+		return $field_array;
106
+	}
107
+
108
+
109
+
110
+	/**
111
+	 * Drops the specified table from the database. $table_name can
112
+	 * optionally start with $wpdb->prefix or not
113
+	 *
114
+	 * @global \wpdb $wpdb
115
+	 * @param string $table_name
116
+	 * @return int
117
+	 */
118
+	public function dropTable($table_name)
119
+	{
120
+		global $wpdb;
121
+		if ($this->getTableAnalysis()->tableExists($table_name)) {
122
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
123
+			return $wpdb->query("DROP TABLE IF EXISTS {$table_name}");
124
+		}
125
+		return 0;
126
+	}
127
+
128
+
129
+
130
+	/**
131
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
132
+	 * each table name provided has a wpdb prefix attached, and that it exists.
133
+	 * Returns the list actually deleted
134
+	 *
135
+	 * @global WPDB $wpdb
136
+	 * @param array $table_names
137
+	 * @return array of table names which we deleted
138
+	 */
139
+	public function dropTables($table_names)
140
+	{
141
+		$tables_to_delete = array();
142
+		foreach ($table_names as $table_name) {
143
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
144
+			if ($this->getTableAnalysis()->tableExists($table_name)) {
145
+				$tables_to_delete[] = $table_name;
146
+			}
147
+		}
148
+		if( ! empty( $tables_to_delete ) ) {
149
+			global $wpdb;
150
+			$wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
151
+		}
152
+		return $tables_to_delete;
153
+	}
154
+
155
+
156
+
157
+	/**
158
+	 * Drops the specified index from the specified table. $table_name can
159
+	 * optionally start with $wpdb->prefix or not
160
+	 *
162 161
 *@global \wpdb       $wpdb
163
-     * @param string $table_name
164
-     * @param string $index_name
165
-     * @return int
166
-     */
167
-    public function dropIndex($table_name, $index_name)
168
-    {
169
-        if (apply_filters('FHEE__EEH_Activation__drop_index__short_circuit', false)) {
170
-            return false;
171
-        }
172
-        global $wpdb;
173
-        $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
174
-        $index_exists_query = "SHOW INDEX FROM {$table_name} WHERE Key_name = '{$index_name}'";
175
-        if (
176
-            $this->getTableAnalysis()->tableExists($table_name)
177
-            && $wpdb->get_var($index_exists_query)
178
-               === $table_name //using get_var with the $index_exists_query returns the table's name
179
-        ) {
180
-            return $wpdb->query("ALTER TABLE {$table_name} DROP INDEX {$index_name}");
181
-        }
182
-        return 0;
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * Just creates the requested table. $table_name can
189
-     * optionally start with $wpdb->prefix or not
190
-
191
-     *
162
+	 * @param string $table_name
163
+	 * @param string $index_name
164
+	 * @return int
165
+	 */
166
+	public function dropIndex($table_name, $index_name)
167
+	{
168
+		if (apply_filters('FHEE__EEH_Activation__drop_index__short_circuit', false)) {
169
+			return false;
170
+		}
171
+		global $wpdb;
172
+		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
173
+		$index_exists_query = "SHOW INDEX FROM {$table_name} WHERE Key_name = '{$index_name}'";
174
+		if (
175
+			$this->getTableAnalysis()->tableExists($table_name)
176
+			&& $wpdb->get_var($index_exists_query)
177
+			   === $table_name //using get_var with the $index_exists_query returns the table's name
178
+		) {
179
+			return $wpdb->query("ALTER TABLE {$table_name} DROP INDEX {$index_name}");
180
+		}
181
+		return 0;
182
+	}
183
+
184
+
185
+
186
+	/**
187
+	 * Just creates the requested table. $table_name can
188
+	 * optionally start with $wpdb->prefix or not
189
+	 *
192 190
 *@param string       $table_name
193
-     * @param string $create_sql defining the table's columns and indexes
194
-     * @param string $engine     (no need to specify "ENGINE=", that's implied)
195
-     * @return void
196
-     * @throws \EE_Error
197
-     */
198
-    public function createTable($table_name, $create_sql, $engine = 'MyISAM')
199
-    {
200
-        // does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
201
-        if (preg_match('((((.*?))(,\s))+)', $create_sql, $valid_column_data)) {
202
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
203
-            /** @var \wpdb $wpdb */
204
-            global $wpdb;
205
-            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
206
-
207
-            //get $wpdb to echo errors, but buffer them. This way at least WE know an error
208
-            //happened. And then we can choose to tell the end user
209
-            $old_show_errors_policy = $wpdb->show_errors(true);
210
-            $old_error_suppression_policy = $wpdb->suppress_errors(false);
211
-            ob_start();
212
-            dbDelta($SQL);
213
-            $output = ob_get_contents();
214
-            ob_end_clean();
215
-            $wpdb->show_errors($old_show_errors_policy);
216
-            $wpdb->suppress_errors($old_error_suppression_policy);
217
-            if ( ! empty($output)) {
218
-                throw new \EE_Error($output);
219
-            }
220
-        } else {
221
-            throw new \EE_Error(
222
-                sprintf(
223
-                    __('The following table creation SQL does not contain valid information about the table columns: %1$s %2$s',
224
-                        'event_espresso'),
225
-                    '<br />',
226
-                    $create_sql
227
-                )
228
-            );
229
-        }
230
-    }
191
+	 * @param string $create_sql defining the table's columns and indexes
192
+	 * @param string $engine     (no need to specify "ENGINE=", that's implied)
193
+	 * @return void
194
+	 * @throws \EE_Error
195
+	 */
196
+	public function createTable($table_name, $create_sql, $engine = 'MyISAM')
197
+	{
198
+		// does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
199
+		if (preg_match('((((.*?))(,\s))+)', $create_sql, $valid_column_data)) {
200
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
201
+			/** @var \wpdb $wpdb */
202
+			global $wpdb;
203
+			$SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
204
+
205
+			//get $wpdb to echo errors, but buffer them. This way at least WE know an error
206
+			//happened. And then we can choose to tell the end user
207
+			$old_show_errors_policy = $wpdb->show_errors(true);
208
+			$old_error_suppression_policy = $wpdb->suppress_errors(false);
209
+			ob_start();
210
+			dbDelta($SQL);
211
+			$output = ob_get_contents();
212
+			ob_end_clean();
213
+			$wpdb->show_errors($old_show_errors_policy);
214
+			$wpdb->suppress_errors($old_error_suppression_policy);
215
+			if ( ! empty($output)) {
216
+				throw new \EE_Error($output);
217
+			}
218
+		} else {
219
+			throw new \EE_Error(
220
+				sprintf(
221
+					__('The following table creation SQL does not contain valid information about the table columns: %1$s %2$s',
222
+						'event_espresso'),
223
+					'<br />',
224
+					$create_sql
225
+				)
226
+			);
227
+		}
228
+	}
231 229
 
232 230
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -145,9 +145,9 @@  discard block
 block discarded – undo
145 145
                 $tables_to_delete[] = $table_name;
146 146
             }
147 147
         }
148
-        if( ! empty( $tables_to_delete ) ) {
148
+        if ( ! empty($tables_to_delete)) {
149 149
             global $wpdb;
150
-            $wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
150
+            $wpdb->query('DROP TABLE '.implode(', ', $tables_to_delete));
151 151
         }
152 152
         return $tables_to_delete;
153 153
     }
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
             $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
203 203
             /** @var \wpdb $wpdb */
204 204
             global $wpdb;
205
-            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
205
+            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} ".$wpdb->get_charset_collate();
206 206
 
207 207
             //get $wpdb to echo errors, but buffer them. This way at least WE know an error
208 208
             //happened. And then we can choose to tell the end user
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 2 patches
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -1,16 +1,16 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { exit('No direct script access allowed'); }
2 2
  /**
3
- *
4
- * Class EE_SPCO_Reg_Step_Attendee_Information
5
- *
6
- * Description
7
- *
8
- * @package 			Event Espresso
9
- * @subpackage 	core
10
- * @author 				Brent Christensen
11
- * @since 				4.5.0
12
- *
13
- */
3
+  *
4
+  * Class EE_SPCO_Reg_Step_Attendee_Information
5
+  *
6
+  * Description
7
+  *
8
+  * @package 			Event Espresso
9
+  * @subpackage 	core
10
+  * @author 				Brent Christensen
11
+  * @since 				4.5.0
12
+  *
13
+  */
14 14
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step {
15 15
 
16 16
 	/**
@@ -135,33 +135,33 @@  discard block
 block discarded – undo
135 135
 					$registration instanceof EE_Registration
136 136
 					&& $this->checkout->visit_allows_processing_of_this_registration( $registration )
137 137
 				) {
138
-                    $attendee_reg_form = $this->_registrations_reg_form($registration);
139
-                    if ($attendee_reg_form instanceof EE_Form_Section_Proper) {
140
-                        $subsections[$registration->reg_url_link()] = $attendee_reg_form;
141
-                        if ( ! $this->checkout->admin_request) {
142
-                            $template_args['registrations'][$registration->reg_url_link()] = $registration;
143
-                            $template_args['ticket_count'][$registration->ticket()->ID()] = isset(
144
-                                $template_args['ticket_count'][$registration->ticket()->ID()]
145
-                            )
146
-                                ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
147
-                                : 1;
148
-                            $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
149
-                                $this->checkout->cart->get_grand_total(),
150
-                                'Ticket',
151
-                                array($registration->ticket()->ID())
152
-                            );
153
-                            $ticket_line_item = is_array($ticket_line_item)
154
-                                ? reset($ticket_line_item)
155
-                                : $ticket_line_item;
156
-                            $template_args['ticket_line_item'][$registration->ticket()
157
-                                                                            ->ID()] = $Line_Item_Display->display_line_item(
158
-                                $ticket_line_item
159
-                            );
160
-                        }
161
-                    }
162
-                    if ($registration->is_primary_registrant()) {
163
-                        $primary_registrant = $registration->reg_url_link();
164
-                    }
138
+					$attendee_reg_form = $this->_registrations_reg_form($registration);
139
+					if ($attendee_reg_form instanceof EE_Form_Section_Proper) {
140
+						$subsections[$registration->reg_url_link()] = $attendee_reg_form;
141
+						if ( ! $this->checkout->admin_request) {
142
+							$template_args['registrations'][$registration->reg_url_link()] = $registration;
143
+							$template_args['ticket_count'][$registration->ticket()->ID()] = isset(
144
+								$template_args['ticket_count'][$registration->ticket()->ID()]
145
+							)
146
+								? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
147
+								: 1;
148
+							$ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
149
+								$this->checkout->cart->get_grand_total(),
150
+								'Ticket',
151
+								array($registration->ticket()->ID())
152
+							);
153
+							$ticket_line_item = is_array($ticket_line_item)
154
+								? reset($ticket_line_item)
155
+								: $ticket_line_item;
156
+							$template_args['ticket_line_item'][$registration->ticket()
157
+																			->ID()] = $Line_Item_Display->display_line_item(
158
+								$ticket_line_item
159
+							);
160
+						}
161
+					}
162
+					if ($registration->is_primary_registrant()) {
163
+						$primary_registrant = $registration->reg_url_link();
164
+					}
165 165
 				}
166 166
 			}
167 167
 			// print_copy_info ?
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 				// generate hidden input
174 174
 				if (
175 175
 					isset( $subsections[ $primary_registrant ] )
176
-				     && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
176
+					 && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
177 177
 				) {
178 178
 					$subsections[ $primary_registrant ]->add_subsections( $copy_options, 'primary_registrant', false );
179 179
 				}
@@ -208,35 +208,35 @@  discard block
 block discarded – undo
208 208
 	 */
209 209
 	private function _registrations_reg_form( EE_Registration $registration ) {
210 210
 		static $attendee_nmbr = 1;
211
-        $form_args = array();
211
+		$form_args = array();
212 212
 		// verify that registration has valid event
213 213
 		if ( $registration->event() instanceof EE_Event ) {
214 214
 			$question_groups = $registration->event()->question_groups(
215
-                array(
216
-                    array(
217
-                        'Event.EVT_ID'                     => $registration->event()->ID(),
218
-                        'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false
219
-                    ),
220
-                    'order_by' => array('QSG_order' => 'ASC')
221
-                )
222
-            );
215
+				array(
216
+					array(
217
+						'Event.EVT_ID'                     => $registration->event()->ID(),
218
+						'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false
219
+					),
220
+					'order_by' => array('QSG_order' => 'ASC')
221
+				)
222
+			);
223 223
 			if ( $question_groups ) {
224
-                // array of params to pass to parent constructor
225
-                $form_args = array(
226
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
227
-                    'html_class'      => 'ee-reg-form-attendee-dv',
228
-                    'html_style'      => $this->checkout->admin_request
229
-                        ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
230
-                        : '',
231
-                    'subsections'     => array(),
232
-                    'layout_strategy' => new EE_Fieldset_Section_Layout(
233
-                        array(
234
-                            'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
235
-                            'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr)
236
-                        )
237
-                    )
238
-                );
239
-                foreach ( $question_groups as $question_group ) {
224
+				// array of params to pass to parent constructor
225
+				$form_args = array(
226
+					'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
227
+					'html_class'      => 'ee-reg-form-attendee-dv',
228
+					'html_style'      => $this->checkout->admin_request
229
+						? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
230
+						: '',
231
+					'subsections'     => array(),
232
+					'layout_strategy' => new EE_Fieldset_Section_Layout(
233
+						array(
234
+							'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
235
+							'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr)
236
+						)
237
+					)
238
+				);
239
+				foreach ( $question_groups as $question_group ) {
240 240
 					if ( $question_group instanceof EE_Question_Group ) {
241 241
 						$form_args['subsections'][ $question_group->identifier() ] = $this->_question_group_reg_form(
242 242
 							$registration,
@@ -244,19 +244,19 @@  discard block
 block discarded – undo
244 244
 						);
245 245
 					}
246 246
 				}
247
-                // add hidden input
248
-                $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
249
-                    $registration
250
-                );
251
-                // if we have question groups for additional attendees, then display the copy options
247
+				// add hidden input
248
+				$form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
249
+					$registration
250
+				);
251
+				// if we have question groups for additional attendees, then display the copy options
252 252
 				$this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
253
-                if ($registration->is_primary_registrant()) {
254
-                    // generate hidden input
255
-                    $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs($registration);
256
-                }
257
-            }
253
+				if ($registration->is_primary_registrant()) {
254
+					// generate hidden input
255
+					$form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs($registration);
256
+				}
257
+			}
258 258
 		}
259
-        $attendee_nmbr++;
259
+		$attendee_nmbr++;
260 260
 		return ! empty($form_args) ? new EE_Form_Section_Proper( $form_args ) : null;
261 261
 	}
262 262
 
@@ -889,7 +889,7 @@  discard block
 block discarded – undo
889 889
 					if ( isset( $valid_data[ $reg_url_link ] ) ) {
890 890
 						// do we need to copy basic info from primary attendee ?
891 891
 						$copy_primary = isset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] )
892
-						                && absint( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ) === 0
892
+										&& absint( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ) === 0
893 893
 							? true
894 894
 							: false;
895 895
 						// filter form input data for this registration
@@ -1064,7 +1064,7 @@  discard block
 block discarded – undo
1064 1064
 			? $form_input
1065 1065
 			: $form_input . '-' . $registration->reg_url_link();
1066 1066
 		$answer_is_obj = isset( $this->_registration_answers[ $answer_cache_id ] )
1067
-		                 && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer
1067
+						 && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer
1068 1068
 			? true
1069 1069
 			: false;
1070 1070
 		//rename form_inputs if they are EE_Attendee properties
@@ -1184,7 +1184,7 @@  discard block
 block discarded – undo
1184 1184
 		// then attempt to copy them from the primary attendee
1185 1185
 		if (
1186 1186
 			$this->checkout->primary_attendee_obj instanceof EE_Attendee
1187
-            && ! isset( $attendee_data['ATT_fname'], $attendee_data['ATT_email'] )
1187
+			&& ! isset( $attendee_data['ATT_fname'], $attendee_data['ATT_email'] )
1188 1188
 		) {
1189 1189
 			return $this->checkout->primary_attendee_obj;
1190 1190
 		}
@@ -1302,7 +1302,7 @@  discard block
 block discarded – undo
1302 1302
 		}
1303 1303
 		foreach ( $critical_attendee_details as $critical_attendee_detail ) {
1304 1304
 			if ( ! isset( $attendee_data[ $critical_attendee_detail ] )
1305
-			     || empty( $attendee_data[ $critical_attendee_detail ] )
1305
+				 || empty( $attendee_data[ $critical_attendee_detail ] )
1306 1306
 			) {
1307 1307
 				$attendee_data[ $critical_attendee_detail ] = $this->checkout->primary_attendee_obj->get(
1308 1308
 					$critical_attendee_detail
Please login to merge, or discard this patch.
Spacing   +211 added lines, -212 removed lines patch added patch discarded remove patch
@@ -41,21 +41,21 @@  discard block
 block discarded – undo
41 41
 	 * @access    public
42 42
 	 * @param    EE_Checkout $checkout
43 43
 	 */
44
-	public function __construct( EE_Checkout $checkout ) {
44
+	public function __construct(EE_Checkout $checkout) {
45 45
 		$this->_slug = 'attendee_information';
46 46
 		$this->_name = __('Attendee Information', 'event_espresso');
47
-		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
47
+		$this->_template = SPCO_REG_STEPS_PATH.$this->_slug.DS.'attendee_info_main.template.php';
48 48
 		$this->checkout = $checkout;
49 49
 		$this->_reset_success_message();
50 50
 		$this->set_instructions(
51
-			__( 'Please answer the following registration questions before proceeding.', 'event_espresso' )
51
+			__('Please answer the following registration questions before proceeding.', 'event_espresso')
52 52
 		);
53 53
 	}
54 54
 
55 55
 
56 56
 
57 57
 	public function translate_js_strings() {
58
-		EE_Registry::$i18n_js_strings['required_field'] = __( ' is a required question.', 'event_espresso' );
58
+		EE_Registry::$i18n_js_strings['required_field'] = __(' is a required question.', 'event_espresso');
59 59
 		EE_Registry::$i18n_js_strings['required_multi_field'] = __(
60 60
 			' is a required question. Please enter a value for at least one of the options.',
61 61
 			'event_espresso'
@@ -115,7 +115,7 @@  discard block
 block discarded – undo
115 115
 		// calculate taxes
116 116
 		$Line_Item_Display->display_line_item(
117 117
 			$this->checkout->cart->get_grand_total(),
118
-			array( 'set_tax_rate' => true )
118
+			array('set_tax_rate' => true)
119 119
 		);
120 120
 		/** @var $subsections EE_Form_Section_Proper[] */
121 121
 		$subsections = array(
@@ -127,13 +127,13 @@  discard block
 block discarded – undo
127 127
 			'ticket_count' 	=> array()
128 128
 		);
129 129
 		// grab the saved registrations from the transaction
130
-		$registrations = $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params );
131
-		if ( $registrations ) {
132
-			foreach ( $registrations as $registration ) {
130
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
131
+		if ($registrations) {
132
+			foreach ($registrations as $registration) {
133 133
 				// can this registration be processed during this visit ?
134 134
 				if (
135 135
 					$registration instanceof EE_Registration
136
-					&& $this->checkout->visit_allows_processing_of_this_registration( $registration )
136
+					&& $this->checkout->visit_allows_processing_of_this_registration($registration)
137 137
 				) {
138 138
                     $attendee_reg_form = $this->_registrations_reg_form($registration);
139 139
                     if ($attendee_reg_form instanceof EE_Form_Section_Proper) {
@@ -165,17 +165,17 @@  discard block
 block discarded – undo
165 165
 				}
166 166
 			}
167 167
 			// print_copy_info ?
168
-			if ( $primary_registrant && ! $this->checkout->admin_request && count( $registrations ) > 1 ) {
168
+			if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
169 169
 				// TODO: add admin option for toggling copy attendee info, then use that value to change $this->_print_copy_info
170 170
 				$copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
171 171
 					? $this->_copy_attendee_info_form()
172 172
 					: $this->_auto_copy_attendee_info();
173 173
 				// generate hidden input
174 174
 				if (
175
-					isset( $subsections[ $primary_registrant ] )
176
-				     && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
175
+					isset($subsections[$primary_registrant])
176
+				     && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
177 177
 				) {
178
-					$subsections[ $primary_registrant ]->add_subsections( $copy_options, 'primary_registrant', false );
178
+					$subsections[$primary_registrant]->add_subsections($copy_options, 'primary_registrant', false);
179 179
 				}
180 180
 			}
181 181
 
@@ -187,8 +187,7 @@  discard block
 block discarded – undo
187 187
 				'html_id' 					=> $this->reg_form_name(),
188 188
 				'subsections' 			=> $subsections,
189 189
 				'layout_strategy'		=> $this->checkout->admin_request ?
190
-					new EE_Div_Per_Section_Layout() :
191
-					new EE_Template_Layout(
190
+					new EE_Div_Per_Section_Layout() : new EE_Template_Layout(
192 191
 						array(
193 192
 							'layout_template_file' 	=> $this->_template, // layout_template
194 193
 							'template_args' 				=> $template_args
@@ -206,11 +205,11 @@  discard block
 block discarded – undo
206 205
 	 * @return EE_Form_Section_Proper
207 206
 	 * @throws \EE_Error
208 207
 	 */
209
-	private function _registrations_reg_form( EE_Registration $registration ) {
208
+	private function _registrations_reg_form(EE_Registration $registration) {
210 209
 		static $attendee_nmbr = 1;
211 210
         $form_args = array();
212 211
 		// verify that registration has valid event
213
-		if ( $registration->event() instanceof EE_Event ) {
212
+		if ($registration->event() instanceof EE_Event) {
214 213
 			$question_groups = $registration->event()->question_groups(
215 214
                 array(
216 215
                     array(
@@ -220,10 +219,10 @@  discard block
 block discarded – undo
220 219
                     'order_by' => array('QSG_order' => 'ASC')
221 220
                 )
222 221
             );
223
-			if ( $question_groups ) {
222
+			if ($question_groups) {
224 223
                 // array of params to pass to parent constructor
225 224
                 $form_args = array(
226
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
225
+                    'html_id'         => 'ee-registration-'.$registration->reg_url_link(),
227 226
                     'html_class'      => 'ee-reg-form-attendee-dv',
228 227
                     'html_style'      => $this->checkout->admin_request
229 228
                         ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
@@ -236,9 +235,9 @@  discard block
 block discarded – undo
236 235
                         )
237 236
                     )
238 237
                 );
239
-                foreach ( $question_groups as $question_group ) {
240
-					if ( $question_group instanceof EE_Question_Group ) {
241
-						$form_args['subsections'][ $question_group->identifier() ] = $this->_question_group_reg_form(
238
+                foreach ($question_groups as $question_group) {
239
+					if ($question_group instanceof EE_Question_Group) {
240
+						$form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
242 241
 							$registration,
243 242
 							$question_group
244 243
 						);
@@ -257,7 +256,7 @@  discard block
 block discarded – undo
257 256
             }
258 257
 		}
259 258
         $attendee_nmbr++;
260
-		return ! empty($form_args) ? new EE_Form_Section_Proper( $form_args ) : null;
259
+		return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : null;
261 260
 	}
262 261
 
263 262
 
@@ -278,7 +277,7 @@  discard block
 block discarded – undo
278 277
 		// generate hidden input
279 278
 		return new EE_Hidden_Input(
280 279
 			array(
281
-				'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
280
+				'html_id' => 'additional-attendee-reg-info-'.$registration->reg_url_link(),
282 281
 				'default' => $additional_attendee_reg_info
283 282
 			)
284 283
 		);
@@ -292,26 +291,26 @@  discard block
 block discarded – undo
292 291
 	 * @return EE_Form_Section_Proper
293 292
 	 * @throws \EE_Error
294 293
 	 */
295
-	private function _question_group_reg_form( EE_Registration $registration, EE_Question_Group $question_group ){
294
+	private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group) {
296 295
 		// array of params to pass to parent constructor
297 296
 		$form_args = array(
298
-			'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier(),
297
+			'html_id'         => 'ee-reg-form-qstn-grp-'.$question_group->identifier(),
299 298
 			'html_class'      => $this->checkout->admin_request
300 299
 				? 'form-table ee-reg-form-qstn-grp-dv'
301 300
 				: 'ee-reg-form-qstn-grp-dv',
302
-			'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-lbl',
301
+			'html_label_id'   => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-lbl',
303 302
 			'subsections'     => array(
304
-				'reg_form_qstn_grp_hdr' => $this->_question_group_header( $question_group )
303
+				'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group)
305 304
 			),
306 305
 			'layout_strategy' => $this->checkout->admin_request
307 306
 				? new EE_Admin_Two_Column_Layout()
308 307
 				: new EE_Div_Per_Section_Layout()
309 308
 		);
310 309
 		// where params
311
-		$query_params = array( 'QST_deleted' => 0 );
310
+		$query_params = array('QST_deleted' => 0);
312 311
 		// don't load admin only questions on the frontend
313
-		if ( ! $this->checkout->admin_request ) {
314
-			$query_params['QST_admin_only'] = array( '!=', true );
312
+		if ( ! $this->checkout->admin_request) {
313
+			$query_params['QST_admin_only'] = array('!=', true);
315 314
 		}
316 315
 		$questions = $question_group->get_many_related(
317 316
 			'Question',
@@ -333,10 +332,10 @@  discard block
 block discarded – undo
333 332
 			)
334 333
 		);
335 334
 		// loop thru questions
336
-		foreach ( $questions as $question ) {
337
-			if( $question instanceof EE_Question ){
335
+		foreach ($questions as $question) {
336
+			if ($question instanceof EE_Question) {
338 337
 				$identifier = $question->is_system_question() ? $question->system_ID() : $question->ID();
339
-				$form_args['subsections'][ $identifier ] = $this->reg_form_question( $registration, $question );
338
+				$form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
340 339
 			}
341 340
 		}
342 341
 		$form_args['subsections'] = apply_filters(
@@ -357,7 +356,7 @@  discard block
 block discarded – undo
357 356
 			)
358 357
 		);
359 358
 //		d( $form_args );
360
-		$question_group_reg_form = new EE_Form_Section_Proper( $form_args );
359
+		$question_group_reg_form = new EE_Form_Section_Proper($form_args);
361 360
 		return apply_filters(
362 361
 			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
363 362
 			$question_group_reg_form,
@@ -374,11 +373,11 @@  discard block
 block discarded – undo
374 373
 	 * @param EE_Question_Group $question_group
375 374
 	 * @return 	EE_Form_Section_HTML
376 375
 	 */
377
-	private function _question_group_header( EE_Question_Group $question_group ){
376
+	private function _question_group_header(EE_Question_Group $question_group) {
378 377
 		$html = '';
379 378
 		// group_name
380
-		if ( $question_group->show_group_name() && $question_group->name() !== '' ) {
381
-			if ( $this->checkout->admin_request ) {
379
+		if ($question_group->show_group_name() && $question_group->name() !== '') {
380
+			if ($this->checkout->admin_request) {
382 381
 				$html .= EEH_HTML::br();
383 382
 				$html .= EEH_HTML::h3(
384 383
 					$question_group->name(),
@@ -392,7 +391,7 @@  discard block
 block discarded – undo
392 391
 			}
393 392
 		}
394 393
 		// group_desc
395
-		if ( $question_group->show_group_desc() && $question_group->desc() !== '' ) {
394
+		if ($question_group->show_group_desc() && $question_group->desc() !== '') {
396 395
 			$html .= EEH_HTML::p(
397 396
 				$question_group->desc(),
398 397
 				'',
@@ -402,7 +401,7 @@  discard block
 block discarded – undo
402 401
 			);
403 402
 
404 403
 		}
405
-		return new EE_Form_Section_HTML( $html );
404
+		return new EE_Form_Section_HTML($html);
406 405
 	}
407 406
 
408 407
 
@@ -412,7 +411,7 @@  discard block
 block discarded – undo
412 411
 	 * @return    EE_Form_Section_Proper
413 412
 	 * @throws \EE_Error
414 413
 	 */
415
-	private function _copy_attendee_info_form(){
414
+	private function _copy_attendee_info_form() {
416 415
 		// array of params to pass to parent constructor
417 416
 		return new EE_Form_Section_Proper(
418 417
 			array(
@@ -441,7 +440,7 @@  discard block
 block discarded – undo
441 440
 	private function _auto_copy_attendee_info() {
442 441
 		return new EE_Form_Section_HTML(
443 442
 			EEH_Template::locate_template(
444
-				SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
443
+				SPCO_REG_STEPS_PATH.$this->_slug.DS.'_auto_copy_attendee_info.template.php',
445 444
 				apply_filters(
446 445
 					'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
447 446
 					array()
@@ -465,32 +464,32 @@  discard block
 block discarded – undo
465 464
 		$copy_attendee_info_inputs = array();
466 465
 		$prev_ticket = NULL;
467 466
 		// grab the saved registrations from the transaction
468
-		$registrations = $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params );
469
-		foreach ( $registrations as $registration ) {
467
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
468
+		foreach ($registrations as $registration) {
470 469
 			// for all  attendees other than the primary attendee
471
-			if ( $registration instanceof EE_Registration && ! $registration->is_primary_registrant() ) {
470
+			if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
472 471
 				// if this is a new ticket OR if this is the very first additional attendee after the primary attendee
473
-				if ( $registration->ticket()->ID() !== $prev_ticket ) {
472
+				if ($registration->ticket()->ID() !== $prev_ticket) {
474 473
 					$item_name = $registration->ticket()->name();
475 474
 					$item_name .= $registration->ticket()->description() !== ''
476
-						? ' - ' . $registration->ticket()->description()
475
+						? ' - '.$registration->ticket()->description()
477 476
 						: '';
478
-					$copy_attendee_info_inputs[ 'spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']' ] = new EE_Form_Section_HTML(
479
-						'<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
477
+					$copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-'.$registration->ticket()->ID().']'] = new EE_Form_Section_HTML(
478
+						'<h6 class="spco-copy-attendee-event-hdr">'.$item_name.'</h6>'
480 479
 					);
481 480
 					$prev_ticket = $registration->ticket()->ID();
482 481
 				}
483 482
 
484
-				$copy_attendee_info_inputs[ 'spco_copy_attendee_chk[' . $registration->ID() . ']' ] = new
483
+				$copy_attendee_info_inputs['spco_copy_attendee_chk['.$registration->ID().']'] = new
485 484
 				EE_Checkbox_Multi_Input(
486 485
 					array(
487 486
 						$registration->ID() => sprintf(
488
-							__( 'Attendee #%s', 'event_espresso' ),
487
+							__('Attendee #%s', 'event_espresso'),
489 488
 							$registration->count()
490 489
 						)
491 490
 					),
492 491
 					array(
493
-						'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
492
+						'html_id'                 => 'spco-copy-attendee-chk-'.$registration->reg_url_link(),
494 493
 						'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
495 494
 						'display_html_label_text' => false
496 495
 					)
@@ -510,7 +509,7 @@  discard block
 block discarded – undo
510 509
 	 * @return    EE_Form_Input_Base
511 510
 	 * @throws \EE_Error
512 511
 	 */
513
-	private function _additional_primary_registrant_inputs( EE_Registration $registration ){
512
+	private function _additional_primary_registrant_inputs(EE_Registration $registration) {
514 513
 		// generate hidden input
515 514
 		return new EE_Hidden_Input(
516 515
 			array(
@@ -529,7 +528,7 @@  discard block
 block discarded – undo
529 528
 	 * @return    EE_Form_Input_Base
530 529
 	 * @throws \EE_Error
531 530
 	 */
532
-	public function reg_form_question( EE_Registration $registration, EE_Question $question ){
531
+	public function reg_form_question(EE_Registration $registration, EE_Question $question) {
533 532
 
534 533
 		// if this question was for an attendee detail, then check for that answer
535 534
 		$answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
@@ -538,32 +537,32 @@  discard block
 block discarded – undo
538 537
 		);
539 538
 		$answer = $answer_value === null
540 539
 			? EEM_Answer::instance()->get_one(
541
-				array( array( 'QST_ID' => $question->ID(), 'REG_ID' => $registration->ID() ) )
540
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
542 541
 			)
543 542
 			: null;
544 543
 		// if NOT returning to edit an existing registration
545 544
 		// OR if this question is for an attendee property
546 545
 		// OR we still don't have an EE_Answer object
547
-		if( $answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link() ) {
546
+		if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
548 547
 			// create an EE_Answer object for storing everything in
549
-			$answer = EE_Answer::new_instance ( array(
548
+			$answer = EE_Answer::new_instance(array(
550 549
 				'QST_ID'=> $question->ID(),
551 550
 				'REG_ID'=> $registration->ID()
552 551
 			));
553 552
 		}
554 553
 		// verify instance
555
-		if( $answer instanceof EE_Answer ){
556
-			if ( ! empty( $answer_value )) {
557
-				$answer->set( 'ANS_value', $answer_value );
554
+		if ($answer instanceof EE_Answer) {
555
+			if ( ! empty($answer_value)) {
556
+				$answer->set('ANS_value', $answer_value);
558 557
 			}
559
-			$answer->cache( 'Question', $question );
558
+			$answer->cache('Question', $question);
560 559
 			//remember system ID had a bug where sometimes it could be null
561
-			$answer_cache_id =$question->is_system_question()
562
-				? $question->system_ID() . '-' . $registration->reg_url_link()
563
-				: $question->ID() . '-' . $registration->reg_url_link();
564
-			$registration->cache( 'Answer', $answer, $answer_cache_id );
560
+			$answer_cache_id = $question->is_system_question()
561
+				? $question->system_ID().'-'.$registration->reg_url_link()
562
+				: $question->ID().'-'.$registration->reg_url_link();
563
+			$registration->cache('Answer', $answer, $answer_cache_id);
565 564
 		}
566
-		return $this->_generate_question_input( $registration, $question, $answer );
565
+		return $this->_generate_question_input($registration, $question, $answer);
567 566
 
568 567
 	}
569 568
 
@@ -576,46 +575,46 @@  discard block
 block discarded – undo
576 575
 	 * @return EE_Form_Input_Base
577 576
 	 * @throws \EE_Error
578 577
 	 */
579
-	private function _generate_question_input( EE_Registration $registration, EE_Question $question, $answer ){
578
+	private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer) {
580 579
 		$identifier = $question->is_system_question() ? $question->system_ID() : $question->ID();
581
-		$this->_required_questions[ $identifier ] = $question->required() ? true : false;
580
+		$this->_required_questions[$identifier] = $question->required() ? true : false;
582 581
 		add_filter(
583 582
 			'FHEE__EE_Question__generate_form_input__country_options',
584
-			array( $this, 'use_cached_countries_for_form_input' ),
583
+			array($this, 'use_cached_countries_for_form_input'),
585 584
 			10,
586 585
 			4
587 586
 		);
588 587
 		add_filter(
589 588
 			'FHEE__EE_Question__generate_form_input__state_options',
590
-			array( $this, 'use_cached_states_for_form_input' ),
589
+			array($this, 'use_cached_states_for_form_input'),
591 590
 			10,
592 591
 			4
593 592
 		);
594 593
 		$input_constructor_args = array(
595
-			'html_name'     => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
596
-			'html_id'       => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
597
-			'html_class'    => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
598
-			'html_label_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
594
+			'html_name'     => 'ee_reg_qstn['.$registration->ID().']['.$identifier.']',
595
+			'html_id'       => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
596
+			'html_class'    => 'ee-reg-qstn ee-reg-qstn-'.$identifier,
597
+			'html_label_id' => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
599 598
 			'html_label_class'	=> 'ee-reg-qstn',
600 599
 		);
601
-		$input_constructor_args['html_label_id'] 	.= '-lbl';
602
-		if ( $answer instanceof EE_Answer && $answer->ID() ) {
603
-			$input_constructor_args[ 'html_name' ] .= '[' . $answer->ID() . ']';
604
-			$input_constructor_args[ 'html_id' ] .= '-' . $answer->ID();
605
-			$input_constructor_args[ 'html_label_id' ] .= '-' . $answer->ID();
600
+		$input_constructor_args['html_label_id'] .= '-lbl';
601
+		if ($answer instanceof EE_Answer && $answer->ID()) {
602
+			$input_constructor_args['html_name'] .= '['.$answer->ID().']';
603
+			$input_constructor_args['html_id'] .= '-'.$answer->ID();
604
+			$input_constructor_args['html_label_id'] .= '-'.$answer->ID();
606 605
 		}
607
-		$form_input =  $question->generate_form_input(
606
+		$form_input = $question->generate_form_input(
608 607
 			$registration,
609 608
 			$answer,
610 609
 			$input_constructor_args
611 610
 		);
612 611
 		remove_filter(
613 612
 			'FHEE__EE_Question__generate_form_input__country_options',
614
-			array( $this, 'use_cached_countries_for_form_input' )
613
+			array($this, 'use_cached_countries_for_form_input')
615 614
 		);
616 615
 		remove_filter(
617 616
 			'FHEE__EE_Question__generate_form_input__state_options',
618
-			array( $this, 'use_cached_states_for_form_input' )
617
+			array($this, 'use_cached_states_for_form_input')
619 618
 		);
620 619
 		return $form_input;
621 620
 	}
@@ -637,22 +636,22 @@  discard block
 block discarded – undo
637 636
 		\EE_Registration $registration = null,
638 637
 		\EE_Answer $answer = null
639 638
 	) {
640
-		$country_options = array( '' => '' );
639
+		$country_options = array('' => '');
641 640
 		// get possibly cached list of countries
642 641
 		$countries = $this->checkout->action === 'process_reg_step'
643 642
 			? EEM_Country::instance()->get_all_countries()
644 643
 			: EEM_Country::instance()->get_all_active_countries();
645
-		if ( ! empty( $countries )) {
646
-			foreach( $countries as $country ){
647
-				if ( $country instanceof EE_Country ) {
648
-					$country_options[ $country->ID() ] = $country->name();
644
+		if ( ! empty($countries)) {
645
+			foreach ($countries as $country) {
646
+				if ($country instanceof EE_Country) {
647
+					$country_options[$country->ID()] = $country->name();
649 648
 				}
650 649
 			}
651 650
 		}
652
-		if( $question instanceof EE_Question
653
-			&& $registration instanceof EE_Registration ) {
651
+		if ($question instanceof EE_Question
652
+			&& $registration instanceof EE_Registration) {
654 653
 			$answer = EEM_Answer::instance()->get_one(
655
-				array( array( 'QST_ID' => $question->ID(), 'REG_ID' => $registration->ID() ) )
654
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
656 655
 			);
657 656
 		} else {
658 657
 			$answer = EE_Answer::new_instance();
@@ -685,14 +684,14 @@  discard block
 block discarded – undo
685 684
 		\EE_Registration $registration = null,
686 685
 		\EE_Answer $answer = null
687 686
 	) {
688
-		$state_options = array( '' => array( '' => ''));
687
+		$state_options = array('' => array('' => ''));
689 688
 		$states = $this->checkout->action === 'process_reg_step'
690 689
 			? EEM_State::instance()->get_all_states()
691 690
 			: EEM_State::instance()->get_all_active_states();
692
-		if ( ! empty( $states )) {
693
-			foreach( $states as $state ){
694
-				if ( $state instanceof EE_State ) {
695
-					$state_options[ $state->country()->name() ][ $state->ID() ] = $state->name();
691
+		if ( ! empty($states)) {
692
+			foreach ($states as $state) {
693
+				if ($state instanceof EE_State) {
694
+					$state_options[$state->country()->name()][$state->ID()] = $state->name();
696 695
 				}
697 696
 			}
698 697
 		}
@@ -720,24 +719,24 @@  discard block
 block discarded – undo
720 719
 	 * @throws \EE_Error
721 720
 	 */
722 721
 	public function process_reg_step() {
723
-		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
722
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
724 723
 		// grab validated data from form
725 724
 		$valid_data = $this->checkout->current_step->valid_data();
726 725
 		// EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
727 726
 		// EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
728 727
 		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
729
-		if ( empty( $valid_data ))  {
728
+		if (empty($valid_data)) {
730 729
 			EE_Error::add_error(
731
-				__( 'No valid question responses were received.', 'event_espresso' ),
730
+				__('No valid question responses were received.', 'event_espresso'),
732 731
 				__FILE__,
733 732
 				__FUNCTION__,
734 733
 				__LINE__
735 734
 			);
736 735
 			return false;
737 736
 		}
738
-		if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg ) {
737
+		if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
739 738
 			EE_Error::add_error(
740
-				__( 'A valid transaction could not be initiated for processing your registrations.', 'event_espresso' ),
739
+				__('A valid transaction could not be initiated for processing your registrations.', 'event_espresso'),
741 740
 				__FILE__,
742 741
 				__FUNCTION__,
743 742
 				__LINE__
@@ -745,11 +744,11 @@  discard block
 block discarded – undo
745 744
 			return false;
746 745
 		}
747 746
 		// get cached registrations
748
-		$registrations = $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params );
747
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
749 748
 		// verify we got the goods
750
-		if ( empty( $registrations )) {
749
+		if (empty($registrations)) {
751 750
 			EE_Error::add_error(
752
-				__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' ),
751
+				__('Your form data could not be applied to any valid registrations.', 'event_espresso'),
753 752
 				__FILE__,
754 753
 				__FUNCTION__,
755 754
 				__LINE__
@@ -757,15 +756,15 @@  discard block
 block discarded – undo
757 756
 			return false;
758 757
 		}
759 758
 		// extract attendee info from form data and save to model objects
760
-		$registrations_processed = $this->_process_registrations( $registrations, $valid_data );
759
+		$registrations_processed = $this->_process_registrations($registrations, $valid_data);
761 760
 		// if first pass thru SPCO,
762 761
 		// then let's check processed registrations against the total number of tickets in the cart
763
-		if ( $registrations_processed === false ) {
762
+		if ($registrations_processed === false) {
764 763
 			// but return immediately if the previous step exited early due to errors
765 764
 			return false;
766
-		} else if ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count ) {
765
+		} else if ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
767 766
 			// generate a correctly translated string for all possible singular/plural combinations
768
-			if ( $this->checkout->total_ticket_count === 1 && $registrations_processed !== 1 ) {
767
+			if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
769 768
 				$error_msg = sprintf(
770 769
 					__(
771 770
 						'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
@@ -774,7 +773,7 @@  discard block
 block discarded – undo
774 773
 					$this->checkout->total_ticket_count,
775 774
 					$registrations_processed
776 775
 				);
777
-			} else if ( $this->checkout->total_ticket_count !== 1 && $registrations_processed === 1 ) {
776
+			} else if ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
778 777
 				$error_msg = sprintf(
779 778
 					__(
780 779
 						'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
@@ -793,17 +792,17 @@  discard block
 block discarded – undo
793 792
 					$registrations_processed
794 793
 				);
795 794
 			}
796
-			EE_Error::add_error( $error_msg, __FILE__, __FUNCTION__, __LINE__ );
795
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
797 796
 			return false;
798 797
 		}
799 798
 		// mark this reg step as completed
800 799
 		$this->set_completed();
801 800
 		$this->_set_success_message(
802
-			__( 'The Attendee Information Step has been successfully completed.', 'event_espresso' )
801
+			__('The Attendee Information Step has been successfully completed.', 'event_espresso')
803 802
 		);
804 803
 		//do action in case a plugin wants to do something with the data submitted in step 1.
805 804
 		//passes EE_Single_Page_Checkout, and it's posted data
806
-		do_action( 'AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data );
805
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
807 806
 		return true;
808 807
 	}
809 808
 
@@ -817,9 +816,9 @@  discard block
 block discarded – undo
817 816
 	 * @return boolean | int
818 817
 	 * @throws \EE_Error
819 818
 	 */
820
-	private function _process_registrations( $registrations = array(), $valid_data = array() ) {
819
+	private function _process_registrations($registrations = array(), $valid_data = array()) {
821 820
 		// load resources and set some defaults
822
-		EE_Registry::instance()->load_model( 'Attendee' );
821
+		EE_Registry::instance()->load_model('Attendee');
823 822
 		// holder for primary registrant attendee object
824 823
 		$this->checkout->primary_attendee_obj = NULL;
825 824
 		// array for tracking reg form data for the primary registrant
@@ -836,9 +835,9 @@  discard block
 block discarded – undo
836 835
 		// attendee counter
837 836
 		$att_nmbr = 0;
838 837
 		// grab the saved registrations from the transaction
839
-		foreach ( $registrations  as $registration ) {
838
+		foreach ($registrations  as $registration) {
840 839
 			// verify EE_Registration object
841
-			if ( ! $registration instanceof EE_Registration ) {
840
+			if ( ! $registration instanceof EE_Registration) {
842 841
 				EE_Error::add_error(
843 842
 					__(
844 843
 						'An invalid Registration object was discovered when attempting to process your registration information.',
@@ -853,12 +852,12 @@  discard block
 block discarded – undo
853 852
 			/** @var string $reg_url_link */
854 853
 			$reg_url_link = $registration->reg_url_link();
855 854
 			// reg_url_link exists ?
856
-			if ( ! empty( $reg_url_link ) ) {
855
+			if ( ! empty($reg_url_link)) {
857 856
 				// should this registration be processed during this visit ?
858
-				if ( $this->checkout->visit_allows_processing_of_this_registration( $registration ) ) {
857
+				if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
859 858
 					// if NOT revisiting, then let's save the registration now,
860 859
 					// so that we have a REG_ID to use when generating other objects
861
-					if ( ! $this->checkout->revisit ) {
860
+					if ( ! $this->checkout->revisit) {
862 861
 						$registration->save();
863 862
 					}
864 863
 					/**
@@ -868,7 +867,7 @@  discard block
 block discarded – undo
868 867
 					 * @var bool   if true is returned by the plugin then the
869 868
 					 *      		registration processing is halted.
870 869
 					 */
871
-					if ( apply_filters(
870
+					if (apply_filters(
872 871
 						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
873 872
 						false,
874 873
 						$att_nmbr,
@@ -876,38 +875,38 @@  discard block
 block discarded – undo
876 875
 						$registrations,
877 876
 						$valid_data,
878 877
 						$this
879
-					) ) {
878
+					)) {
880 879
 						return false;
881 880
 					}
882 881
 
883 882
 					// Houston, we have a registration!
884 883
 					$att_nmbr++;
885
-					$this->_attendee_data[ $reg_url_link ] = array();
884
+					$this->_attendee_data[$reg_url_link] = array();
886 885
 					// grab any existing related answer objects
887 886
 					$this->_registration_answers = $registration->answers();
888 887
 					// unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
889
-					if ( isset( $valid_data[ $reg_url_link ] ) ) {
888
+					if (isset($valid_data[$reg_url_link])) {
890 889
 						// do we need to copy basic info from primary attendee ?
891
-						$copy_primary = isset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] )
892
-						                && absint( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ) === 0
890
+						$copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
891
+						                && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
893 892
 							? true
894 893
 							: false;
895 894
 						// filter form input data for this registration
896
-						$valid_data[ $reg_url_link ] = (array)apply_filters(
895
+						$valid_data[$reg_url_link] = (array) apply_filters(
897 896
 							'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
898
-							$valid_data[ $reg_url_link ]
897
+							$valid_data[$reg_url_link]
899 898
 						);
900 899
 						// EEH_Debug_Tools::printr( $valid_data[ $reg_url_link ], '$valid_data[ $reg_url_link ]', __FILE__, __LINE__ );
901
-						if ( isset( $valid_data['primary_attendee'] )) {
902
-							$primary_registrant['line_item_id'] =  ! empty( $valid_data['primary_attendee'] )
900
+						if (isset($valid_data['primary_attendee'])) {
901
+							$primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
903 902
 								? $valid_data['primary_attendee']
904 903
 								: false;
905
-							unset( $valid_data['primary_attendee'] );
904
+							unset($valid_data['primary_attendee']);
906 905
 						}
907 906
 						// now loop through our array of valid post data && process attendee reg forms
908
-						foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs ) {
909
-							if ( ! in_array( $form_section, $non_input_form_sections )) {
910
-								foreach ( $form_inputs as $form_input => $input_value ) {
907
+						foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
908
+							if ( ! in_array($form_section, $non_input_form_sections)) {
909
+								foreach ($form_inputs as $form_input => $input_value) {
911 910
 									// \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
912 911
 									// check for critical inputs
913 912
 									if (
@@ -921,16 +920,16 @@  discard block
 block discarded – undo
921 920
 									// store a bit of data about the primary attendee
922 921
 									if (
923 922
 										$att_nmbr === 1
924
-										&& ! empty( $input_value )
923
+										&& ! empty($input_value)
925 924
 										&& $reg_url_link === $primary_registrant['line_item_id']
926 925
 									) {
927
-										$primary_registrant[ $form_input ] = $input_value;
926
+										$primary_registrant[$form_input] = $input_value;
928 927
 									} else if (
929 928
 										$copy_primary
930 929
 										&& $input_value === null
931
-										&& isset( $primary_registrant[ $form_input ] )
930
+										&& isset($primary_registrant[$form_input])
932 931
 									) {
933
-										$input_value = $primary_registrant[ $form_input ];
932
+										$input_value = $primary_registrant[$form_input];
934 933
 									}
935 934
 									// now attempt to save the input data
936 935
 									if (
@@ -972,55 +971,55 @@  discard block
 block discarded – undo
972 971
 						// have we met before?
973 972
 						$attendee = $this->_find_existing_attendee(
974 973
 							$registration,
975
-							$this->_attendee_data[ $reg_url_link ]
974
+							$this->_attendee_data[$reg_url_link]
976 975
 						);
977 976
 						// did we find an already existing record for this attendee ?
978
-						if ( $attendee instanceof EE_Attendee ) {
977
+						if ($attendee instanceof EE_Attendee) {
979 978
 							$attendee = $this->_update_existing_attendee_data(
980 979
 								$attendee,
981
-								$this->_attendee_data[ $reg_url_link ]
980
+								$this->_attendee_data[$reg_url_link]
982 981
 							);
983 982
 						} else {
984 983
 							// ensure critical details are set for additional attendees
985
-							$this->_attendee_data[ $reg_url_link ] = $att_nmbr > 1
984
+							$this->_attendee_data[$reg_url_link] = $att_nmbr > 1
986 985
 								? $this->_copy_critical_attendee_details_from_primary_registrant(
987
-									$this->_attendee_data[ $reg_url_link ]
986
+									$this->_attendee_data[$reg_url_link]
988 987
 								)
989
-								: $this->_attendee_data[ $reg_url_link ];
988
+								: $this->_attendee_data[$reg_url_link];
990 989
 							$attendee = $this->_create_new_attendee(
991 990
 								$registration,
992
-								$this->_attendee_data[ $reg_url_link ]
991
+								$this->_attendee_data[$reg_url_link]
993 992
 							);
994 993
 						}
995 994
 						// who's #1 ?
996
-						if ( $att_nmbr === 1 ) {
995
+						if ($att_nmbr === 1) {
997 996
 							$this->checkout->primary_attendee_obj = $attendee;
998 997
 						}
999 998
 					}
1000 999
 					// EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1001 1000
 					// add relation to registration, set attendee ID, and cache attendee
1002
-					$this->_associate_attendee_with_registration( $registration, $attendee );
1001
+					$this->_associate_attendee_with_registration($registration, $attendee);
1003 1002
 					// \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1004
-					if ( ! $registration->attendee() instanceof EE_Attendee ) {
1005
-						EE_Error::add_error( sprintf( __( 'Registration %s has an invalid or missing Attendee object.', 'event_espresso' ), $reg_url_link ), __FILE__, __FUNCTION__, __LINE__ );
1003
+					if ( ! $registration->attendee() instanceof EE_Attendee) {
1004
+						EE_Error::add_error(sprintf(__('Registration %s has an invalid or missing Attendee object.', 'event_espresso'), $reg_url_link), __FILE__, __FUNCTION__, __LINE__);
1006 1005
 						return false;
1007 1006
 					}
1008 1007
 					/** @type EE_Registration_Processor $registration_processor */
1009
-					$registration_processor = EE_Registry::instance()->load_class( 'Registration_Processor' );
1008
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1010 1009
 					// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
1011
-					$registration_processor->toggle_incomplete_registration_status_to_default( $registration, false );
1010
+					$registration_processor->toggle_incomplete_registration_status_to_default($registration, false);
1012 1011
 					// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1013 1012
 					$this->checkout->transaction->toggle_failed_transaction_status();
1014 1013
 					// if we've gotten this far, then let's save what we have
1015 1014
 					$registration->save();
1016 1015
 					// add relation between TXN and registration
1017
-					$this->_associate_registration_with_transaction( $registration );
1016
+					$this->_associate_registration_with_transaction($registration);
1018 1017
 				} // end of if ( ! $this->checkout->revisit || $this->checkout->primary_revisit || ( $this->checkout->revisit && $this->checkout->reg_url_link == $reg_url_link )) {
1019 1018
 
1020
-			}  else {
1021
-				EE_Error::add_error( __( 'An invalid or missing line item ID was encountered while attempting to process the registration form.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
1019
+			} else {
1020
+				EE_Error::add_error(__('An invalid or missing line item ID was encountered while attempting to process the registration form.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1022 1021
 				// remove malformed data
1023
-				unset( $valid_data[ $reg_url_link ] );
1022
+				unset($valid_data[$reg_url_link]);
1024 1023
 				return false;
1025 1024
 			}
1026 1025
 
@@ -1049,26 +1048,26 @@  discard block
 block discarded – undo
1049 1048
 		// \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1050 1049
 		// allow for plugins to hook in and do their own processing of the form input.
1051 1050
 		// For plugins to bypass normal processing here, they just need to return a boolean value.
1052
-		if ( apply_filters(
1051
+		if (apply_filters(
1053 1052
 			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1054 1053
 			false,
1055 1054
 			$registration,
1056 1055
 			$form_input,
1057 1056
 			$input_value,
1058 1057
 			$this
1059
-		) ) {
1058
+		)) {
1060 1059
 			return true;
1061 1060
 		}
1062 1061
 		// $answer_cache_id is the key used to find the EE_Answer we want
1063 1062
 		$answer_cache_id = $this->checkout->reg_url_link
1064 1063
 			? $form_input
1065
-			: $form_input . '-' . $registration->reg_url_link();
1066
-		$answer_is_obj = isset( $this->_registration_answers[ $answer_cache_id ] )
1067
-		                 && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer
1064
+			: $form_input.'-'.$registration->reg_url_link();
1065
+		$answer_is_obj = isset($this->_registration_answers[$answer_cache_id])
1066
+		                 && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1068 1067
 			? true
1069 1068
 			: false;
1070 1069
 		//rename form_inputs if they are EE_Attendee properties
1071
-		switch( (string)$form_input ) {
1070
+		switch ((string) $form_input) {
1072 1071
 
1073 1072
 			case 'state' :
1074 1073
 			case 'STA_ID' :
@@ -1083,32 +1082,32 @@  discard block
 block discarded – undo
1083 1082
 				break;
1084 1083
 
1085 1084
 			default :
1086
-				$ATT_input = 'ATT_' . $form_input;
1085
+				$ATT_input = 'ATT_'.$form_input;
1087 1086
 				//EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1088
-				$attendee_property = EEM_Attendee::instance()->has_field( $ATT_input ) ? true : false;
1089
-				$form_input = $attendee_property ? 'ATT_' . $form_input : $form_input;
1087
+				$attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1088
+				$form_input = $attendee_property ? 'ATT_'.$form_input : $form_input;
1090 1089
 		}
1091 1090
 		// EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1092 1091
 		// EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1093 1092
 		// EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1094 1093
 		// if this form input has a corresponding attendee property
1095
-		if ( $attendee_property ) {
1096
-			$this->_attendee_data[ $registration->reg_url_link() ][ $form_input ] = $input_value;
1097
-			if ( $answer_is_obj ) {
1094
+		if ($attendee_property) {
1095
+			$this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1096
+			if ($answer_is_obj) {
1098 1097
 				// and delete the corresponding answer since we won't be storing this data in that object
1099
-				$registration->_remove_relation_to( $this->_registration_answers[ $answer_cache_id ], 'Answer' );
1100
-				$this->_registration_answers[ $answer_cache_id ]->delete_permanently();
1098
+				$registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1099
+				$this->_registration_answers[$answer_cache_id]->delete_permanently();
1101 1100
 			}
1102 1101
 			return true;
1103
-		} elseif ( $answer_is_obj ) {
1102
+		} elseif ($answer_is_obj) {
1104 1103
 			// save this data to the answer object
1105
-			$this->_registration_answers[ $answer_cache_id ]->set_value( $input_value );
1106
-			$result = $this->_registration_answers[ $answer_cache_id ]->save();
1104
+			$this->_registration_answers[$answer_cache_id]->set_value($input_value);
1105
+			$result = $this->_registration_answers[$answer_cache_id]->save();
1107 1106
 			return $result !== false ? true : false;
1108 1107
 		} else {
1109
-			foreach ( $this->_registration_answers as $answer ) {
1110
-				if ( $answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id ) {
1111
-					$answer->set_value( $input_value );
1108
+			foreach ($this->_registration_answers as $answer) {
1109
+				if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1110
+					$answer->set_value($input_value);
1112 1111
 					$result = $answer->save();
1113 1112
 					return $result !== false ? true : false;
1114 1113
 				}
@@ -1130,15 +1129,15 @@  discard block
 block discarded – undo
1130 1129
 		$form_input = '',
1131 1130
 		$input_value = ''
1132 1131
 	) {
1133
-		if ( empty( $input_value ) ) {
1132
+		if (empty($input_value)) {
1134 1133
 			// if the form input isn't marked as being required, then just return
1135
-			if ( ! isset( $this->_required_questions[ $form_input ] ) || ! $this->_required_questions[ $form_input ] ) {
1134
+			if ( ! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1136 1135
 				return true;
1137 1136
 			}
1138
-			switch ( $form_input ) {
1137
+			switch ($form_input) {
1139 1138
 				case 'fname' :
1140 1139
 					EE_Error::add_error(
1141
-						__( 'First Name is a required value.', 'event_espresso' ),
1140
+						__('First Name is a required value.', 'event_espresso'),
1142 1141
 						__FILE__,
1143 1142
 						__FUNCTION__,
1144 1143
 						__LINE__
@@ -1147,7 +1146,7 @@  discard block
 block discarded – undo
1147 1146
 					break;
1148 1147
 				case 'lname' :
1149 1148
 					EE_Error::add_error(
1150
-						__( 'Last Name is a required value.', 'event_espresso' ),
1149
+						__('Last Name is a required value.', 'event_espresso'),
1151 1150
 						__FILE__,
1152 1151
 						__FUNCTION__,
1153 1152
 						__LINE__
@@ -1156,7 +1155,7 @@  discard block
 block discarded – undo
1156 1155
 					break;
1157 1156
 				case 'email' :
1158 1157
 					EE_Error::add_error(
1159
-						__( 'Please enter a valid email address.', 'event_espresso' ),
1158
+						__('Please enter a valid email address.', 'event_espresso'),
1160 1159
 						__FILE__,
1161 1160
 						__FUNCTION__,
1162 1161
 						__LINE__
@@ -1178,30 +1177,30 @@  discard block
 block discarded – undo
1178 1177
 	 * @return boolean|EE_Attendee
1179 1178
 	 * @throws \EE_Error
1180 1179
 	 */
1181
-	private function _find_existing_attendee( EE_Registration $registration, $attendee_data = array() ) {
1180
+	private function _find_existing_attendee(EE_Registration $registration, $attendee_data = array()) {
1182 1181
 		$existing_attendee = null;
1183 1182
 		// if none of the critical properties are set in the incoming attendee data...
1184 1183
 		// then attempt to copy them from the primary attendee
1185 1184
 		if (
1186 1185
 			$this->checkout->primary_attendee_obj instanceof EE_Attendee
1187
-            && ! isset( $attendee_data['ATT_fname'], $attendee_data['ATT_email'] )
1186
+            && ! isset($attendee_data['ATT_fname'], $attendee_data['ATT_email'])
1188 1187
 		) {
1189 1188
 			return $this->checkout->primary_attendee_obj;
1190 1189
 		}
1191 1190
 		// does this attendee already exist in the db ?
1192 1191
 		// we're searching using a combination of first name, last name, AND email address
1193
-		$ATT_fname = isset( $attendee_data['ATT_fname'] ) && ! empty( $attendee_data['ATT_fname'] )
1192
+		$ATT_fname = isset($attendee_data['ATT_fname']) && ! empty($attendee_data['ATT_fname'])
1194 1193
 			? $attendee_data['ATT_fname']
1195 1194
 			: '';
1196
-		$ATT_lname = isset( $attendee_data['ATT_lname'] ) && ! empty( $attendee_data['ATT_lname'] )
1195
+		$ATT_lname = isset($attendee_data['ATT_lname']) && ! empty($attendee_data['ATT_lname'])
1197 1196
 			? $attendee_data['ATT_lname']
1198 1197
 			: '';
1199
-		$ATT_email = isset( $attendee_data['ATT_email'] ) && ! empty( $attendee_data['ATT_email'] )
1198
+		$ATT_email = isset($attendee_data['ATT_email']) && ! empty($attendee_data['ATT_email'])
1200 1199
 			? $attendee_data['ATT_email']
1201 1200
 			: '';
1202 1201
 		// but only if those have values
1203
-		if ( $ATT_fname && $ATT_lname && $ATT_email ) {
1204
-			$existing_attendee = EEM_Attendee::instance()->find_existing_attendee( array(
1202
+		if ($ATT_fname && $ATT_lname && $ATT_email) {
1203
+			$existing_attendee = EEM_Attendee::instance()->find_existing_attendee(array(
1205 1204
 				'ATT_fname' => $ATT_fname,
1206 1205
 				'ATT_lname' => $ATT_lname,
1207 1206
 				'ATT_email' => $ATT_email
@@ -1225,13 +1224,13 @@  discard block
 block discarded – undo
1225 1224
 	 * @return \EE_Attendee
1226 1225
 	 * @throws \EE_Error
1227 1226
 	 */
1228
-	private function _update_existing_attendee_data( EE_Attendee $existing_attendee, $attendee_data = array() ) {
1227
+	private function _update_existing_attendee_data(EE_Attendee $existing_attendee, $attendee_data = array()) {
1229 1228
 		// first remove fname, lname, and email from attendee data
1230
-		$dont_set = array( 'ATT_fname', 'ATT_lname', 'ATT_email' );
1229
+		$dont_set = array('ATT_fname', 'ATT_lname', 'ATT_email');
1231 1230
 		// now loop thru what's left and add to attendee CPT
1232
-		foreach ( $attendee_data as $property_name => $property_value ) {
1233
-			if ( ! in_array( $property_name, $dont_set ) && EEM_Attendee::instance()->has_field( $property_name )) {
1234
-				$existing_attendee->set( $property_name, $property_value );
1231
+		foreach ($attendee_data as $property_name => $property_value) {
1232
+			if ( ! in_array($property_name, $dont_set) && EEM_Attendee::instance()->has_field($property_name)) {
1233
+				$existing_attendee->set($property_name, $property_value);
1235 1234
 			}
1236 1235
 		}
1237 1236
 		// better save that now
@@ -1249,11 +1248,11 @@  discard block
 block discarded – undo
1249 1248
 	 * @return void
1250 1249
 	 * @throws \EE_Error
1251 1250
 	 */
1252
-	private function _associate_attendee_with_registration( EE_Registration $registration, EE_Attendee $attendee ) {
1251
+	private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee) {
1253 1252
 		// add relation to attendee
1254
-		$registration->_add_relation_to( $attendee, 'Attendee' );
1255
-		$registration->set_attendee_id( $attendee->ID() );
1256
-		$registration->update_cache_after_object_save( 'Attendee', $attendee );
1253
+		$registration->_add_relation_to($attendee, 'Attendee');
1254
+		$registration->set_attendee_id($attendee->ID());
1255
+		$registration->update_cache_after_object_save('Attendee', $attendee);
1257 1256
 	}
1258 1257
 
1259 1258
 
@@ -1265,10 +1264,10 @@  discard block
 block discarded – undo
1265 1264
 	 * @return void
1266 1265
 	 * @throws \EE_Error
1267 1266
 	 */
1268
-	private function _associate_registration_with_transaction( EE_Registration $registration ) {
1267
+	private function _associate_registration_with_transaction(EE_Registration $registration) {
1269 1268
 		// add relation to attendee
1270
-		$this->checkout->transaction->_add_relation_to( $registration, 'Registration' );
1271
-		$this->checkout->transaction->update_cache_after_object_save( 'Registration', $registration );
1269
+		$this->checkout->transaction->_add_relation_to($registration, 'Registration');
1270
+		$this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1272 1271
 	}
1273 1272
 
1274 1273
 
@@ -1281,14 +1280,14 @@  discard block
 block discarded – undo
1281 1280
 	 * @return array
1282 1281
 	 * @throws \EE_Error
1283 1282
 	 */
1284
-	private function _copy_critical_attendee_details_from_primary_registrant( $attendee_data = array() ) {
1283
+	private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array()) {
1285 1284
 		// bare minimum critical details include first name, last name, email address
1286
-		$critical_attendee_details = array( 'ATT_fname', 'ATT_lname', 'ATT_email' );
1285
+		$critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1287 1286
 		// add address info to critical details?
1288
-		if ( apply_filters(
1287
+		if (apply_filters(
1289 1288
 			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1290 1289
 			false
1291
-		) ) {
1290
+		)) {
1292 1291
 			$address_details = array(
1293 1292
 				'ATT_address',
1294 1293
 				'ATT_address2',
@@ -1298,13 +1297,13 @@  discard block
 block discarded – undo
1298 1297
 				'ATT_zip',
1299 1298
 				'ATT_phone'
1300 1299
 			);
1301
-			$critical_attendee_details = array_merge( $critical_attendee_details, $address_details );
1300
+			$critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1302 1301
 		}
1303
-		foreach ( $critical_attendee_details as $critical_attendee_detail ) {
1304
-			if ( ! isset( $attendee_data[ $critical_attendee_detail ] )
1305
-			     || empty( $attendee_data[ $critical_attendee_detail ] )
1302
+		foreach ($critical_attendee_details as $critical_attendee_detail) {
1303
+			if ( ! isset($attendee_data[$critical_attendee_detail])
1304
+			     || empty($attendee_data[$critical_attendee_detail])
1306 1305
 			) {
1307
-				$attendee_data[ $critical_attendee_detail ] = $this->checkout->primary_attendee_obj->get(
1306
+				$attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1308 1307
 					$critical_attendee_detail
1309 1308
 				);
1310 1309
 			}
@@ -1322,11 +1321,11 @@  discard block
 block discarded – undo
1322 1321
 	 * @return \EE_Attendee
1323 1322
 	 * @throws \EE_Error
1324 1323
 	 */
1325
-	private function _create_new_attendee( EE_Registration $registration, $attendee_data = array() ) {
1324
+	private function _create_new_attendee(EE_Registration $registration, $attendee_data = array()) {
1326 1325
 		// create new attendee object
1327
-		$new_attendee = EE_Attendee::new_instance( $attendee_data );
1326
+		$new_attendee = EE_Attendee::new_instance($attendee_data);
1328 1327
 		// set author to event creator
1329
-		$new_attendee->set( 'ATT_author', $registration->event()->wp_user() );
1328
+		$new_attendee->set('ATT_author', $registration->event()->wp_user());
1330 1329
 		$new_attendee->save();
1331 1330
 		return $new_attendee;
1332 1331
 	}
@@ -1343,7 +1342,7 @@  discard block
 block discarded – undo
1343 1342
 	 */
1344 1343
 	public function update_reg_step() {
1345 1344
 		// save everything
1346
-		if ( $this->process_reg_step() ) {
1345
+		if ($this->process_reg_step()) {
1347 1346
 			$this->checkout->redirect = true;
1348 1347
 			$this->checkout->redirect_url = add_query_arg(
1349 1348
 				array(
@@ -1352,7 +1351,7 @@  discard block
 block discarded – undo
1352 1351
 				),
1353 1352
 				$this->checkout->thank_you_page_url
1354 1353
 			);
1355
-			$this->checkout->json_response->set_redirect_url( $this->checkout->redirect_url );
1354
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1356 1355
 			return true;
1357 1356
 		}
1358 1357
 		return false;
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 2 patches
Indentation   +1704 added lines, -1704 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\exceptions\InvalidEntityException;
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
 
@@ -17,1709 +17,1709 @@  discard block
 block discarded – undo
17 17
 class EED_Single_Page_Checkout extends EED_Module
18 18
 {
19 19
 
20
-    /**
21
-     * $_initialized - has the SPCO controller already been initialized ?
22
-     *
23
-     * @access private
24
-     * @var bool $_initialized
25
-     */
26
-    private static $_initialized = false;
27
-
28
-
29
-    /**
30
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
31
-     *
32
-     * @access private
33
-     * @var bool $_valid_checkout
34
-     */
35
-    private static $_checkout_verified = true;
36
-
37
-    /**
38
-     *    $_reg_steps_array - holds initial array of reg steps
39
-     *
40
-     * @access private
41
-     * @var array $_reg_steps_array
42
-     */
43
-    private static $_reg_steps_array = array();
44
-
45
-    /**
46
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
47
-     *
48
-     * @access public
49
-     * @var EE_Checkout $checkout
50
-     */
51
-    public $checkout;
52
-
53
-
54
-
55
-    /**
56
-     * @return EED_Single_Page_Checkout
57
-     */
58
-    public static function instance()
59
-    {
60
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
61
-        return parent::get_instance(__CLASS__);
62
-    }
63
-
64
-
65
-
66
-    /**
67
-     * @return EE_CART
68
-     */
69
-    public function cart()
70
-    {
71
-        return $this->checkout->cart;
72
-    }
73
-
74
-
75
-
76
-    /**
77
-     * @return EE_Transaction
78
-     */
79
-    public function transaction()
80
-    {
81
-        return $this->checkout->transaction;
82
-    }
83
-
84
-
85
-
86
-    /**
87
-     *    set_hooks - for hooking into EE Core, other modules, etc
88
-     *
89
-     * @access    public
90
-     * @return    void
91
-     * @throws \EE_Error
92
-     */
93
-    public static function set_hooks()
94
-    {
95
-        EED_Single_Page_Checkout::set_definitions();
96
-    }
97
-
98
-
99
-
100
-    /**
101
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
102
-     *
103
-     * @access    public
104
-     * @return    void
105
-     * @throws \EE_Error
106
-     */
107
-    public static function set_hooks_admin()
108
-    {
109
-        EED_Single_Page_Checkout::set_definitions();
110
-        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
111
-            // hook into the top of pre_get_posts to set the reg step routing, which gives other modules or plugins a chance to modify the reg steps, but just before the routes get called
112
-            add_action('pre_get_posts', array('EED_Single_Page_Checkout', 'load_reg_steps'), 1);
113
-            return;
114
-        }
115
-        // going to start an output buffer in case anything gets accidentally output that might disrupt our JSON response
116
-        ob_start();
117
-        EED_Single_Page_Checkout::load_request_handler();
118
-        EED_Single_Page_Checkout::load_reg_steps();
119
-        // set ajax hooks
120
-        add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
121
-        add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
122
-        add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
123
-        add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
124
-        add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
125
-        add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
126
-    }
127
-
128
-
129
-
130
-    /**
131
-     *    process ajax request
132
-     *
133
-     * @param string $ajax_action
134
-     * @throws \EE_Error
135
-     */
136
-    public static function process_ajax_request($ajax_action)
137
-    {
138
-        EE_Registry::instance()->REQ->set('action', $ajax_action);
139
-        EED_Single_Page_Checkout::instance()->_initialize();
140
-    }
141
-
142
-
143
-
144
-    /**
145
-     *    ajax display registration step
146
-     *
147
-     * @throws \EE_Error
148
-     */
149
-    public static function display_reg_step()
150
-    {
151
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
152
-    }
153
-
154
-
155
-
156
-    /**
157
-     *    ajax process registration step
158
-     *
159
-     * @throws \EE_Error
160
-     */
161
-    public static function process_reg_step()
162
-    {
163
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     *    ajax process registration step
170
-     *
171
-     * @throws \EE_Error
172
-     */
173
-    public static function update_reg_step()
174
-    {
175
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
176
-    }
177
-
178
-
179
-
180
-    /**
181
-     *   update_checkout
182
-     *
183
-     * @access public
184
-     * @return void
185
-     * @throws \EE_Error
186
-     */
187
-    public static function update_checkout()
188
-    {
189
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
190
-    }
191
-
192
-
193
-
194
-    /**
195
-     *    load_request_handler
196
-     *
197
-     * @access    public
198
-     * @return    void
199
-     */
200
-    public static function load_request_handler()
201
-    {
202
-        // load core Request_Handler class
203
-        if ( ! isset(EE_Registry::instance()->REQ)) {
204
-            EE_Registry::instance()->load_core('Request_Handler');
205
-        }
206
-    }
207
-
208
-
209
-
210
-    /**
211
-     *    set_definitions
212
-     *
213
-     * @access    public
214
-     * @return    void
215
-     * @throws \EE_Error
216
-     */
217
-    public static function set_definitions()
218
-    {
219
-        define('SPCO_BASE_PATH', rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS);
220
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
221
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
222
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
223
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
224
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
225
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
226
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
227
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
228
-            __('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
229
-                'event_espresso'),
230
-            '<h4 class="important-notice">',
231
-            '</h4>',
232
-            '<br />',
233
-            '<p>',
234
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
235
-            '">',
236
-            '</a>',
237
-            '</p>'
238
-        );
239
-    }
240
-
241
-
242
-
243
-    /**
244
-     * load_reg_steps
245
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
246
-     *
247
-     * @access    private
248
-     * @throws EE_Error
249
-     * @return void
250
-     */
251
-    public static function load_reg_steps()
252
-    {
253
-        static $reg_steps_loaded = false;
254
-        if ($reg_steps_loaded) {
255
-            return;
256
-        }
257
-        // filter list of reg_steps
258
-        $reg_steps_to_load = (array)apply_filters(
259
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
260
-            EED_Single_Page_Checkout::get_reg_steps()
261
-        );
262
-        // sort by key (order)
263
-        ksort($reg_steps_to_load);
264
-        // loop through folders
265
-        foreach ($reg_steps_to_load as $order => $reg_step) {
266
-            // we need a
267
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
268
-                // copy over to the reg_steps_array
269
-                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
270
-                // register custom key route for each reg step
271
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
272
-                EE_Config::register_route($reg_step['slug'], 'EED_Single_Page_Checkout', 'run', 'step');
273
-                // add AJAX or other hooks
274
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
275
-                    // setup autoloaders if necessary
276
-                    if ( ! class_exists($reg_step['class_name'])) {
277
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder($reg_step['file_path'], true);
278
-                    }
279
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
280
-                        call_user_func(array($reg_step['class_name'], 'set_hooks'));
281
-                    }
282
-                }
283
-            }
284
-        }
285
-        $reg_steps_loaded = true;
286
-    }
287
-
288
-
289
-
290
-    /**
291
-     *    get_reg_steps
292
-     *
293
-     * @access    public
294
-     * @return    array
295
-     */
296
-    public static function get_reg_steps()
297
-    {
298
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
299
-        if (empty($reg_steps)) {
300
-            $reg_steps = array(
301
-                10  => array(
302
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
303
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
304
-                    'slug'       => 'attendee_information',
305
-                    'has_hooks'  => false,
306
-                ),
307
-                20  => array(
308
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
309
-                    'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
310
-                    'slug'       => 'registration_confirmation',
311
-                    'has_hooks'  => false,
312
-                ),
313
-                30  => array(
314
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
315
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
316
-                    'slug'       => 'payment_options',
317
-                    'has_hooks'  => true,
318
-                ),
319
-                999 => array(
320
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
321
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
322
-                    'slug'       => 'finalize_registration',
323
-                    'has_hooks'  => false,
324
-                ),
325
-            );
326
-        }
327
-        return $reg_steps;
328
-    }
329
-
330
-
331
-
332
-    /**
333
-     *    registration_checkout_for_admin
334
-     *
335
-     * @access    public
336
-     * @return    string
337
-     * @throws \EE_Error
338
-     */
339
-    public static function registration_checkout_for_admin()
340
-    {
341
-        EED_Single_Page_Checkout::load_reg_steps();
342
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
343
-        EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
344
-        EE_Registry::instance()->REQ->set('process_form_submission', false);
345
-        EED_Single_Page_Checkout::instance()->_initialize();
346
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
347
-        return EE_Registry::instance()->REQ->get_output();
348
-    }
349
-
350
-
351
-
352
-    /**
353
-     * process_registration_from_admin
354
-     *
355
-     * @access public
356
-     * @return \EE_Transaction
357
-     * @throws \EE_Error
358
-     */
359
-    public static function process_registration_from_admin()
360
-    {
361
-        EED_Single_Page_Checkout::load_reg_steps();
362
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
363
-        EE_Registry::instance()->REQ->set('action', 'process_reg_step');
364
-        EE_Registry::instance()->REQ->set('process_form_submission', true);
365
-        EED_Single_Page_Checkout::instance()->_initialize();
366
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
367
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
368
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
369
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
370
-                if ($final_reg_step->process_reg_step()) {
371
-                    $final_reg_step->set_completed();
372
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
373
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
374
-                }
375
-            }
376
-        }
377
-        return null;
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     *    run
384
-     *
385
-     * @access    public
386
-     * @param WP_Query $WP_Query
387
-     * @return    void
388
-     * @throws \EE_Error
389
-     */
390
-    public function run($WP_Query)
391
-    {
392
-        if (
393
-            $WP_Query instanceof WP_Query
394
-            && $WP_Query->is_main_query()
395
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
396
-            && $this->_is_reg_checkout()
397
-        ) {
398
-            $this->_initialize();
399
-        }
400
-    }
401
-
402
-
403
-
404
-    /**
405
-     * determines whether current url matches reg page url
406
-     *
407
-     * @return bool
408
-     */
409
-    protected function _is_reg_checkout()
410
-    {
411
-        // get current permalink for reg page without any extra query args
412
-        $reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
413
-        // get request URI for current request, but without the scheme or host
414
-        $current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
415
-        $current_request_uri = html_entity_decode($current_request_uri);
416
-        // get array of query args from the current request URI
417
-        $query_args = \EEH_URL::get_query_string($current_request_uri);
418
-        // grab page id if it is set
419
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
420
-        // and remove the page id from the query args (we will re-add it later)
421
-        unset($query_args['page_id']);
422
-        // now strip all query args from current request URI
423
-        $current_request_uri = remove_query_arg(array_flip($query_args), $current_request_uri);
424
-        // and re-add the page id if it was set
425
-        if ($page_id) {
426
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
427
-        }
428
-        // remove slashes and ?
429
-        $current_request_uri = trim($current_request_uri, '?/');
430
-        // is current request URI part of the known full reg page URL ?
431
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
432
-    }
433
-
434
-
435
-
436
-    /**
437
-     *    run
438
-     *
439
-     * @access    public
440
-     * @param WP_Query $WP_Query
441
-     * @return    void
442
-     * @throws \EE_Error
443
-     */
444
-    public static function init($WP_Query)
445
-    {
446
-        EED_Single_Page_Checkout::instance()->run($WP_Query);
447
-    }
448
-
449
-
450
-
451
-    /**
452
-     *    _initialize - initial module setup
453
-     *
454
-     * @access    private
455
-     * @throws EE_Error
456
-     * @return    void
457
-     */
458
-    private function _initialize()
459
-    {
460
-        // ensure SPCO doesn't run twice
461
-        if (EED_Single_Page_Checkout::$_initialized) {
462
-            return;
463
-        }
464
-        try {
465
-            $this->_verify_session();
466
-            // setup the EE_Checkout object
467
-            $this->checkout = $this->_initialize_checkout();
468
-            // filter checkout
469
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
470
-            // get the $_GET
471
-            $this->_get_request_vars();
472
-            if ($this->_block_bots()) {
473
-                return;
474
-            }
475
-            // filter continue_reg
476
-            $this->checkout->continue_reg = apply_filters('FHEE__EED_Single_Page_Checkout__init___continue_reg', true, $this->checkout);
477
-            // load the reg steps array
478
-            if ( ! $this->_load_and_instantiate_reg_steps()) {
479
-                EED_Single_Page_Checkout::$_initialized = true;
480
-                return;
481
-            }
482
-            // set the current step
483
-            $this->checkout->set_current_step($this->checkout->step);
484
-            // and the next step
485
-            $this->checkout->set_next_step();
486
-            // verify that everything has been setup correctly
487
-            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
488
-                EED_Single_Page_Checkout::$_initialized = true;
489
-                return;
490
-            }
491
-            // lock the transaction
492
-            $this->checkout->transaction->lock();
493
-            // make sure all of our cached objects are added to their respective model entity mappers
494
-            $this->checkout->refresh_all_entities();
495
-            // set amount owing
496
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
497
-            // initialize each reg step, which gives them the chance to potentially alter the process
498
-            $this->_initialize_reg_steps();
499
-            // DEBUG LOG
500
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
501
-            // get reg form
502
-            if( ! $this->_check_form_submission()) {
503
-                EED_Single_Page_Checkout::$_initialized = true;
504
-                return;
505
-            }
506
-            // checkout the action!!!
507
-            $this->_process_form_action();
508
-            // add some style and make it dance
509
-            $this->add_styles_and_scripts();
510
-            // kk... SPCO has successfully run
511
-            EED_Single_Page_Checkout::$_initialized = true;
512
-            // set no cache headers and constants
513
-            EE_System::do_not_cache();
514
-            // add anchor
515
-            add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
516
-            // remove transaction lock
517
-            add_action('shutdown', array($this, 'unlock_transaction'), 1);
518
-        } catch (Exception $e) {
519
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
520
-        }
521
-    }
522
-
523
-
524
-
525
-    /**
526
-     *    _verify_session
527
-     * checks that the session is valid and not expired
528
-     *
529
-     * @access    private
530
-     * @throws EE_Error
531
-     */
532
-    private function _verify_session()
533
-    {
534
-        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
535
-            throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
536
-        }
537
-        // is session still valid ?
538
-        if (EE_Registry::instance()->SSN->expired() && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === '') {
539
-            $this->checkout = new EE_Checkout();
540
-            EE_Registry::instance()->SSN->reset_cart();
541
-            EE_Registry::instance()->SSN->reset_checkout();
542
-            EE_Registry::instance()->SSN->reset_transaction();
543
-            EE_Error::add_attention(EE_Registry::$i18n_js_strings['registration_expiration_notice'], __FILE__,
544
-                __FUNCTION__, __LINE__);
545
-            EE_Registry::instance()->SSN->reset_expired();
546
-        }
547
-    }
548
-
549
-
550
-
551
-    /**
552
-     *    _initialize_checkout
553
-     * loads and instantiates EE_Checkout
554
-     *
555
-     * @access    private
556
-     * @throws EE_Error
557
-     * @return EE_Checkout
558
-     */
559
-    private function _initialize_checkout()
560
-    {
561
-        // look in session for existing checkout
562
-        /** @type EE_Checkout $checkout */
563
-        $checkout = EE_Registry::instance()->SSN->checkout();
564
-        // verify
565
-        if ( ! $checkout instanceof EE_Checkout) {
566
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
567
-            $checkout = EE_Registry::instance()->load_file(SPCO_INC_PATH, 'EE_Checkout', 'class', array(), false);
568
-        } else {
569
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
570
-                $this->unlock_transaction();
571
-                wp_safe_redirect($checkout->redirect_url);
572
-                exit();
573
-            }
574
-        }
575
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
576
-        // verify again
577
-        if ( ! $checkout instanceof EE_Checkout) {
578
-            throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
579
-        }
580
-        // reset anything that needs a clean slate for each request
581
-        $checkout->reset_for_current_request();
582
-        return $checkout;
583
-    }
584
-
585
-
586
-
587
-    /**
588
-     *    _get_request_vars
589
-     *
590
-     * @access    private
591
-     * @return    void
592
-     * @throws \EE_Error
593
-     */
594
-    private function _get_request_vars()
595
-    {
596
-        // load classes
597
-        EED_Single_Page_Checkout::load_request_handler();
598
-        //make sure this request is marked as belonging to EE
599
-        EE_Registry::instance()->REQ->set_espresso_page(true);
600
-        // which step is being requested ?
601
-        $this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
602
-        // which step is being edited ?
603
-        $this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
604
-        // and what we're doing on the current step
605
-        $this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
606
-        // timestamp
607
-        $this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
608
-        // returning to edit ?
609
-        $this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
610
-        // or some other kind of revisit ?
611
-        $this->checkout->revisit = filter_var(
612
-            EE_Registry::instance()->REQ->get('revisit', false),
613
-            FILTER_VALIDATE_BOOLEAN
614
-        );
615
-        // and whether or not to generate a reg form for this request
616
-        $this->checkout->generate_reg_form = filter_var(
617
-            EE_Registry::instance()->REQ->get('generate_reg_form', true),
618
-            FILTER_VALIDATE_BOOLEAN
619
-        );
620
-        // and whether or not to process a reg form submission for this request
621
-        $this->checkout->process_form_submission = filter_var(
622
-            EE_Registry::instance()->REQ->get(
623
-                'process_form_submission',
624
-                $this->checkout->action === 'process_reg_step'
625
-            ),
626
-            FILTER_VALIDATE_BOOLEAN
627
-        );
628
-        $this->checkout->process_form_submission = filter_var(
629
-            $this->checkout->action !== 'display_spco_reg_step'
630
-                ? $this->checkout->process_form_submission
631
-                : false,
632
-            FILTER_VALIDATE_BOOLEAN
633
-        );
634
-        // $this->_display_request_vars();
635
-    }
636
-
637
-
638
-
639
-    /**
640
-     *  _display_request_vars
641
-     *
642
-     * @access    protected
643
-     * @return    void
644
-     */
645
-    protected function _display_request_vars()
646
-    {
647
-        if ( ! WP_DEBUG) {
648
-            return;
649
-        }
650
-        EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
651
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
652
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
653
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
654
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
655
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
656
-        EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
657
-        EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
658
-    }
659
-
660
-
661
-
662
-    /**
663
-     * _block_bots
664
-     * checks that the incoming request has either of the following set:
665
-     *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
666
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
667
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
668
-     * then where you coming from man?
669
-     *
670
-     * @return boolean
671
-     */
672
-    private function _block_bots()
673
-    {
674
-        $invalid_checkout_access = \EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
675
-        if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
676
-            return true;
677
-        }
678
-        return false;
679
-    }
680
-
681
-
682
-
683
-    /**
684
-     *    _get_first_step
685
-     *  gets slug for first step in $_reg_steps_array
686
-     *
687
-     * @access    private
688
-     * @throws EE_Error
689
-     * @return    string
690
-     */
691
-    private function _get_first_step()
692
-    {
693
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
694
-        return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
695
-    }
696
-
697
-
698
-
699
-    /**
700
-     *    _load_and_instantiate_reg_steps
701
-     *  instantiates each reg step based on the loaded reg_steps array
702
-     *
703
-     * @access    private
704
-     * @throws EE_Error
705
-     * @return    bool
706
-     */
707
-    private function _load_and_instantiate_reg_steps()
708
-    {
709
-        // have reg_steps already been instantiated ?
710
-        if (
711
-            empty($this->checkout->reg_steps)
712
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
713
-        ) {
714
-            // if not, then loop through raw reg steps array
715
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
716
-                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
717
-                    return false;
718
-                }
719
-            }
720
-            EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
721
-            EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
722
-            // skip the registration_confirmation page ?
723
-            if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
724
-                // just remove it from the reg steps array
725
-                $this->checkout->remove_reg_step('registration_confirmation', false);
726
-            } else if (
727
-                isset($this->checkout->reg_steps['registration_confirmation'])
728
-                && EE_Registry::instance()->CFG->registration->reg_confirmation_last
729
-            ) {
730
-                // set the order to something big like 100
731
-                $this->checkout->set_reg_step_order('registration_confirmation', 100);
732
-            }
733
-            // filter the array for good luck
734
-            $this->checkout->reg_steps = apply_filters(
735
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
736
-                $this->checkout->reg_steps
737
-            );
738
-            // finally re-sort based on the reg step class order properties
739
-            $this->checkout->sort_reg_steps();
740
-        } else {
741
-            foreach ($this->checkout->reg_steps as $reg_step) {
742
-                // set all current step stati to FALSE
743
-                $reg_step->set_is_current_step(false);
744
-            }
745
-        }
746
-        if (empty($this->checkout->reg_steps)) {
747
-            EE_Error::add_error(__('No Reg Steps were loaded..', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
748
-            return false;
749
-        }
750
-        // make reg step details available to JS
751
-        $this->checkout->set_reg_step_JSON_info();
752
-        return true;
753
-    }
754
-
755
-
756
-
757
-    /**
758
-     *     _load_and_instantiate_reg_step
759
-     *
760
-     * @access    private
761
-     * @param array $reg_step
762
-     * @param int   $order
763
-     * @return bool
764
-     */
765
-    private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
766
-    {
767
-        // we need a file_path, class_name, and slug to add a reg step
768
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
769
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
770
-            if (
771
-                $this->checkout->reg_url_link
772
-                && $this->checkout->step !== $reg_step['slug']
773
-                && $reg_step['slug'] !== 'finalize_registration'
774
-            ) {
775
-                return true;
776
-            }
777
-            // instantiate step class using file path and class name
778
-            $reg_step_obj = EE_Registry::instance()->load_file(
779
-                $reg_step['file_path'],
780
-                $reg_step['class_name'],
781
-                'class',
782
-                $this->checkout,
783
-                false
784
-            );
785
-            // did we gets the goods ?
786
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
787
-                // set reg step order based on config
788
-                $reg_step_obj->set_order($order);
789
-                // add instantiated reg step object to the master reg steps array
790
-                $this->checkout->add_reg_step($reg_step_obj);
791
-            } else {
792
-                EE_Error::add_error(
793
-                    __('The current step could not be set.', 'event_espresso'),
794
-                    __FILE__, __FUNCTION__, __LINE__
795
-                );
796
-                return false;
797
-            }
798
-        } else {
799
-            if (WP_DEBUG) {
800
-                EE_Error::add_error(
801
-                    sprintf(
802
-                        __('A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s', 'event_espresso'),
803
-                        isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
804
-                        isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
805
-                        isset($reg_step['slug']) ? $reg_step['slug'] : '',
806
-                        '<ul>',
807
-                        '<li>',
808
-                        '</li>',
809
-                        '</ul>'
810
-                    ),
811
-                    __FILE__, __FUNCTION__, __LINE__
812
-                );
813
-            }
814
-            return false;
815
-        }
816
-        return true;
817
-    }
818
-
819
-
820
-
821
-    /**
822
-     * _verify_transaction_and_get_registrations
823
-     *
824
-     * @access private
825
-     * @return bool
826
-     */
827
-    private function _verify_transaction_and_get_registrations()
828
-    {
829
-        // was there already a valid transaction in the checkout from the session ?
830
-        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
831
-            // get transaction from db or session
832
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
833
-                ? $this->_get_transaction_and_cart_for_previous_visit()
834
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
835
-            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
836
-                EE_Error::add_error(
837
-                    __('Your Registration and Transaction information could not be retrieved from the db.',
838
-                        'event_espresso'),
839
-                    __FILE__, __FUNCTION__, __LINE__
840
-                );
841
-                $this->checkout->transaction = EE_Transaction::new_instance();
842
-                // add some style and make it dance
843
-                $this->add_styles_and_scripts();
844
-                EED_Single_Page_Checkout::$_initialized = true;
845
-                return false;
846
-            }
847
-            // and the registrations for the transaction
848
-            $this->_get_registrations($this->checkout->transaction);
849
-        }
850
-        return true;
851
-    }
852
-
853
-
854
-
855
-    /**
856
-     * _get_transaction_and_cart_for_previous_visit
857
-     *
858
-     * @access private
859
-     * @return mixed EE_Transaction|NULL
860
-     */
861
-    private function _get_transaction_and_cart_for_previous_visit()
862
-    {
863
-        /** @var $TXN_model EEM_Transaction */
864
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
865
-        // because the reg_url_link is present in the request, this is a return visit to SPCO, so we'll get the transaction data from the db
866
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
867
-        // verify transaction
868
-        if ($transaction instanceof EE_Transaction) {
869
-            // and get the cart that was used for that transaction
870
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
871
-            return $transaction;
872
-        } else {
873
-            EE_Error::add_error(__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
874
-            return null;
875
-        }
876
-    }
877
-
878
-
879
-
880
-    /**
881
-     * _get_cart_for_transaction
882
-     *
883
-     * @access private
884
-     * @param EE_Transaction $transaction
885
-     * @return EE_Cart
886
-     */
887
-    private function _get_cart_for_transaction($transaction)
888
-    {
889
-        return $this->checkout->get_cart_for_transaction($transaction);
890
-    }
891
-
892
-
893
-
894
-    /**
895
-     * get_cart_for_transaction
896
-     *
897
-     * @access public
898
-     * @param EE_Transaction $transaction
899
-     * @return EE_Cart
900
-     */
901
-    public function get_cart_for_transaction(EE_Transaction $transaction)
902
-    {
903
-        return $this->checkout->get_cart_for_transaction($transaction);
904
-    }
905
-
906
-
907
-
908
-    /**
909
-     * _get_transaction_and_cart_for_current_session
910
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
911
-     *
912
-     * @access private
913
-     * @return EE_Transaction
914
-     * @throws \EE_Error
915
-     */
916
-    private function _get_cart_for_current_session_and_setup_new_transaction()
917
-    {
918
-        //  if there's no transaction, then this is the FIRST visit to SPCO
919
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
920
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
921
-        // and then create a new transaction
922
-        $transaction = $this->_initialize_transaction();
923
-        // verify transaction
924
-        if ($transaction instanceof EE_Transaction) {
925
-            // save it so that we have an ID for other objects to use
926
-            $transaction->save();
927
-            // and save TXN data to the cart
928
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
929
-        } else {
930
-            EE_Error::add_error(__('A Valid Transaction could not be initialized.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
931
-        }
932
-        return $transaction;
933
-    }
934
-
935
-
936
-
937
-    /**
938
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
939
-     *
940
-     * @access private
941
-     * @return mixed EE_Transaction|NULL
942
-     */
943
-    private function _initialize_transaction()
944
-    {
945
-        try {
946
-            // ensure cart totals have been calculated
947
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
948
-            // grab the cart grand total
949
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
950
-            // create new TXN
951
-            $transaction = EE_Transaction::new_instance(
952
-                array(
953
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
954
-                    'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
955
-                    'TXN_paid'      => 0,
956
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
957
-                )
958
-            );
959
-            // save it so that we have an ID for other objects to use
960
-            $transaction->save();
961
-            // set cron job for following up on TXNs after their session has expired
962
-            EE_Cron_Tasks::schedule_expired_transaction_check(
963
-                EE_Registry::instance()->SSN->expiration() + 1,
964
-                $transaction->ID()
965
-            );
966
-            return $transaction;
967
-        } catch (Exception $e) {
968
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
969
-        }
970
-        return null;
971
-    }
972
-
973
-
974
-
975
-    /**
976
-     * _get_registrations
977
-     *
978
-     * @access private
979
-     * @param EE_Transaction $transaction
980
-     * @return void
981
-     * @throws \EventEspresso\core\exceptions\InvalidEntityException
982
-     * @throws \EE_Error
983
-     */
984
-    private function _get_registrations(EE_Transaction $transaction)
985
-    {
986
-        // first step: grab the registrants  { : o
987
-        $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
988
-        // verify registrations have been set
989
-        if (empty($registrations)) {
990
-            // if no cached registrations, then check the db
991
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
992
-            // still nothing ? well as long as this isn't a revisit
993
-            if (empty($registrations) && ! $this->checkout->revisit) {
994
-                // generate new registrations from scratch
995
-                $registrations = $this->_initialize_registrations($transaction);
996
-            }
997
-        }
998
-        // sort by their original registration order
999
-        usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1000
-        // then loop thru the array
1001
-        foreach ($registrations as $registration) {
1002
-            // verify each registration
1003
-            if ($registration instanceof EE_Registration) {
1004
-                // we display all attendee info for the primary registrant
1005
-                if ($this->checkout->reg_url_link === $registration->reg_url_link()
1006
-                    && $registration->is_primary_registrant()
1007
-                ) {
1008
-                    $this->checkout->primary_revisit = true;
1009
-                    break;
1010
-                } else if ($this->checkout->revisit
1011
-                           && $this->checkout->reg_url_link !== $registration->reg_url_link()
1012
-                ) {
1013
-                    // but hide info if it doesn't belong to you
1014
-                    $transaction->clear_cache('Registration', $registration->ID());
1015
-                }
1016
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1017
-            }
1018
-        }
1019
-    }
1020
-
1021
-
1022
-
1023
-    /**
1024
-     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1025
-     *
1026
-     * @access private
1027
-     * @param EE_Transaction $transaction
1028
-     * @return    array
1029
-     * @throws \EventEspresso\core\exceptions\InvalidEntityException
1030
-     * @throws \EE_Error
1031
-     */
1032
-    private function _initialize_registrations(EE_Transaction $transaction)
1033
-    {
1034
-        $att_nmbr = 0;
1035
-        $registrations = array();
1036
-        if ($transaction instanceof EE_Transaction) {
1037
-            /** @type EE_Registration_Processor $registration_processor */
1038
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1039
-            $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1040
-            // now let's add the cart items to the $transaction
1041
-            foreach ($this->checkout->cart->get_tickets() as $line_item) {
1042
-                //do the following for each ticket of this type they selected
1043
-                for ($x = 1; $x <= $line_item->quantity(); $x++) {
1044
-                    $att_nmbr++;
1045
-                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1046
-                    $CreateRegistrationCommand = EE_Registry::instance()
1047
-                                                            ->create(
1048
-                                                                'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1049
-                                                                array(
1050
-                                                                    $transaction,
1051
-                                                                    $line_item,
1052
-                                                                    $att_nmbr,
1053
-                                                                    $this->checkout->total_ticket_count,
1054
-                                                                )
1055
-                                                            );
1056
-                    // override capabilities for frontend registrations
1057
-                    if ( ! is_admin()) {
1058
-                        $CreateRegistrationCommand->setCapCheck(
1059
-                            new PublicCapabilities('', 'create_new_registration')
1060
-                        );
1061
-                    }
1062
-                    $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1063
-                    if ( ! $registration instanceof EE_Registration) {
1064
-                        throw new InvalidEntityException($registration, 'EE_Registration');
1065
-                    }
1066
-                    $registrations[ $registration->ID() ] = $registration;
1067
-                }
1068
-            }
1069
-            $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1070
-        }
1071
-        return $registrations;
1072
-    }
1073
-
1074
-
1075
-
1076
-    /**
1077
-     * sorts registrations by REG_count
1078
-     *
1079
-     * @access public
1080
-     * @param EE_Registration $reg_A
1081
-     * @param EE_Registration $reg_B
1082
-     * @return int
1083
-     */
1084
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1085
-    {
1086
-        // this shouldn't ever happen within the same TXN, but oh well
1087
-        if ($reg_A->count() === $reg_B->count()) {
1088
-            return 0;
1089
-        }
1090
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1091
-    }
1092
-
1093
-
1094
-
1095
-    /**
1096
-     *    _final_verifications
1097
-     * just makes sure that everything is set up correctly before proceeding
1098
-     *
1099
-     * @access    private
1100
-     * @return    bool
1101
-     * @throws \EE_Error
1102
-     */
1103
-    private function _final_verifications()
1104
-    {
1105
-        // filter checkout
1106
-        $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___final_verifications__checkout', $this->checkout);
1107
-        //verify that current step is still set correctly
1108
-        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1109
-            EE_Error::add_error(
1110
-                __('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1111
-                __FILE__,
1112
-                __FUNCTION__,
1113
-                __LINE__
1114
-            );
1115
-            return false;
1116
-        }
1117
-        // if returning to SPCO, then verify that primary registrant is set
1118
-        if ( ! empty($this->checkout->reg_url_link)) {
1119
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1120
-            if ( ! $valid_registrant instanceof EE_Registration) {
1121
-                EE_Error::add_error(
1122
-                    __('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1123
-                    __FILE__,
1124
-                    __FUNCTION__,
1125
-                    __LINE__
1126
-                );
1127
-                return false;
1128
-            }
1129
-            $valid_registrant = null;
1130
-            foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1131
-                if (
1132
-                    $registration instanceof EE_Registration
1133
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1134
-                ) {
1135
-                    $valid_registrant = $registration;
1136
-                }
1137
-            }
1138
-            if ( ! $valid_registrant instanceof EE_Registration) {
1139
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1140
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1141
-                    // clear the session, mark the checkout as unverified, and try again
1142
-                    EE_Registry::instance()->SSN->clear_session();
1143
-                    EED_Single_Page_Checkout::$_initialized = false;
1144
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1145
-                    $this->_initialize();
1146
-                    EE_Error::reset_notices();
1147
-                    return false;
1148
-                }
1149
-                EE_Error::add_error(
1150
-                    __('We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.', 'event_espresso'),
1151
-                    __FILE__,
1152
-                    __FUNCTION__,
1153
-                    __LINE__
1154
-                );
1155
-                return false;
1156
-            }
1157
-        }
1158
-        // now that things have been kinda sufficiently verified,
1159
-        // let's add the checkout to the session so that's available other systems
1160
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1161
-        return true;
1162
-    }
1163
-
1164
-
1165
-
1166
-    /**
1167
-     *    _initialize_reg_steps
1168
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1169
-     * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1170
-     *
1171
-     * @access    private
1172
-     * @param bool $reinitializing
1173
-     * @throws \EE_Error
1174
-     */
1175
-    private function _initialize_reg_steps($reinitializing = false)
1176
-    {
1177
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1178
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1179
-        foreach ($this->checkout->reg_steps as $reg_step) {
1180
-            if ( ! $reg_step->initialize_reg_step()) {
1181
-                // if not initialized then maybe this step is being removed...
1182
-                if ( ! $reinitializing && $reg_step->is_current_step()) {
1183
-                    // if it was the current step, then we need to start over here
1184
-                    $this->_initialize_reg_steps(true);
1185
-                    return;
1186
-                }
1187
-                continue;
1188
-            }
1189
-            // add css and JS for current step
1190
-            $reg_step->enqueue_styles_and_scripts();
1191
-            // i18n
1192
-            $reg_step->translate_js_strings();
1193
-            if ($reg_step->is_current_step()) {
1194
-                // the text that appears on the reg step form submit button
1195
-                $reg_step->set_submit_button_text();
1196
-            }
1197
-        }
1198
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1199
-        do_action("AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}", $this->checkout->current_step);
1200
-    }
1201
-
1202
-
1203
-
1204
-    /**
1205
-     * _check_form_submission
1206
-     *
1207
-     * @access private
1208
-     * @return boolean
1209
-     */
1210
-    private function _check_form_submission()
1211
-    {
1212
-        //does this request require the reg form to be generated ?
1213
-        if ($this->checkout->generate_reg_form) {
1214
-            // ever heard that song by Blue Rodeo ?
1215
-            try {
1216
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1217
-                // if not displaying a form, then check for form submission
1218
-                if (
1219
-                    $this->checkout->process_form_submission
1220
-                    && $this->checkout->current_step->reg_form->was_submitted()
1221
-                ) {
1222
-                    // clear out any old data in case this step is being run again
1223
-                    $this->checkout->current_step->set_valid_data(array());
1224
-                    // capture submitted form data
1225
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1226
-                        apply_filters('FHEE__Single_Page_Checkout___check_form_submission__request_params', EE_Registry::instance()->REQ->params(), $this->checkout)
1227
-                    );
1228
-                    // validate submitted form data
1229
-                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1230
-                        // thou shall not pass !!!
1231
-                        $this->checkout->continue_reg = false;
1232
-                        // any form validation errors?
1233
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1234
-                            $submission_error_messages = array();
1235
-                            // bad, bad, bad registrant
1236
-                            foreach ($this->checkout->current_step->reg_form->get_validation_errors_accumulated() as $validation_error) {
1237
-                                if ($validation_error instanceof EE_Validation_Error) {
1238
-                                    $submission_error_messages[] = sprintf(
1239
-                                        __('%s : %s', 'event_espresso'),
1240
-                                        $validation_error->get_form_section()->html_label_text(),
1241
-                                        $validation_error->getMessage()
1242
-                                    );
1243
-                                }
1244
-                            }
1245
-                            EE_Error::add_error(implode('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1246
-                        }
1247
-                        // well not really... what will happen is we'll just get redirected back to redo the current step
1248
-                        $this->go_to_next_step();
1249
-                        return false;
1250
-                    }
1251
-                }
1252
-            } catch (EE_Error $e) {
1253
-                $e->get_error();
1254
-            }
1255
-        }
1256
-        return true;
1257
-    }
1258
-
1259
-
1260
-
1261
-    /**
1262
-     * _process_action
1263
-     *
1264
-     * @access private
1265
-     * @return void
1266
-     * @throws \EE_Error
1267
-     */
1268
-    private function _process_form_action()
1269
-    {
1270
-        // what cha wanna do?
1271
-        switch ($this->checkout->action) {
1272
-            // AJAX next step reg form
1273
-            case 'display_spco_reg_step' :
1274
-                $this->checkout->redirect = false;
1275
-                if (EE_Registry::instance()->REQ->ajax) {
1276
-                    $this->checkout->json_response->set_reg_step_html($this->checkout->current_step->display_reg_form());
1277
-                }
1278
-                break;
1279
-            default :
1280
-                // meh... do one of those other steps first
1281
-                if ( ! empty($this->checkout->action) && is_callable(array($this->checkout->current_step, $this->checkout->action))) {
1282
-                    // dynamically creates hook point like: AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1283
-                    do_action("AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1284
-                    // call action on current step
1285
-                    if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1286
-                        // good registrant, you get to proceed
1287
-                        if (
1288
-                            $this->checkout->current_step->success_message() !== ''
1289
-                            && apply_filters(
1290
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1291
-                                false
1292
-                            )
1293
-                        ) {
1294
-                            EE_Error::add_success(
1295
-                                $this->checkout->current_step->success_message()
1296
-                                . '<br />' . $this->checkout->next_step->_instructions()
1297
-                            );
1298
-                        }
1299
-                        // pack it up, pack it in...
1300
-                        $this->_setup_redirect();
1301
-                    }
1302
-                    // dynamically creates hook point like: AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1303
-                    do_action("AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1304
-                } else {
1305
-                    EE_Error::add_error(
1306
-                        sprintf(
1307
-                            __('The requested form action "%s" does not exist for the current "%s" registration step.', 'event_espresso'),
1308
-                            $this->checkout->action,
1309
-                            $this->checkout->current_step->name()
1310
-                        ),
1311
-                        __FILE__,
1312
-                        __FUNCTION__,
1313
-                        __LINE__
1314
-                    );
1315
-                }
1316
-            // end default
1317
-        }
1318
-        // store our progress so far
1319
-        $this->checkout->stash_transaction_and_checkout();
1320
-        // advance to the next step! If you pass GO, collect $200
1321
-        $this->go_to_next_step();
1322
-    }
1323
-
1324
-
1325
-
1326
-    /**
1327
-     *        add_styles_and_scripts
1328
-     *
1329
-     * @access        public
1330
-     * @return        void
1331
-     */
1332
-    public function add_styles_and_scripts()
1333
-    {
1334
-        // i18n
1335
-        $this->translate_js_strings();
1336
-        if ($this->checkout->admin_request) {
1337
-            add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1338
-        } else {
1339
-            add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1340
-        }
1341
-    }
1342
-
1343
-
1344
-
1345
-    /**
1346
-     *        translate_js_strings
1347
-     *
1348
-     * @access        public
1349
-     * @return        void
1350
-     */
1351
-    public function translate_js_strings()
1352
-    {
1353
-        EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1354
-        EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1355
-        EE_Registry::$i18n_js_strings['server_error'] = __('An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1356
-        EE_Registry::$i18n_js_strings['invalid_json_response'] = __('An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1357
-        EE_Registry::$i18n_js_strings['validation_error'] = __('There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.', 'event_espresso');
1358
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = __('There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.', 'event_espresso');
1359
-        EE_Registry::$i18n_js_strings['reg_step_error'] = __('This registration step could not be completed. Please refresh the page and try again.', 'event_espresso');
1360
-        EE_Registry::$i18n_js_strings['invalid_coupon'] = __('We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.', 'event_espresso');
1361
-        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1362
-            __('Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.', 'event_espresso'),
1363
-            '<br/>',
1364
-            '<br/>'
1365
-        );
1366
-        EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1367
-        EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1368
-        EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1369
-        EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1370
-        EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1371
-        EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1372
-        EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1373
-        EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1374
-        EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1375
-        EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1376
-        EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1377
-        EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1378
-        EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1379
-        EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1380
-        EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1381
-        EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1382
-        EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1383
-        EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1384
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1385
-            __(
1386
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
1387
-                'event_espresso'
1388
-            ),
1389
-            '<h4 class="important-notice">',
1390
-            '</h4>',
1391
-            '<br />',
1392
-            '<p>',
1393
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1394
-            '">',
1395
-            '</a>',
1396
-            '</p>'
1397
-        );
1398
-        EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters('FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', true);
1399
-        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1400
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1401
-        );
1402
-        EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1403
-            'M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1404
-        );
1405
-    }
1406
-
1407
-
1408
-
1409
-    /**
1410
-     *    enqueue_styles_and_scripts
1411
-     *
1412
-     * @access        public
1413
-     * @return        void
1414
-     * @throws \EE_Error
1415
-     */
1416
-    public function enqueue_styles_and_scripts()
1417
-    {
1418
-        // load css
1419
-        wp_register_style('single_page_checkout', SPCO_CSS_URL . 'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION);
1420
-        wp_enqueue_style('single_page_checkout');
1421
-        // load JS
1422
-        wp_register_script('jquery_plugin', EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js', array('jquery'), '1.0.1', true);
1423
-        wp_register_script('jquery_countdown', EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js', array('jquery_plugin'), '2.0.2', true);
1424
-        wp_register_script('single_page_checkout', SPCO_JS_URL . 'single_page_checkout.js', array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'), EVENT_ESPRESSO_VERSION, true);
1425
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1426
-            $this->checkout->registration_form->enqueue_js();
1427
-        }
1428
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1429
-            $this->checkout->current_step->reg_form->enqueue_js();
1430
-        }
1431
-        wp_enqueue_script('single_page_checkout');
1432
-        /**
1433
-         * global action hook for enqueueing styles and scripts with
1434
-         * spco calls.
1435
-         */
1436
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1437
-        /**
1438
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1439
-         * The hook will end up being something like AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1440
-         */
1441
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(), $this);
1442
-    }
1443
-
1444
-
1445
-
1446
-    /**
1447
-     *    display the Registration Single Page Checkout Form
1448
-     *
1449
-     * @access    private
1450
-     * @return    void
1451
-     * @throws \EE_Error
1452
-     */
1453
-    private function _display_spco_reg_form()
1454
-    {
1455
-        // if registering via the admin, just display the reg form for the current step
1456
-        if ($this->checkout->admin_request) {
1457
-            EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1458
-        } else {
1459
-            // add powered by EE msg
1460
-            add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1461
-            $empty_cart = count($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)) < 1
1462
-                ? true
1463
-                : false;
1464
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1465
-            $cookies_not_set_msg = '';
1466
-            if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1467
-                $cookies_not_set_msg = apply_filters(
1468
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1469
-                    sprintf(
1470
-                        __(
1471
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1472
-                            'event_espresso'
1473
-                        ),
1474
-                        '<div class="ee-attention">',
1475
-                        '</div>',
1476
-                        '<h6 class="important-notice">',
1477
-                        '</h6>',
1478
-                        '<p>',
1479
-                        '</p>',
1480
-                        '<br />',
1481
-                        '<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1482
-                        '</a>'
1483
-                    )
1484
-                );
1485
-            }
1486
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1487
-                array(
1488
-                    'name'            => 'single-page-checkout',
1489
-                    'html_id'         => 'ee-single-page-checkout-dv',
1490
-                    'layout_strategy' =>
1491
-                        new EE_Template_Layout(
1492
-                            array(
1493
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1494
-                                'template_args'        => array(
1495
-                                    'empty_cart'              => $empty_cart,
1496
-                                    'revisit'                 => $this->checkout->revisit,
1497
-                                    'reg_steps'               => $this->checkout->reg_steps,
1498
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1499
-                                        ? $this->checkout->next_step->slug()
1500
-                                        : '',
1501
-                                    'cancel_page_url'         => $this->checkout->cancel_page_url,
1502
-                                    'empty_msg'               => apply_filters(
1503
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1504
-                                        sprintf(
1505
-                                            __('You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1506
-                                                'event_espresso'),
1507
-                                            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1508
-                                            '">',
1509
-                                            '</a>'
1510
-                                        )
1511
-                                    ),
1512
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1513
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1514
-                                    'session_expiration'      =>
1515
-                                        date('M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)),
1516
-                                ),
1517
-                            )
1518
-                        ),
1519
-                )
1520
-            );
1521
-            // load template and add to output sent that gets filtered into the_content()
1522
-            EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1523
-        }
1524
-    }
1525
-
1526
-
1527
-
1528
-    /**
1529
-     *    add_extra_finalize_registration_inputs
1530
-     *
1531
-     * @access    public
1532
-     * @param $next_step
1533
-     * @internal  param string $label
1534
-     * @return void
1535
-     */
1536
-    public function add_extra_finalize_registration_inputs($next_step)
1537
-    {
1538
-        if ($next_step === 'finalize_registration') {
1539
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1540
-        }
1541
-    }
1542
-
1543
-
1544
-
1545
-    /**
1546
-     *    display_registration_footer
1547
-     *
1548
-     * @access    public
1549
-     * @return    string
1550
-     */
1551
-    public static function display_registration_footer()
1552
-    {
1553
-        if (
1554
-        apply_filters(
1555
-            'FHEE__EE_Front__Controller__show_reg_footer',
1556
-            EE_Registry::instance()->CFG->admin->show_reg_footer
1557
-        )
1558
-        ) {
1559
-            add_filter(
1560
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1561
-                function ($url) {
1562
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1563
-                }
1564
-            );
1565
-            echo apply_filters(
1566
-                'FHEE__EE_Front_Controller__display_registration_footer',
1567
-                \EEH_Template::powered_by_event_espresso(
1568
-                    '',
1569
-                    'espresso-registration-footer-dv',
1570
-                    array('utm_content' => 'registration_checkout')
1571
-                )
1572
-            );
1573
-        }
1574
-        return '';
1575
-    }
1576
-
1577
-
1578
-
1579
-    /**
1580
-     *    unlock_transaction
1581
-     *
1582
-     * @access    public
1583
-     * @return    void
1584
-     * @throws \EE_Error
1585
-     */
1586
-    public function unlock_transaction()
1587
-    {
1588
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1589
-            $this->checkout->transaction->unlock();
1590
-        }
1591
-    }
1592
-
1593
-
1594
-
1595
-    /**
1596
-     *        _setup_redirect
1597
-     *
1598
-     * @access    private
1599
-     * @return void
1600
-     */
1601
-    private function _setup_redirect()
1602
-    {
1603
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1604
-            $this->checkout->redirect = true;
1605
-            if (empty($this->checkout->redirect_url)) {
1606
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1607
-            }
1608
-            $this->checkout->redirect_url = apply_filters(
1609
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1610
-                $this->checkout->redirect_url,
1611
-                $this->checkout
1612
-            );
1613
-        }
1614
-    }
1615
-
1616
-
1617
-
1618
-    /**
1619
-     *   handle ajax message responses and redirects
1620
-     *
1621
-     * @access public
1622
-     * @return void
1623
-     * @throws \EE_Error
1624
-     */
1625
-    public function go_to_next_step()
1626
-    {
1627
-        if (EE_Registry::instance()->REQ->ajax) {
1628
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1629
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1630
-        }
1631
-        $this->unlock_transaction();
1632
-        // just return for these conditions
1633
-        if (
1634
-            $this->checkout->admin_request
1635
-            || $this->checkout->action === 'redirect_form'
1636
-            || $this->checkout->action === 'update_checkout'
1637
-        ) {
1638
-            return;
1639
-        }
1640
-        // AJAX response
1641
-        $this->_handle_json_response();
1642
-        // redirect to next step or the Thank You page
1643
-        $this->_handle_html_redirects();
1644
-        // hmmm... must be something wrong, so let's just display the form again !
1645
-        $this->_display_spco_reg_form();
1646
-    }
1647
-
1648
-
1649
-
1650
-    /**
1651
-     *   _handle_json_response
1652
-     *
1653
-     * @access protected
1654
-     * @return void
1655
-     */
1656
-    protected function _handle_json_response()
1657
-    {
1658
-        // if this is an ajax request
1659
-        if (EE_Registry::instance()->REQ->ajax) {
1660
-            // DEBUG LOG
1661
-            //$this->checkout->log(
1662
-            //	__CLASS__, __FUNCTION__, __LINE__,
1663
-            //	array(
1664
-            //		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1665
-            //		'redirect'                   => $this->checkout->redirect,
1666
-            //		'continue_reg'               => $this->checkout->continue_reg,
1667
-            //	)
1668
-            //);
1669
-            $this->checkout->json_response->set_registration_time_limit(
1670
-                $this->checkout->get_registration_time_limit()
1671
-            );
1672
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1673
-            // just send the ajax (
1674
-            $json_response = apply_filters(
1675
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1676
-                $this->checkout->json_response
1677
-            );
1678
-            echo $json_response;
1679
-            exit();
1680
-        }
1681
-    }
1682
-
1683
-
1684
-
1685
-    /**
1686
-     *   _handle_redirects
1687
-     *
1688
-     * @access protected
1689
-     * @return void
1690
-     */
1691
-    protected function _handle_html_redirects()
1692
-    {
1693
-        // going somewhere ?
1694
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1695
-            // store notices in a transient
1696
-            EE_Error::get_notices(false, true, true);
1697
-            // DEBUG LOG
1698
-            //$this->checkout->log(
1699
-            //	__CLASS__, __FUNCTION__, __LINE__,
1700
-            //	array(
1701
-            //		'headers_sent' => headers_sent(),
1702
-            //		'redirect_url'     => $this->checkout->redirect_url,
1703
-            //		'headers_list'    => headers_list(),
1704
-            //	)
1705
-            //);
1706
-            wp_safe_redirect($this->checkout->redirect_url);
1707
-            exit();
1708
-        }
1709
-    }
1710
-
1711
-
1712
-
1713
-    /**
1714
-     *   set_checkout_anchor
1715
-     *
1716
-     * @access public
1717
-     * @return void
1718
-     */
1719
-    public function set_checkout_anchor()
1720
-    {
1721
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1722
-    }
20
+	/**
21
+	 * $_initialized - has the SPCO controller already been initialized ?
22
+	 *
23
+	 * @access private
24
+	 * @var bool $_initialized
25
+	 */
26
+	private static $_initialized = false;
27
+
28
+
29
+	/**
30
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
31
+	 *
32
+	 * @access private
33
+	 * @var bool $_valid_checkout
34
+	 */
35
+	private static $_checkout_verified = true;
36
+
37
+	/**
38
+	 *    $_reg_steps_array - holds initial array of reg steps
39
+	 *
40
+	 * @access private
41
+	 * @var array $_reg_steps_array
42
+	 */
43
+	private static $_reg_steps_array = array();
44
+
45
+	/**
46
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
47
+	 *
48
+	 * @access public
49
+	 * @var EE_Checkout $checkout
50
+	 */
51
+	public $checkout;
52
+
53
+
54
+
55
+	/**
56
+	 * @return EED_Single_Page_Checkout
57
+	 */
58
+	public static function instance()
59
+	{
60
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
61
+		return parent::get_instance(__CLASS__);
62
+	}
63
+
64
+
65
+
66
+	/**
67
+	 * @return EE_CART
68
+	 */
69
+	public function cart()
70
+	{
71
+		return $this->checkout->cart;
72
+	}
73
+
74
+
75
+
76
+	/**
77
+	 * @return EE_Transaction
78
+	 */
79
+	public function transaction()
80
+	{
81
+		return $this->checkout->transaction;
82
+	}
83
+
84
+
85
+
86
+	/**
87
+	 *    set_hooks - for hooking into EE Core, other modules, etc
88
+	 *
89
+	 * @access    public
90
+	 * @return    void
91
+	 * @throws \EE_Error
92
+	 */
93
+	public static function set_hooks()
94
+	{
95
+		EED_Single_Page_Checkout::set_definitions();
96
+	}
97
+
98
+
99
+
100
+	/**
101
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
102
+	 *
103
+	 * @access    public
104
+	 * @return    void
105
+	 * @throws \EE_Error
106
+	 */
107
+	public static function set_hooks_admin()
108
+	{
109
+		EED_Single_Page_Checkout::set_definitions();
110
+		if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
111
+			// hook into the top of pre_get_posts to set the reg step routing, which gives other modules or plugins a chance to modify the reg steps, but just before the routes get called
112
+			add_action('pre_get_posts', array('EED_Single_Page_Checkout', 'load_reg_steps'), 1);
113
+			return;
114
+		}
115
+		// going to start an output buffer in case anything gets accidentally output that might disrupt our JSON response
116
+		ob_start();
117
+		EED_Single_Page_Checkout::load_request_handler();
118
+		EED_Single_Page_Checkout::load_reg_steps();
119
+		// set ajax hooks
120
+		add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
121
+		add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
122
+		add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
123
+		add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
124
+		add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
125
+		add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
126
+	}
127
+
128
+
129
+
130
+	/**
131
+	 *    process ajax request
132
+	 *
133
+	 * @param string $ajax_action
134
+	 * @throws \EE_Error
135
+	 */
136
+	public static function process_ajax_request($ajax_action)
137
+	{
138
+		EE_Registry::instance()->REQ->set('action', $ajax_action);
139
+		EED_Single_Page_Checkout::instance()->_initialize();
140
+	}
141
+
142
+
143
+
144
+	/**
145
+	 *    ajax display registration step
146
+	 *
147
+	 * @throws \EE_Error
148
+	 */
149
+	public static function display_reg_step()
150
+	{
151
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
152
+	}
153
+
154
+
155
+
156
+	/**
157
+	 *    ajax process registration step
158
+	 *
159
+	 * @throws \EE_Error
160
+	 */
161
+	public static function process_reg_step()
162
+	{
163
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 *    ajax process registration step
170
+	 *
171
+	 * @throws \EE_Error
172
+	 */
173
+	public static function update_reg_step()
174
+	{
175
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
176
+	}
177
+
178
+
179
+
180
+	/**
181
+	 *   update_checkout
182
+	 *
183
+	 * @access public
184
+	 * @return void
185
+	 * @throws \EE_Error
186
+	 */
187
+	public static function update_checkout()
188
+	{
189
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
190
+	}
191
+
192
+
193
+
194
+	/**
195
+	 *    load_request_handler
196
+	 *
197
+	 * @access    public
198
+	 * @return    void
199
+	 */
200
+	public static function load_request_handler()
201
+	{
202
+		// load core Request_Handler class
203
+		if ( ! isset(EE_Registry::instance()->REQ)) {
204
+			EE_Registry::instance()->load_core('Request_Handler');
205
+		}
206
+	}
207
+
208
+
209
+
210
+	/**
211
+	 *    set_definitions
212
+	 *
213
+	 * @access    public
214
+	 * @return    void
215
+	 * @throws \EE_Error
216
+	 */
217
+	public static function set_definitions()
218
+	{
219
+		define('SPCO_BASE_PATH', rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS);
220
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
221
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
222
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
223
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
224
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
225
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
226
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
227
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
228
+			__('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
229
+				'event_espresso'),
230
+			'<h4 class="important-notice">',
231
+			'</h4>',
232
+			'<br />',
233
+			'<p>',
234
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
235
+			'">',
236
+			'</a>',
237
+			'</p>'
238
+		);
239
+	}
240
+
241
+
242
+
243
+	/**
244
+	 * load_reg_steps
245
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
246
+	 *
247
+	 * @access    private
248
+	 * @throws EE_Error
249
+	 * @return void
250
+	 */
251
+	public static function load_reg_steps()
252
+	{
253
+		static $reg_steps_loaded = false;
254
+		if ($reg_steps_loaded) {
255
+			return;
256
+		}
257
+		// filter list of reg_steps
258
+		$reg_steps_to_load = (array)apply_filters(
259
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
260
+			EED_Single_Page_Checkout::get_reg_steps()
261
+		);
262
+		// sort by key (order)
263
+		ksort($reg_steps_to_load);
264
+		// loop through folders
265
+		foreach ($reg_steps_to_load as $order => $reg_step) {
266
+			// we need a
267
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
268
+				// copy over to the reg_steps_array
269
+				EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
270
+				// register custom key route for each reg step
271
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
272
+				EE_Config::register_route($reg_step['slug'], 'EED_Single_Page_Checkout', 'run', 'step');
273
+				// add AJAX or other hooks
274
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
275
+					// setup autoloaders if necessary
276
+					if ( ! class_exists($reg_step['class_name'])) {
277
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder($reg_step['file_path'], true);
278
+					}
279
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
280
+						call_user_func(array($reg_step['class_name'], 'set_hooks'));
281
+					}
282
+				}
283
+			}
284
+		}
285
+		$reg_steps_loaded = true;
286
+	}
287
+
288
+
289
+
290
+	/**
291
+	 *    get_reg_steps
292
+	 *
293
+	 * @access    public
294
+	 * @return    array
295
+	 */
296
+	public static function get_reg_steps()
297
+	{
298
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
299
+		if (empty($reg_steps)) {
300
+			$reg_steps = array(
301
+				10  => array(
302
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
303
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
304
+					'slug'       => 'attendee_information',
305
+					'has_hooks'  => false,
306
+				),
307
+				20  => array(
308
+					'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
309
+					'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
310
+					'slug'       => 'registration_confirmation',
311
+					'has_hooks'  => false,
312
+				),
313
+				30  => array(
314
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
315
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
316
+					'slug'       => 'payment_options',
317
+					'has_hooks'  => true,
318
+				),
319
+				999 => array(
320
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
321
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
322
+					'slug'       => 'finalize_registration',
323
+					'has_hooks'  => false,
324
+				),
325
+			);
326
+		}
327
+		return $reg_steps;
328
+	}
329
+
330
+
331
+
332
+	/**
333
+	 *    registration_checkout_for_admin
334
+	 *
335
+	 * @access    public
336
+	 * @return    string
337
+	 * @throws \EE_Error
338
+	 */
339
+	public static function registration_checkout_for_admin()
340
+	{
341
+		EED_Single_Page_Checkout::load_reg_steps();
342
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
343
+		EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
344
+		EE_Registry::instance()->REQ->set('process_form_submission', false);
345
+		EED_Single_Page_Checkout::instance()->_initialize();
346
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
347
+		return EE_Registry::instance()->REQ->get_output();
348
+	}
349
+
350
+
351
+
352
+	/**
353
+	 * process_registration_from_admin
354
+	 *
355
+	 * @access public
356
+	 * @return \EE_Transaction
357
+	 * @throws \EE_Error
358
+	 */
359
+	public static function process_registration_from_admin()
360
+	{
361
+		EED_Single_Page_Checkout::load_reg_steps();
362
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
363
+		EE_Registry::instance()->REQ->set('action', 'process_reg_step');
364
+		EE_Registry::instance()->REQ->set('process_form_submission', true);
365
+		EED_Single_Page_Checkout::instance()->_initialize();
366
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
367
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
368
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
369
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
370
+				if ($final_reg_step->process_reg_step()) {
371
+					$final_reg_step->set_completed();
372
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
373
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
374
+				}
375
+			}
376
+		}
377
+		return null;
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 *    run
384
+	 *
385
+	 * @access    public
386
+	 * @param WP_Query $WP_Query
387
+	 * @return    void
388
+	 * @throws \EE_Error
389
+	 */
390
+	public function run($WP_Query)
391
+	{
392
+		if (
393
+			$WP_Query instanceof WP_Query
394
+			&& $WP_Query->is_main_query()
395
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
396
+			&& $this->_is_reg_checkout()
397
+		) {
398
+			$this->_initialize();
399
+		}
400
+	}
401
+
402
+
403
+
404
+	/**
405
+	 * determines whether current url matches reg page url
406
+	 *
407
+	 * @return bool
408
+	 */
409
+	protected function _is_reg_checkout()
410
+	{
411
+		// get current permalink for reg page without any extra query args
412
+		$reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
413
+		// get request URI for current request, but without the scheme or host
414
+		$current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
415
+		$current_request_uri = html_entity_decode($current_request_uri);
416
+		// get array of query args from the current request URI
417
+		$query_args = \EEH_URL::get_query_string($current_request_uri);
418
+		// grab page id if it is set
419
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
420
+		// and remove the page id from the query args (we will re-add it later)
421
+		unset($query_args['page_id']);
422
+		// now strip all query args from current request URI
423
+		$current_request_uri = remove_query_arg(array_flip($query_args), $current_request_uri);
424
+		// and re-add the page id if it was set
425
+		if ($page_id) {
426
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
427
+		}
428
+		// remove slashes and ?
429
+		$current_request_uri = trim($current_request_uri, '?/');
430
+		// is current request URI part of the known full reg page URL ?
431
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
432
+	}
433
+
434
+
435
+
436
+	/**
437
+	 *    run
438
+	 *
439
+	 * @access    public
440
+	 * @param WP_Query $WP_Query
441
+	 * @return    void
442
+	 * @throws \EE_Error
443
+	 */
444
+	public static function init($WP_Query)
445
+	{
446
+		EED_Single_Page_Checkout::instance()->run($WP_Query);
447
+	}
448
+
449
+
450
+
451
+	/**
452
+	 *    _initialize - initial module setup
453
+	 *
454
+	 * @access    private
455
+	 * @throws EE_Error
456
+	 * @return    void
457
+	 */
458
+	private function _initialize()
459
+	{
460
+		// ensure SPCO doesn't run twice
461
+		if (EED_Single_Page_Checkout::$_initialized) {
462
+			return;
463
+		}
464
+		try {
465
+			$this->_verify_session();
466
+			// setup the EE_Checkout object
467
+			$this->checkout = $this->_initialize_checkout();
468
+			// filter checkout
469
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
470
+			// get the $_GET
471
+			$this->_get_request_vars();
472
+			if ($this->_block_bots()) {
473
+				return;
474
+			}
475
+			// filter continue_reg
476
+			$this->checkout->continue_reg = apply_filters('FHEE__EED_Single_Page_Checkout__init___continue_reg', true, $this->checkout);
477
+			// load the reg steps array
478
+			if ( ! $this->_load_and_instantiate_reg_steps()) {
479
+				EED_Single_Page_Checkout::$_initialized = true;
480
+				return;
481
+			}
482
+			// set the current step
483
+			$this->checkout->set_current_step($this->checkout->step);
484
+			// and the next step
485
+			$this->checkout->set_next_step();
486
+			// verify that everything has been setup correctly
487
+			if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
488
+				EED_Single_Page_Checkout::$_initialized = true;
489
+				return;
490
+			}
491
+			// lock the transaction
492
+			$this->checkout->transaction->lock();
493
+			// make sure all of our cached objects are added to their respective model entity mappers
494
+			$this->checkout->refresh_all_entities();
495
+			// set amount owing
496
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
497
+			// initialize each reg step, which gives them the chance to potentially alter the process
498
+			$this->_initialize_reg_steps();
499
+			// DEBUG LOG
500
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
501
+			// get reg form
502
+			if( ! $this->_check_form_submission()) {
503
+				EED_Single_Page_Checkout::$_initialized = true;
504
+				return;
505
+			}
506
+			// checkout the action!!!
507
+			$this->_process_form_action();
508
+			// add some style and make it dance
509
+			$this->add_styles_and_scripts();
510
+			// kk... SPCO has successfully run
511
+			EED_Single_Page_Checkout::$_initialized = true;
512
+			// set no cache headers and constants
513
+			EE_System::do_not_cache();
514
+			// add anchor
515
+			add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
516
+			// remove transaction lock
517
+			add_action('shutdown', array($this, 'unlock_transaction'), 1);
518
+		} catch (Exception $e) {
519
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
520
+		}
521
+	}
522
+
523
+
524
+
525
+	/**
526
+	 *    _verify_session
527
+	 * checks that the session is valid and not expired
528
+	 *
529
+	 * @access    private
530
+	 * @throws EE_Error
531
+	 */
532
+	private function _verify_session()
533
+	{
534
+		if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
535
+			throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
536
+		}
537
+		// is session still valid ?
538
+		if (EE_Registry::instance()->SSN->expired() && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === '') {
539
+			$this->checkout = new EE_Checkout();
540
+			EE_Registry::instance()->SSN->reset_cart();
541
+			EE_Registry::instance()->SSN->reset_checkout();
542
+			EE_Registry::instance()->SSN->reset_transaction();
543
+			EE_Error::add_attention(EE_Registry::$i18n_js_strings['registration_expiration_notice'], __FILE__,
544
+				__FUNCTION__, __LINE__);
545
+			EE_Registry::instance()->SSN->reset_expired();
546
+		}
547
+	}
548
+
549
+
550
+
551
+	/**
552
+	 *    _initialize_checkout
553
+	 * loads and instantiates EE_Checkout
554
+	 *
555
+	 * @access    private
556
+	 * @throws EE_Error
557
+	 * @return EE_Checkout
558
+	 */
559
+	private function _initialize_checkout()
560
+	{
561
+		// look in session for existing checkout
562
+		/** @type EE_Checkout $checkout */
563
+		$checkout = EE_Registry::instance()->SSN->checkout();
564
+		// verify
565
+		if ( ! $checkout instanceof EE_Checkout) {
566
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
567
+			$checkout = EE_Registry::instance()->load_file(SPCO_INC_PATH, 'EE_Checkout', 'class', array(), false);
568
+		} else {
569
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
570
+				$this->unlock_transaction();
571
+				wp_safe_redirect($checkout->redirect_url);
572
+				exit();
573
+			}
574
+		}
575
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
576
+		// verify again
577
+		if ( ! $checkout instanceof EE_Checkout) {
578
+			throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
579
+		}
580
+		// reset anything that needs a clean slate for each request
581
+		$checkout->reset_for_current_request();
582
+		return $checkout;
583
+	}
584
+
585
+
586
+
587
+	/**
588
+	 *    _get_request_vars
589
+	 *
590
+	 * @access    private
591
+	 * @return    void
592
+	 * @throws \EE_Error
593
+	 */
594
+	private function _get_request_vars()
595
+	{
596
+		// load classes
597
+		EED_Single_Page_Checkout::load_request_handler();
598
+		//make sure this request is marked as belonging to EE
599
+		EE_Registry::instance()->REQ->set_espresso_page(true);
600
+		// which step is being requested ?
601
+		$this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
602
+		// which step is being edited ?
603
+		$this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
604
+		// and what we're doing on the current step
605
+		$this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
606
+		// timestamp
607
+		$this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
608
+		// returning to edit ?
609
+		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
610
+		// or some other kind of revisit ?
611
+		$this->checkout->revisit = filter_var(
612
+			EE_Registry::instance()->REQ->get('revisit', false),
613
+			FILTER_VALIDATE_BOOLEAN
614
+		);
615
+		// and whether or not to generate a reg form for this request
616
+		$this->checkout->generate_reg_form = filter_var(
617
+			EE_Registry::instance()->REQ->get('generate_reg_form', true),
618
+			FILTER_VALIDATE_BOOLEAN
619
+		);
620
+		// and whether or not to process a reg form submission for this request
621
+		$this->checkout->process_form_submission = filter_var(
622
+			EE_Registry::instance()->REQ->get(
623
+				'process_form_submission',
624
+				$this->checkout->action === 'process_reg_step'
625
+			),
626
+			FILTER_VALIDATE_BOOLEAN
627
+		);
628
+		$this->checkout->process_form_submission = filter_var(
629
+			$this->checkout->action !== 'display_spco_reg_step'
630
+				? $this->checkout->process_form_submission
631
+				: false,
632
+			FILTER_VALIDATE_BOOLEAN
633
+		);
634
+		// $this->_display_request_vars();
635
+	}
636
+
637
+
638
+
639
+	/**
640
+	 *  _display_request_vars
641
+	 *
642
+	 * @access    protected
643
+	 * @return    void
644
+	 */
645
+	protected function _display_request_vars()
646
+	{
647
+		if ( ! WP_DEBUG) {
648
+			return;
649
+		}
650
+		EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
651
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
652
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
653
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
654
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
655
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
656
+		EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
657
+		EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
658
+	}
659
+
660
+
661
+
662
+	/**
663
+	 * _block_bots
664
+	 * checks that the incoming request has either of the following set:
665
+	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
666
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
667
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
668
+	 * then where you coming from man?
669
+	 *
670
+	 * @return boolean
671
+	 */
672
+	private function _block_bots()
673
+	{
674
+		$invalid_checkout_access = \EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
675
+		if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
676
+			return true;
677
+		}
678
+		return false;
679
+	}
680
+
681
+
682
+
683
+	/**
684
+	 *    _get_first_step
685
+	 *  gets slug for first step in $_reg_steps_array
686
+	 *
687
+	 * @access    private
688
+	 * @throws EE_Error
689
+	 * @return    string
690
+	 */
691
+	private function _get_first_step()
692
+	{
693
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
694
+		return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
695
+	}
696
+
697
+
698
+
699
+	/**
700
+	 *    _load_and_instantiate_reg_steps
701
+	 *  instantiates each reg step based on the loaded reg_steps array
702
+	 *
703
+	 * @access    private
704
+	 * @throws EE_Error
705
+	 * @return    bool
706
+	 */
707
+	private function _load_and_instantiate_reg_steps()
708
+	{
709
+		// have reg_steps already been instantiated ?
710
+		if (
711
+			empty($this->checkout->reg_steps)
712
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
713
+		) {
714
+			// if not, then loop through raw reg steps array
715
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
716
+				if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
717
+					return false;
718
+				}
719
+			}
720
+			EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
721
+			EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
722
+			// skip the registration_confirmation page ?
723
+			if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
724
+				// just remove it from the reg steps array
725
+				$this->checkout->remove_reg_step('registration_confirmation', false);
726
+			} else if (
727
+				isset($this->checkout->reg_steps['registration_confirmation'])
728
+				&& EE_Registry::instance()->CFG->registration->reg_confirmation_last
729
+			) {
730
+				// set the order to something big like 100
731
+				$this->checkout->set_reg_step_order('registration_confirmation', 100);
732
+			}
733
+			// filter the array for good luck
734
+			$this->checkout->reg_steps = apply_filters(
735
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
736
+				$this->checkout->reg_steps
737
+			);
738
+			// finally re-sort based on the reg step class order properties
739
+			$this->checkout->sort_reg_steps();
740
+		} else {
741
+			foreach ($this->checkout->reg_steps as $reg_step) {
742
+				// set all current step stati to FALSE
743
+				$reg_step->set_is_current_step(false);
744
+			}
745
+		}
746
+		if (empty($this->checkout->reg_steps)) {
747
+			EE_Error::add_error(__('No Reg Steps were loaded..', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
748
+			return false;
749
+		}
750
+		// make reg step details available to JS
751
+		$this->checkout->set_reg_step_JSON_info();
752
+		return true;
753
+	}
754
+
755
+
756
+
757
+	/**
758
+	 *     _load_and_instantiate_reg_step
759
+	 *
760
+	 * @access    private
761
+	 * @param array $reg_step
762
+	 * @param int   $order
763
+	 * @return bool
764
+	 */
765
+	private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
766
+	{
767
+		// we need a file_path, class_name, and slug to add a reg step
768
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
769
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
770
+			if (
771
+				$this->checkout->reg_url_link
772
+				&& $this->checkout->step !== $reg_step['slug']
773
+				&& $reg_step['slug'] !== 'finalize_registration'
774
+			) {
775
+				return true;
776
+			}
777
+			// instantiate step class using file path and class name
778
+			$reg_step_obj = EE_Registry::instance()->load_file(
779
+				$reg_step['file_path'],
780
+				$reg_step['class_name'],
781
+				'class',
782
+				$this->checkout,
783
+				false
784
+			);
785
+			// did we gets the goods ?
786
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
787
+				// set reg step order based on config
788
+				$reg_step_obj->set_order($order);
789
+				// add instantiated reg step object to the master reg steps array
790
+				$this->checkout->add_reg_step($reg_step_obj);
791
+			} else {
792
+				EE_Error::add_error(
793
+					__('The current step could not be set.', 'event_espresso'),
794
+					__FILE__, __FUNCTION__, __LINE__
795
+				);
796
+				return false;
797
+			}
798
+		} else {
799
+			if (WP_DEBUG) {
800
+				EE_Error::add_error(
801
+					sprintf(
802
+						__('A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s', 'event_espresso'),
803
+						isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
804
+						isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
805
+						isset($reg_step['slug']) ? $reg_step['slug'] : '',
806
+						'<ul>',
807
+						'<li>',
808
+						'</li>',
809
+						'</ul>'
810
+					),
811
+					__FILE__, __FUNCTION__, __LINE__
812
+				);
813
+			}
814
+			return false;
815
+		}
816
+		return true;
817
+	}
818
+
819
+
820
+
821
+	/**
822
+	 * _verify_transaction_and_get_registrations
823
+	 *
824
+	 * @access private
825
+	 * @return bool
826
+	 */
827
+	private function _verify_transaction_and_get_registrations()
828
+	{
829
+		// was there already a valid transaction in the checkout from the session ?
830
+		if ( ! $this->checkout->transaction instanceof EE_Transaction) {
831
+			// get transaction from db or session
832
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
833
+				? $this->_get_transaction_and_cart_for_previous_visit()
834
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
835
+			if ( ! $this->checkout->transaction instanceof EE_Transaction) {
836
+				EE_Error::add_error(
837
+					__('Your Registration and Transaction information could not be retrieved from the db.',
838
+						'event_espresso'),
839
+					__FILE__, __FUNCTION__, __LINE__
840
+				);
841
+				$this->checkout->transaction = EE_Transaction::new_instance();
842
+				// add some style and make it dance
843
+				$this->add_styles_and_scripts();
844
+				EED_Single_Page_Checkout::$_initialized = true;
845
+				return false;
846
+			}
847
+			// and the registrations for the transaction
848
+			$this->_get_registrations($this->checkout->transaction);
849
+		}
850
+		return true;
851
+	}
852
+
853
+
854
+
855
+	/**
856
+	 * _get_transaction_and_cart_for_previous_visit
857
+	 *
858
+	 * @access private
859
+	 * @return mixed EE_Transaction|NULL
860
+	 */
861
+	private function _get_transaction_and_cart_for_previous_visit()
862
+	{
863
+		/** @var $TXN_model EEM_Transaction */
864
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
865
+		// because the reg_url_link is present in the request, this is a return visit to SPCO, so we'll get the transaction data from the db
866
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
867
+		// verify transaction
868
+		if ($transaction instanceof EE_Transaction) {
869
+			// and get the cart that was used for that transaction
870
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
871
+			return $transaction;
872
+		} else {
873
+			EE_Error::add_error(__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
874
+			return null;
875
+		}
876
+	}
877
+
878
+
879
+
880
+	/**
881
+	 * _get_cart_for_transaction
882
+	 *
883
+	 * @access private
884
+	 * @param EE_Transaction $transaction
885
+	 * @return EE_Cart
886
+	 */
887
+	private function _get_cart_for_transaction($transaction)
888
+	{
889
+		return $this->checkout->get_cart_for_transaction($transaction);
890
+	}
891
+
892
+
893
+
894
+	/**
895
+	 * get_cart_for_transaction
896
+	 *
897
+	 * @access public
898
+	 * @param EE_Transaction $transaction
899
+	 * @return EE_Cart
900
+	 */
901
+	public function get_cart_for_transaction(EE_Transaction $transaction)
902
+	{
903
+		return $this->checkout->get_cart_for_transaction($transaction);
904
+	}
905
+
906
+
907
+
908
+	/**
909
+	 * _get_transaction_and_cart_for_current_session
910
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
911
+	 *
912
+	 * @access private
913
+	 * @return EE_Transaction
914
+	 * @throws \EE_Error
915
+	 */
916
+	private function _get_cart_for_current_session_and_setup_new_transaction()
917
+	{
918
+		//  if there's no transaction, then this is the FIRST visit to SPCO
919
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
920
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
921
+		// and then create a new transaction
922
+		$transaction = $this->_initialize_transaction();
923
+		// verify transaction
924
+		if ($transaction instanceof EE_Transaction) {
925
+			// save it so that we have an ID for other objects to use
926
+			$transaction->save();
927
+			// and save TXN data to the cart
928
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
929
+		} else {
930
+			EE_Error::add_error(__('A Valid Transaction could not be initialized.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
931
+		}
932
+		return $transaction;
933
+	}
934
+
935
+
936
+
937
+	/**
938
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
939
+	 *
940
+	 * @access private
941
+	 * @return mixed EE_Transaction|NULL
942
+	 */
943
+	private function _initialize_transaction()
944
+	{
945
+		try {
946
+			// ensure cart totals have been calculated
947
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
948
+			// grab the cart grand total
949
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
950
+			// create new TXN
951
+			$transaction = EE_Transaction::new_instance(
952
+				array(
953
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
954
+					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
955
+					'TXN_paid'      => 0,
956
+					'STS_ID'        => EEM_Transaction::failed_status_code,
957
+				)
958
+			);
959
+			// save it so that we have an ID for other objects to use
960
+			$transaction->save();
961
+			// set cron job for following up on TXNs after their session has expired
962
+			EE_Cron_Tasks::schedule_expired_transaction_check(
963
+				EE_Registry::instance()->SSN->expiration() + 1,
964
+				$transaction->ID()
965
+			);
966
+			return $transaction;
967
+		} catch (Exception $e) {
968
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
969
+		}
970
+		return null;
971
+	}
972
+
973
+
974
+
975
+	/**
976
+	 * _get_registrations
977
+	 *
978
+	 * @access private
979
+	 * @param EE_Transaction $transaction
980
+	 * @return void
981
+	 * @throws \EventEspresso\core\exceptions\InvalidEntityException
982
+	 * @throws \EE_Error
983
+	 */
984
+	private function _get_registrations(EE_Transaction $transaction)
985
+	{
986
+		// first step: grab the registrants  { : o
987
+		$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
988
+		// verify registrations have been set
989
+		if (empty($registrations)) {
990
+			// if no cached registrations, then check the db
991
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
992
+			// still nothing ? well as long as this isn't a revisit
993
+			if (empty($registrations) && ! $this->checkout->revisit) {
994
+				// generate new registrations from scratch
995
+				$registrations = $this->_initialize_registrations($transaction);
996
+			}
997
+		}
998
+		// sort by their original registration order
999
+		usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1000
+		// then loop thru the array
1001
+		foreach ($registrations as $registration) {
1002
+			// verify each registration
1003
+			if ($registration instanceof EE_Registration) {
1004
+				// we display all attendee info for the primary registrant
1005
+				if ($this->checkout->reg_url_link === $registration->reg_url_link()
1006
+					&& $registration->is_primary_registrant()
1007
+				) {
1008
+					$this->checkout->primary_revisit = true;
1009
+					break;
1010
+				} else if ($this->checkout->revisit
1011
+						   && $this->checkout->reg_url_link !== $registration->reg_url_link()
1012
+				) {
1013
+					// but hide info if it doesn't belong to you
1014
+					$transaction->clear_cache('Registration', $registration->ID());
1015
+				}
1016
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1017
+			}
1018
+		}
1019
+	}
1020
+
1021
+
1022
+
1023
+	/**
1024
+	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1025
+	 *
1026
+	 * @access private
1027
+	 * @param EE_Transaction $transaction
1028
+	 * @return    array
1029
+	 * @throws \EventEspresso\core\exceptions\InvalidEntityException
1030
+	 * @throws \EE_Error
1031
+	 */
1032
+	private function _initialize_registrations(EE_Transaction $transaction)
1033
+	{
1034
+		$att_nmbr = 0;
1035
+		$registrations = array();
1036
+		if ($transaction instanceof EE_Transaction) {
1037
+			/** @type EE_Registration_Processor $registration_processor */
1038
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1039
+			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1040
+			// now let's add the cart items to the $transaction
1041
+			foreach ($this->checkout->cart->get_tickets() as $line_item) {
1042
+				//do the following for each ticket of this type they selected
1043
+				for ($x = 1; $x <= $line_item->quantity(); $x++) {
1044
+					$att_nmbr++;
1045
+					/** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1046
+					$CreateRegistrationCommand = EE_Registry::instance()
1047
+															->create(
1048
+																'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1049
+																array(
1050
+																	$transaction,
1051
+																	$line_item,
1052
+																	$att_nmbr,
1053
+																	$this->checkout->total_ticket_count,
1054
+																)
1055
+															);
1056
+					// override capabilities for frontend registrations
1057
+					if ( ! is_admin()) {
1058
+						$CreateRegistrationCommand->setCapCheck(
1059
+							new PublicCapabilities('', 'create_new_registration')
1060
+						);
1061
+					}
1062
+					$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1063
+					if ( ! $registration instanceof EE_Registration) {
1064
+						throw new InvalidEntityException($registration, 'EE_Registration');
1065
+					}
1066
+					$registrations[ $registration->ID() ] = $registration;
1067
+				}
1068
+			}
1069
+			$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1070
+		}
1071
+		return $registrations;
1072
+	}
1073
+
1074
+
1075
+
1076
+	/**
1077
+	 * sorts registrations by REG_count
1078
+	 *
1079
+	 * @access public
1080
+	 * @param EE_Registration $reg_A
1081
+	 * @param EE_Registration $reg_B
1082
+	 * @return int
1083
+	 */
1084
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1085
+	{
1086
+		// this shouldn't ever happen within the same TXN, but oh well
1087
+		if ($reg_A->count() === $reg_B->count()) {
1088
+			return 0;
1089
+		}
1090
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1091
+	}
1092
+
1093
+
1094
+
1095
+	/**
1096
+	 *    _final_verifications
1097
+	 * just makes sure that everything is set up correctly before proceeding
1098
+	 *
1099
+	 * @access    private
1100
+	 * @return    bool
1101
+	 * @throws \EE_Error
1102
+	 */
1103
+	private function _final_verifications()
1104
+	{
1105
+		// filter checkout
1106
+		$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___final_verifications__checkout', $this->checkout);
1107
+		//verify that current step is still set correctly
1108
+		if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1109
+			EE_Error::add_error(
1110
+				__('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1111
+				__FILE__,
1112
+				__FUNCTION__,
1113
+				__LINE__
1114
+			);
1115
+			return false;
1116
+		}
1117
+		// if returning to SPCO, then verify that primary registrant is set
1118
+		if ( ! empty($this->checkout->reg_url_link)) {
1119
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1120
+			if ( ! $valid_registrant instanceof EE_Registration) {
1121
+				EE_Error::add_error(
1122
+					__('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1123
+					__FILE__,
1124
+					__FUNCTION__,
1125
+					__LINE__
1126
+				);
1127
+				return false;
1128
+			}
1129
+			$valid_registrant = null;
1130
+			foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1131
+				if (
1132
+					$registration instanceof EE_Registration
1133
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1134
+				) {
1135
+					$valid_registrant = $registration;
1136
+				}
1137
+			}
1138
+			if ( ! $valid_registrant instanceof EE_Registration) {
1139
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1140
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1141
+					// clear the session, mark the checkout as unverified, and try again
1142
+					EE_Registry::instance()->SSN->clear_session();
1143
+					EED_Single_Page_Checkout::$_initialized = false;
1144
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1145
+					$this->_initialize();
1146
+					EE_Error::reset_notices();
1147
+					return false;
1148
+				}
1149
+				EE_Error::add_error(
1150
+					__('We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.', 'event_espresso'),
1151
+					__FILE__,
1152
+					__FUNCTION__,
1153
+					__LINE__
1154
+				);
1155
+				return false;
1156
+			}
1157
+		}
1158
+		// now that things have been kinda sufficiently verified,
1159
+		// let's add the checkout to the session so that's available other systems
1160
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1161
+		return true;
1162
+	}
1163
+
1164
+
1165
+
1166
+	/**
1167
+	 *    _initialize_reg_steps
1168
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1169
+	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1170
+	 *
1171
+	 * @access    private
1172
+	 * @param bool $reinitializing
1173
+	 * @throws \EE_Error
1174
+	 */
1175
+	private function _initialize_reg_steps($reinitializing = false)
1176
+	{
1177
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1178
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1179
+		foreach ($this->checkout->reg_steps as $reg_step) {
1180
+			if ( ! $reg_step->initialize_reg_step()) {
1181
+				// if not initialized then maybe this step is being removed...
1182
+				if ( ! $reinitializing && $reg_step->is_current_step()) {
1183
+					// if it was the current step, then we need to start over here
1184
+					$this->_initialize_reg_steps(true);
1185
+					return;
1186
+				}
1187
+				continue;
1188
+			}
1189
+			// add css and JS for current step
1190
+			$reg_step->enqueue_styles_and_scripts();
1191
+			// i18n
1192
+			$reg_step->translate_js_strings();
1193
+			if ($reg_step->is_current_step()) {
1194
+				// the text that appears on the reg step form submit button
1195
+				$reg_step->set_submit_button_text();
1196
+			}
1197
+		}
1198
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1199
+		do_action("AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}", $this->checkout->current_step);
1200
+	}
1201
+
1202
+
1203
+
1204
+	/**
1205
+	 * _check_form_submission
1206
+	 *
1207
+	 * @access private
1208
+	 * @return boolean
1209
+	 */
1210
+	private function _check_form_submission()
1211
+	{
1212
+		//does this request require the reg form to be generated ?
1213
+		if ($this->checkout->generate_reg_form) {
1214
+			// ever heard that song by Blue Rodeo ?
1215
+			try {
1216
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1217
+				// if not displaying a form, then check for form submission
1218
+				if (
1219
+					$this->checkout->process_form_submission
1220
+					&& $this->checkout->current_step->reg_form->was_submitted()
1221
+				) {
1222
+					// clear out any old data in case this step is being run again
1223
+					$this->checkout->current_step->set_valid_data(array());
1224
+					// capture submitted form data
1225
+					$this->checkout->current_step->reg_form->receive_form_submission(
1226
+						apply_filters('FHEE__Single_Page_Checkout___check_form_submission__request_params', EE_Registry::instance()->REQ->params(), $this->checkout)
1227
+					);
1228
+					// validate submitted form data
1229
+					if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1230
+						// thou shall not pass !!!
1231
+						$this->checkout->continue_reg = false;
1232
+						// any form validation errors?
1233
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1234
+							$submission_error_messages = array();
1235
+							// bad, bad, bad registrant
1236
+							foreach ($this->checkout->current_step->reg_form->get_validation_errors_accumulated() as $validation_error) {
1237
+								if ($validation_error instanceof EE_Validation_Error) {
1238
+									$submission_error_messages[] = sprintf(
1239
+										__('%s : %s', 'event_espresso'),
1240
+										$validation_error->get_form_section()->html_label_text(),
1241
+										$validation_error->getMessage()
1242
+									);
1243
+								}
1244
+							}
1245
+							EE_Error::add_error(implode('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1246
+						}
1247
+						// well not really... what will happen is we'll just get redirected back to redo the current step
1248
+						$this->go_to_next_step();
1249
+						return false;
1250
+					}
1251
+				}
1252
+			} catch (EE_Error $e) {
1253
+				$e->get_error();
1254
+			}
1255
+		}
1256
+		return true;
1257
+	}
1258
+
1259
+
1260
+
1261
+	/**
1262
+	 * _process_action
1263
+	 *
1264
+	 * @access private
1265
+	 * @return void
1266
+	 * @throws \EE_Error
1267
+	 */
1268
+	private function _process_form_action()
1269
+	{
1270
+		// what cha wanna do?
1271
+		switch ($this->checkout->action) {
1272
+			// AJAX next step reg form
1273
+			case 'display_spco_reg_step' :
1274
+				$this->checkout->redirect = false;
1275
+				if (EE_Registry::instance()->REQ->ajax) {
1276
+					$this->checkout->json_response->set_reg_step_html($this->checkout->current_step->display_reg_form());
1277
+				}
1278
+				break;
1279
+			default :
1280
+				// meh... do one of those other steps first
1281
+				if ( ! empty($this->checkout->action) && is_callable(array($this->checkout->current_step, $this->checkout->action))) {
1282
+					// dynamically creates hook point like: AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1283
+					do_action("AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1284
+					// call action on current step
1285
+					if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1286
+						// good registrant, you get to proceed
1287
+						if (
1288
+							$this->checkout->current_step->success_message() !== ''
1289
+							&& apply_filters(
1290
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1291
+								false
1292
+							)
1293
+						) {
1294
+							EE_Error::add_success(
1295
+								$this->checkout->current_step->success_message()
1296
+								. '<br />' . $this->checkout->next_step->_instructions()
1297
+							);
1298
+						}
1299
+						// pack it up, pack it in...
1300
+						$this->_setup_redirect();
1301
+					}
1302
+					// dynamically creates hook point like: AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1303
+					do_action("AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1304
+				} else {
1305
+					EE_Error::add_error(
1306
+						sprintf(
1307
+							__('The requested form action "%s" does not exist for the current "%s" registration step.', 'event_espresso'),
1308
+							$this->checkout->action,
1309
+							$this->checkout->current_step->name()
1310
+						),
1311
+						__FILE__,
1312
+						__FUNCTION__,
1313
+						__LINE__
1314
+					);
1315
+				}
1316
+			// end default
1317
+		}
1318
+		// store our progress so far
1319
+		$this->checkout->stash_transaction_and_checkout();
1320
+		// advance to the next step! If you pass GO, collect $200
1321
+		$this->go_to_next_step();
1322
+	}
1323
+
1324
+
1325
+
1326
+	/**
1327
+	 *        add_styles_and_scripts
1328
+	 *
1329
+	 * @access        public
1330
+	 * @return        void
1331
+	 */
1332
+	public function add_styles_and_scripts()
1333
+	{
1334
+		// i18n
1335
+		$this->translate_js_strings();
1336
+		if ($this->checkout->admin_request) {
1337
+			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1338
+		} else {
1339
+			add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1340
+		}
1341
+	}
1342
+
1343
+
1344
+
1345
+	/**
1346
+	 *        translate_js_strings
1347
+	 *
1348
+	 * @access        public
1349
+	 * @return        void
1350
+	 */
1351
+	public function translate_js_strings()
1352
+	{
1353
+		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1354
+		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1355
+		EE_Registry::$i18n_js_strings['server_error'] = __('An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1356
+		EE_Registry::$i18n_js_strings['invalid_json_response'] = __('An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1357
+		EE_Registry::$i18n_js_strings['validation_error'] = __('There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.', 'event_espresso');
1358
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = __('There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.', 'event_espresso');
1359
+		EE_Registry::$i18n_js_strings['reg_step_error'] = __('This registration step could not be completed. Please refresh the page and try again.', 'event_espresso');
1360
+		EE_Registry::$i18n_js_strings['invalid_coupon'] = __('We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.', 'event_espresso');
1361
+		EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1362
+			__('Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.', 'event_espresso'),
1363
+			'<br/>',
1364
+			'<br/>'
1365
+		);
1366
+		EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1367
+		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1368
+		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1369
+		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1370
+		EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1371
+		EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1372
+		EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1373
+		EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1374
+		EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1375
+		EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1376
+		EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1377
+		EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1378
+		EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1379
+		EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1380
+		EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1381
+		EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1382
+		EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1383
+		EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1384
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1385
+			__(
1386
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
1387
+				'event_espresso'
1388
+			),
1389
+			'<h4 class="important-notice">',
1390
+			'</h4>',
1391
+			'<br />',
1392
+			'<p>',
1393
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1394
+			'">',
1395
+			'</a>',
1396
+			'</p>'
1397
+		);
1398
+		EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters('FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', true);
1399
+		EE_Registry::$i18n_js_strings['session_extension'] = absint(
1400
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1401
+		);
1402
+		EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1403
+			'M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1404
+		);
1405
+	}
1406
+
1407
+
1408
+
1409
+	/**
1410
+	 *    enqueue_styles_and_scripts
1411
+	 *
1412
+	 * @access        public
1413
+	 * @return        void
1414
+	 * @throws \EE_Error
1415
+	 */
1416
+	public function enqueue_styles_and_scripts()
1417
+	{
1418
+		// load css
1419
+		wp_register_style('single_page_checkout', SPCO_CSS_URL . 'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION);
1420
+		wp_enqueue_style('single_page_checkout');
1421
+		// load JS
1422
+		wp_register_script('jquery_plugin', EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js', array('jquery'), '1.0.1', true);
1423
+		wp_register_script('jquery_countdown', EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js', array('jquery_plugin'), '2.0.2', true);
1424
+		wp_register_script('single_page_checkout', SPCO_JS_URL . 'single_page_checkout.js', array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'), EVENT_ESPRESSO_VERSION, true);
1425
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1426
+			$this->checkout->registration_form->enqueue_js();
1427
+		}
1428
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1429
+			$this->checkout->current_step->reg_form->enqueue_js();
1430
+		}
1431
+		wp_enqueue_script('single_page_checkout');
1432
+		/**
1433
+		 * global action hook for enqueueing styles and scripts with
1434
+		 * spco calls.
1435
+		 */
1436
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1437
+		/**
1438
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1439
+		 * The hook will end up being something like AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1440
+		 */
1441
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(), $this);
1442
+	}
1443
+
1444
+
1445
+
1446
+	/**
1447
+	 *    display the Registration Single Page Checkout Form
1448
+	 *
1449
+	 * @access    private
1450
+	 * @return    void
1451
+	 * @throws \EE_Error
1452
+	 */
1453
+	private function _display_spco_reg_form()
1454
+	{
1455
+		// if registering via the admin, just display the reg form for the current step
1456
+		if ($this->checkout->admin_request) {
1457
+			EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1458
+		} else {
1459
+			// add powered by EE msg
1460
+			add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1461
+			$empty_cart = count($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)) < 1
1462
+				? true
1463
+				: false;
1464
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1465
+			$cookies_not_set_msg = '';
1466
+			if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1467
+				$cookies_not_set_msg = apply_filters(
1468
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1469
+					sprintf(
1470
+						__(
1471
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1472
+							'event_espresso'
1473
+						),
1474
+						'<div class="ee-attention">',
1475
+						'</div>',
1476
+						'<h6 class="important-notice">',
1477
+						'</h6>',
1478
+						'<p>',
1479
+						'</p>',
1480
+						'<br />',
1481
+						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1482
+						'</a>'
1483
+					)
1484
+				);
1485
+			}
1486
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1487
+				array(
1488
+					'name'            => 'single-page-checkout',
1489
+					'html_id'         => 'ee-single-page-checkout-dv',
1490
+					'layout_strategy' =>
1491
+						new EE_Template_Layout(
1492
+							array(
1493
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1494
+								'template_args'        => array(
1495
+									'empty_cart'              => $empty_cart,
1496
+									'revisit'                 => $this->checkout->revisit,
1497
+									'reg_steps'               => $this->checkout->reg_steps,
1498
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1499
+										? $this->checkout->next_step->slug()
1500
+										: '',
1501
+									'cancel_page_url'         => $this->checkout->cancel_page_url,
1502
+									'empty_msg'               => apply_filters(
1503
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1504
+										sprintf(
1505
+											__('You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1506
+												'event_espresso'),
1507
+											'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1508
+											'">',
1509
+											'</a>'
1510
+										)
1511
+									),
1512
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1513
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1514
+									'session_expiration'      =>
1515
+										date('M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)),
1516
+								),
1517
+							)
1518
+						),
1519
+				)
1520
+			);
1521
+			// load template and add to output sent that gets filtered into the_content()
1522
+			EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1523
+		}
1524
+	}
1525
+
1526
+
1527
+
1528
+	/**
1529
+	 *    add_extra_finalize_registration_inputs
1530
+	 *
1531
+	 * @access    public
1532
+	 * @param $next_step
1533
+	 * @internal  param string $label
1534
+	 * @return void
1535
+	 */
1536
+	public function add_extra_finalize_registration_inputs($next_step)
1537
+	{
1538
+		if ($next_step === 'finalize_registration') {
1539
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1540
+		}
1541
+	}
1542
+
1543
+
1544
+
1545
+	/**
1546
+	 *    display_registration_footer
1547
+	 *
1548
+	 * @access    public
1549
+	 * @return    string
1550
+	 */
1551
+	public static function display_registration_footer()
1552
+	{
1553
+		if (
1554
+		apply_filters(
1555
+			'FHEE__EE_Front__Controller__show_reg_footer',
1556
+			EE_Registry::instance()->CFG->admin->show_reg_footer
1557
+		)
1558
+		) {
1559
+			add_filter(
1560
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1561
+				function ($url) {
1562
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1563
+				}
1564
+			);
1565
+			echo apply_filters(
1566
+				'FHEE__EE_Front_Controller__display_registration_footer',
1567
+				\EEH_Template::powered_by_event_espresso(
1568
+					'',
1569
+					'espresso-registration-footer-dv',
1570
+					array('utm_content' => 'registration_checkout')
1571
+				)
1572
+			);
1573
+		}
1574
+		return '';
1575
+	}
1576
+
1577
+
1578
+
1579
+	/**
1580
+	 *    unlock_transaction
1581
+	 *
1582
+	 * @access    public
1583
+	 * @return    void
1584
+	 * @throws \EE_Error
1585
+	 */
1586
+	public function unlock_transaction()
1587
+	{
1588
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1589
+			$this->checkout->transaction->unlock();
1590
+		}
1591
+	}
1592
+
1593
+
1594
+
1595
+	/**
1596
+	 *        _setup_redirect
1597
+	 *
1598
+	 * @access    private
1599
+	 * @return void
1600
+	 */
1601
+	private function _setup_redirect()
1602
+	{
1603
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1604
+			$this->checkout->redirect = true;
1605
+			if (empty($this->checkout->redirect_url)) {
1606
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1607
+			}
1608
+			$this->checkout->redirect_url = apply_filters(
1609
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1610
+				$this->checkout->redirect_url,
1611
+				$this->checkout
1612
+			);
1613
+		}
1614
+	}
1615
+
1616
+
1617
+
1618
+	/**
1619
+	 *   handle ajax message responses and redirects
1620
+	 *
1621
+	 * @access public
1622
+	 * @return void
1623
+	 * @throws \EE_Error
1624
+	 */
1625
+	public function go_to_next_step()
1626
+	{
1627
+		if (EE_Registry::instance()->REQ->ajax) {
1628
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1629
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1630
+		}
1631
+		$this->unlock_transaction();
1632
+		// just return for these conditions
1633
+		if (
1634
+			$this->checkout->admin_request
1635
+			|| $this->checkout->action === 'redirect_form'
1636
+			|| $this->checkout->action === 'update_checkout'
1637
+		) {
1638
+			return;
1639
+		}
1640
+		// AJAX response
1641
+		$this->_handle_json_response();
1642
+		// redirect to next step or the Thank You page
1643
+		$this->_handle_html_redirects();
1644
+		// hmmm... must be something wrong, so let's just display the form again !
1645
+		$this->_display_spco_reg_form();
1646
+	}
1647
+
1648
+
1649
+
1650
+	/**
1651
+	 *   _handle_json_response
1652
+	 *
1653
+	 * @access protected
1654
+	 * @return void
1655
+	 */
1656
+	protected function _handle_json_response()
1657
+	{
1658
+		// if this is an ajax request
1659
+		if (EE_Registry::instance()->REQ->ajax) {
1660
+			// DEBUG LOG
1661
+			//$this->checkout->log(
1662
+			//	__CLASS__, __FUNCTION__, __LINE__,
1663
+			//	array(
1664
+			//		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1665
+			//		'redirect'                   => $this->checkout->redirect,
1666
+			//		'continue_reg'               => $this->checkout->continue_reg,
1667
+			//	)
1668
+			//);
1669
+			$this->checkout->json_response->set_registration_time_limit(
1670
+				$this->checkout->get_registration_time_limit()
1671
+			);
1672
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1673
+			// just send the ajax (
1674
+			$json_response = apply_filters(
1675
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1676
+				$this->checkout->json_response
1677
+			);
1678
+			echo $json_response;
1679
+			exit();
1680
+		}
1681
+	}
1682
+
1683
+
1684
+
1685
+	/**
1686
+	 *   _handle_redirects
1687
+	 *
1688
+	 * @access protected
1689
+	 * @return void
1690
+	 */
1691
+	protected function _handle_html_redirects()
1692
+	{
1693
+		// going somewhere ?
1694
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1695
+			// store notices in a transient
1696
+			EE_Error::get_notices(false, true, true);
1697
+			// DEBUG LOG
1698
+			//$this->checkout->log(
1699
+			//	__CLASS__, __FUNCTION__, __LINE__,
1700
+			//	array(
1701
+			//		'headers_sent' => headers_sent(),
1702
+			//		'redirect_url'     => $this->checkout->redirect_url,
1703
+			//		'headers_list'    => headers_list(),
1704
+			//	)
1705
+			//);
1706
+			wp_safe_redirect($this->checkout->redirect_url);
1707
+			exit();
1708
+		}
1709
+	}
1710
+
1711
+
1712
+
1713
+	/**
1714
+	 *   set_checkout_anchor
1715
+	 *
1716
+	 * @access public
1717
+	 * @return void
1718
+	 */
1719
+	public function set_checkout_anchor()
1720
+	{
1721
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1722
+	}
1723 1723
 
1724 1724
 
1725 1725
 
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -216,13 +216,13 @@  discard block
 block discarded – undo
216 216
      */
217 217
     public static function set_definitions()
218 218
     {
219
-        define('SPCO_BASE_PATH', rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS);
220
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
221
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
222
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
223
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
224
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
225
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
219
+        define('SPCO_BASE_PATH', rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS).DS);
220
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css'.DS);
221
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img'.DS);
222
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js'.DS);
223
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc'.DS);
224
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps'.DS);
225
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates'.DS);
226 226
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
227 227
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
228 228
             __('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
             '</h4>',
232 232
             '<br />',
233 233
             '<p>',
234
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
234
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
235 235
             '">',
236 236
             '</a>',
237 237
             '</p>'
@@ -255,7 +255,7 @@  discard block
 block discarded – undo
255 255
             return;
256 256
         }
257 257
         // filter list of reg_steps
258
-        $reg_steps_to_load = (array)apply_filters(
258
+        $reg_steps_to_load = (array) apply_filters(
259 259
             'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
260 260
             EED_Single_Page_Checkout::get_reg_steps()
261 261
         );
@@ -299,25 +299,25 @@  discard block
 block discarded – undo
299 299
         if (empty($reg_steps)) {
300 300
             $reg_steps = array(
301 301
                 10  => array(
302
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
302
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
303 303
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
304 304
                     'slug'       => 'attendee_information',
305 305
                     'has_hooks'  => false,
306 306
                 ),
307 307
                 20  => array(
308
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
308
+                    'file_path'  => SPCO_REG_STEPS_PATH.'registration_confirmation',
309 309
                     'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
310 310
                     'slug'       => 'registration_confirmation',
311 311
                     'has_hooks'  => false,
312 312
                 ),
313 313
                 30  => array(
314
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
314
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
315 315
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
316 316
                     'slug'       => 'payment_options',
317 317
                     'has_hooks'  => true,
318 318
                 ),
319 319
                 999 => array(
320
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
320
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
321 321
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
322 322
                     'slug'       => 'finalize_registration',
323 323
                     'has_hooks'  => false,
@@ -499,7 +499,7 @@  discard block
 block discarded – undo
499 499
             // DEBUG LOG
500 500
             //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
501 501
             // get reg form
502
-            if( ! $this->_check_form_submission()) {
502
+            if ( ! $this->_check_form_submission()) {
503 503
                 EED_Single_Page_Checkout::$_initialized = true;
504 504
                 return;
505 505
             }
@@ -1063,7 +1063,7 @@  discard block
 block discarded – undo
1063 1063
                     if ( ! $registration instanceof EE_Registration) {
1064 1064
                         throw new InvalidEntityException($registration, 'EE_Registration');
1065 1065
                     }
1066
-                    $registrations[ $registration->ID() ] = $registration;
1066
+                    $registrations[$registration->ID()] = $registration;
1067 1067
                 }
1068 1068
             }
1069 1069
             $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1293,7 +1293,7 @@  discard block
 block discarded – undo
1293 1293
                         ) {
1294 1294
                             EE_Error::add_success(
1295 1295
                                 $this->checkout->current_step->success_message()
1296
-                                . '<br />' . $this->checkout->next_step->_instructions()
1296
+                                . '<br />'.$this->checkout->next_step->_instructions()
1297 1297
                             );
1298 1298
                         }
1299 1299
                         // pack it up, pack it in...
@@ -1390,7 +1390,7 @@  discard block
 block discarded – undo
1390 1390
             '</h4>',
1391 1391
             '<br />',
1392 1392
             '<p>',
1393
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1393
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
1394 1394
             '">',
1395 1395
             '</a>',
1396 1396
             '</p>'
@@ -1416,12 +1416,12 @@  discard block
 block discarded – undo
1416 1416
     public function enqueue_styles_and_scripts()
1417 1417
     {
1418 1418
         // load css
1419
-        wp_register_style('single_page_checkout', SPCO_CSS_URL . 'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION);
1419
+        wp_register_style('single_page_checkout', SPCO_CSS_URL.'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION);
1420 1420
         wp_enqueue_style('single_page_checkout');
1421 1421
         // load JS
1422
-        wp_register_script('jquery_plugin', EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js', array('jquery'), '1.0.1', true);
1423
-        wp_register_script('jquery_countdown', EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js', array('jquery_plugin'), '2.0.2', true);
1424
-        wp_register_script('single_page_checkout', SPCO_JS_URL . 'single_page_checkout.js', array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'), EVENT_ESPRESSO_VERSION, true);
1422
+        wp_register_script('jquery_plugin', EE_THIRD_PARTY_URL.'jquery	.plugin.min.js', array('jquery'), '1.0.1', true);
1423
+        wp_register_script('jquery_countdown', EE_THIRD_PARTY_URL.'jquery	.countdown.min.js', array('jquery_plugin'), '2.0.2', true);
1424
+        wp_register_script('single_page_checkout', SPCO_JS_URL.'single_page_checkout.js', array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'), EVENT_ESPRESSO_VERSION, true);
1425 1425
         if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1426 1426
             $this->checkout->registration_form->enqueue_js();
1427 1427
         }
@@ -1438,7 +1438,7 @@  discard block
 block discarded – undo
1438 1438
          * dynamic action hook for enqueueing styles and scripts with spco calls.
1439 1439
          * The hook will end up being something like AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1440 1440
          */
1441
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(), $this);
1441
+        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(), $this);
1442 1442
     }
1443 1443
 
1444 1444
 
@@ -1490,7 +1490,7 @@  discard block
 block discarded – undo
1490 1490
                     'layout_strategy' =>
1491 1491
                         new EE_Template_Layout(
1492 1492
                             array(
1493
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1493
+                                'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
1494 1494
                                 'template_args'        => array(
1495 1495
                                     'empty_cart'              => $empty_cart,
1496 1496
                                     'revisit'                 => $this->checkout->revisit,
@@ -1504,7 +1504,7 @@  discard block
 block discarded – undo
1504 1504
                                         sprintf(
1505 1505
                                             __('You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1506 1506
                                                 'event_espresso'),
1507
-                                            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1507
+                                            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
1508 1508
                                             '">',
1509 1509
                                             '</a>'
1510 1510
                                         )
@@ -1558,7 +1558,7 @@  discard block
 block discarded – undo
1558 1558
         ) {
1559 1559
             add_filter(
1560 1560
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1561
-                function ($url) {
1561
+                function($url) {
1562 1562
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1563 1563
                 }
1564 1564
             );
Please login to merge, or discard this patch.
modules/ticket_selector/EED_Ticket_Selector.module.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -187,7 +187,7 @@  discard block
 block discarded – undo
187 187
 	 *    process_ticket_selections
188 188
 	 *
189 189
 	 * @access        public
190
-	 * @return        array  or FALSE
190
+	 * @return        boolean|null  or FALSE
191 191
 	 * @throws \EE_Error
192 192
 	 */
193 193
 	public function process_ticket_selections() {
@@ -201,7 +201,7 @@  discard block
 block discarded – undo
201 201
      * cancel_ticket_selections
202 202
      *
203 203
      * @access        public
204
-	 * @return        array  or FALSE
204
+	 * @return        false|null  or FALSE
205 205
 	 * @throws \EE_Error
206 206
 	 */
207 207
 	public function cancel_ticket_selections() {
Please login to merge, or discard this patch.
Indentation   +165 added lines, -165 removed lines patch added patch discarded remove patch
@@ -22,15 +22,15 @@  discard block
 block discarded – undo
22 22
  */
23 23
 class EED_Ticket_Selector extends  EED_Module {
24 24
 
25
-    /**
26
-     * @var EventEspresso\modules\ticket_selector\DisplayTicketSelector $ticket_selector
27
-     */
28
-    private static $ticket_selector;
25
+	/**
26
+	 * @var EventEspresso\modules\ticket_selector\DisplayTicketSelector $ticket_selector
27
+	 */
28
+	private static $ticket_selector;
29 29
 
30
-    /**
31
-     * @var EventEspresso\modules\ticket_selector\TicketSelectorIframeEmbedButton $iframe_embed_button
32
-     */
33
-    private static $iframe_embed_button;
30
+	/**
31
+	 * @var EventEspresso\modules\ticket_selector\TicketSelectorIframeEmbedButton $iframe_embed_button
32
+	 */
33
+	private static $iframe_embed_button;
34 34
 
35 35
 
36 36
 
@@ -61,8 +61,8 @@  discard block
 block discarded – undo
61 61
 		// routing
62 62
 		EE_Config::register_route( 'iframe', 'EED_Ticket_Selector', 'ticket_selector_iframe', 'ticket_selector' );
63 63
 		EE_Config::register_route( 'process_ticket_selections', 'EED_Ticket_Selector', 'process_ticket_selections' );
64
-        EE_Config::register_route('cancel_ticket_selections', 'EED_Ticket_Selector', 'cancel_ticket_selections');
65
-        add_action( 'wp_loaded', array( 'EED_Ticket_Selector', 'set_definitions' ), 2 );
64
+		EE_Config::register_route('cancel_ticket_selections', 'EED_Ticket_Selector', 'cancel_ticket_selections');
65
+		add_action( 'wp_loaded', array( 'EED_Ticket_Selector', 'set_definitions' ), 2 );
66 66
 		add_action( 'AHEE_event_details_header_bottom', array( 'EED_Ticket_Selector', 'display_ticket_selector' ), 10, 1 );
67 67
 		add_action( 'wp_enqueue_scripts', array( 'EED_Ticket_Selector', 'load_tckt_slctr_assets' ), 10 );
68 68
 	}
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 			array( 'EED_Ticket_Selector', 'ticket_selector_iframe_embed_button' ),
84 84
 			10
85 85
 		);
86
-    }
86
+	}
87 87
 
88 88
 
89 89
 
@@ -99,23 +99,23 @@  discard block
 block discarded – undo
99 99
 
100 100
 		//if config is not set, initialize
101 101
 		if ( ! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config ) {
102
-            \EED_Ticket_Selector::instance()->set_config();
103
-            \EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector = \EED_Ticket_Selector::instance()->config();
102
+			\EED_Ticket_Selector::instance()->set_config();
103
+			\EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector = \EED_Ticket_Selector::instance()->config();
104 104
 		}
105 105
 	}
106 106
 
107 107
 
108 108
 
109 109
 	/**
110
-     * @return \EventEspresso\modules\ticket_selector\DisplayTicketSelector
111
-     */
112
-    public static function ticketSelector()
113
-    {
114
-        if ( ! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
115
-            EED_Ticket_Selector::$ticket_selector = new DisplayTicketSelector();
116
-        }
117
-        return EED_Ticket_Selector::$ticket_selector;
118
-    }
110
+	 * @return \EventEspresso\modules\ticket_selector\DisplayTicketSelector
111
+	 */
112
+	public static function ticketSelector()
113
+	{
114
+		if ( ! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
115
+			EED_Ticket_Selector::$ticket_selector = new DisplayTicketSelector();
116
+		}
117
+		return EED_Ticket_Selector::$ticket_selector;
118
+	}
119 119
 
120 120
 
121 121
 	/**
@@ -168,15 +168,15 @@  discard block
 block discarded – undo
168 168
 
169 169
 
170 170
 
171
-    /**
172
-     *    creates buttons for selecting number of attendees for an event
173
-     *
174
-     * @access    public
175
-     * @param    WP_Post|int $event
176
-     * @param    bool        $view_details
177
-     * @return    string
178
-     * @throws \EE_Error
179
-     */
171
+	/**
172
+	 *    creates buttons for selecting number of attendees for an event
173
+	 *
174
+	 * @access    public
175
+	 * @param    WP_Post|int $event
176
+	 * @param    bool        $view_details
177
+	 * @return    string
178
+	 * @throws \EE_Error
179
+	 */
180 180
 	public static function display_ticket_selector( $event = NULL, $view_details = FALSE ) {
181 181
 		return EED_Ticket_Selector::ticketSelector()->display( $event, $view_details );
182 182
 	}
@@ -198,9 +198,9 @@  discard block
 block discarded – undo
198 198
 
199 199
 
200 200
 	/**
201
-     * cancel_ticket_selections
202
-     *
203
-     * @access        public
201
+	 * cancel_ticket_selections
202
+	 *
203
+	 * @access        public
204 204
 	 * @return        array  or FALSE
205 205
 	 * @throws \EE_Error
206 206
 	 */
@@ -212,11 +212,11 @@  discard block
 block discarded – undo
212 212
 
213 213
 
214 214
 	/**
215
-	* 	load js
216
-	*
217
-	* 	@access 		public
218
-	* 	@return 		void
219
-	*/
215
+	 * 	load js
216
+	 *
217
+	 * 	@access 		public
218
+	 * 	@return 		void
219
+	 */
220 220
 	public static function load_tckt_slctr_assets() {
221 221
 		if ( apply_filters( 'FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', FALSE ) ) {
222 222
 			// add some style
@@ -225,9 +225,9 @@  discard block
 block discarded – undo
225 225
 			// make it dance
226 226
 			wp_register_script('ticket_selector', TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js', array('espresso_core'), '', TRUE);
227 227
 			wp_enqueue_script('ticket_selector');
228
-            require_once( EE_LIBRARIES.'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php');
229
-            \EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
230
-        }
228
+			require_once( EE_LIBRARIES.'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php');
229
+			\EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
230
+		}
231 231
 	}
232 232
 
233 233
 
@@ -236,129 +236,129 @@  discard block
 block discarded – undo
236 236
 
237 237
 
238 238
 
239
-    /**
240
-     * @deprecated
241
-     * @return string
242
-     * @throws \EE_Error
243
-     */
244
-    public static function display_view_details_btn()
245
-    {
246
-        // todo add doing_it_wrong() notice during next major version
247
-        return EED_Ticket_Selector::ticketSelector()->displayViewDetailsButton();
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * @deprecated
254
-     * @return string
255
-     * @throws \EE_Error
256
-     */
257
-    public static function display_ticket_selector_submit()
258
-    {
259
-        // todo add doing_it_wrong() notice during next major version
260
-        return EED_Ticket_Selector::ticketSelector()->displaySubmitButton();
261
-    }
262
-
263
-
264
-
265
-    /**
266
-     * @deprecated
267
-     * @param string $permalink_string
268
-     * @param int    $id
269
-     * @param string $new_title
270
-     * @param string $new_slug
271
-     * @return string
272
-     */
273
-    public static function iframe_code_button($permalink_string, $id, $new_title = '', $new_slug = '')
274
-    {
275
-        // todo add doing_it_wrong() notice during next major version
276
-        if (
277
-        	\EE_Registry::instance()->REQ->get('page') === 'espresso_events'
278
-        	&& \EE_Registry::instance()->REQ->get('action') === 'edit'
279
-        ) {
280
-            $iframe_embed_button = \EED_Ticket_Selector::getIframeEmbedButton();
281
-            $iframe_embed_button->addEventEditorIframeEmbedButton();
282
-        }
283
-        return '';
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * @deprecated
290
-     * @param int    $ID
291
-     * @param string $external_url
292
-     * @return string
293
-     */
294
-    public static function ticket_selector_form_open($ID = 0, $external_url = '')
295
-    {
296
-        // todo add doing_it_wrong() notice during next major version
297
-        return EED_Ticket_Selector::ticketSelector()->formOpen($ID, $external_url);
298
-    }
299
-
300
-
301
-
302
-    /**
303
-     * @deprecated
304
-     * @return string
305
-     */
306
-    public static function ticket_selector_form_close()
307
-    {
308
-        // todo add doing_it_wrong() notice during next major version
309
-        return EED_Ticket_Selector::ticketSelector()->formClose();
310
-    }
311
-
312
-
313
-
314
-    /**
315
-     * @deprecated
316
-     * @return string
317
-     */
318
-    public static function no_tkt_slctr_end_dv()
319
-    {
320
-        // todo add doing_it_wrong() notice during next major version
321
-        return EED_Ticket_Selector::ticketSelector()->ticketSelectorEndDiv();
322
-    }
323
-
324
-
325
-
326
-    /**
327
-     * @deprecated 4.9.13
328
-     * @return string
329
-     */
330
-    public static function tkt_slctr_end_dv()
331
-    {
332
-        return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
333
-    }
334
-
335
-
336
-
337
-    /**
338
-     * @deprecated
339
-     * @return string
340
-     */
341
-    public static function clear_tkt_slctr()
342
-    {
343
-        return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
344
-    }
345
-
346
-
347
-
348
-    /**
349
-     * @deprecated
350
-     */
351
-    public static function load_tckt_slctr_assets_admin()
352
-    {
353
-        // todo add doing_it_wrong() notice during next major version
354
-	    if (
355
-		    \EE_Registry::instance()->REQ->get( 'page' ) === 'espresso_events'
356
-		    && \EE_Registry::instance()->REQ->get( 'action' ) === 'edit'
357
-	    ) {
358
-		    $iframe_embed_button = \EED_Ticket_Selector::getIframeEmbedButton();
359
-            $iframe_embed_button->embedButtonAssets();
360
-        }
361
-    }
239
+	/**
240
+	 * @deprecated
241
+	 * @return string
242
+	 * @throws \EE_Error
243
+	 */
244
+	public static function display_view_details_btn()
245
+	{
246
+		// todo add doing_it_wrong() notice during next major version
247
+		return EED_Ticket_Selector::ticketSelector()->displayViewDetailsButton();
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * @deprecated
254
+	 * @return string
255
+	 * @throws \EE_Error
256
+	 */
257
+	public static function display_ticket_selector_submit()
258
+	{
259
+		// todo add doing_it_wrong() notice during next major version
260
+		return EED_Ticket_Selector::ticketSelector()->displaySubmitButton();
261
+	}
262
+
263
+
264
+
265
+	/**
266
+	 * @deprecated
267
+	 * @param string $permalink_string
268
+	 * @param int    $id
269
+	 * @param string $new_title
270
+	 * @param string $new_slug
271
+	 * @return string
272
+	 */
273
+	public static function iframe_code_button($permalink_string, $id, $new_title = '', $new_slug = '')
274
+	{
275
+		// todo add doing_it_wrong() notice during next major version
276
+		if (
277
+			\EE_Registry::instance()->REQ->get('page') === 'espresso_events'
278
+			&& \EE_Registry::instance()->REQ->get('action') === 'edit'
279
+		) {
280
+			$iframe_embed_button = \EED_Ticket_Selector::getIframeEmbedButton();
281
+			$iframe_embed_button->addEventEditorIframeEmbedButton();
282
+		}
283
+		return '';
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * @deprecated
290
+	 * @param int    $ID
291
+	 * @param string $external_url
292
+	 * @return string
293
+	 */
294
+	public static function ticket_selector_form_open($ID = 0, $external_url = '')
295
+	{
296
+		// todo add doing_it_wrong() notice during next major version
297
+		return EED_Ticket_Selector::ticketSelector()->formOpen($ID, $external_url);
298
+	}
299
+
300
+
301
+
302
+	/**
303
+	 * @deprecated
304
+	 * @return string
305
+	 */
306
+	public static function ticket_selector_form_close()
307
+	{
308
+		// todo add doing_it_wrong() notice during next major version
309
+		return EED_Ticket_Selector::ticketSelector()->formClose();
310
+	}
311
+
312
+
313
+
314
+	/**
315
+	 * @deprecated
316
+	 * @return string
317
+	 */
318
+	public static function no_tkt_slctr_end_dv()
319
+	{
320
+		// todo add doing_it_wrong() notice during next major version
321
+		return EED_Ticket_Selector::ticketSelector()->ticketSelectorEndDiv();
322
+	}
323
+
324
+
325
+
326
+	/**
327
+	 * @deprecated 4.9.13
328
+	 * @return string
329
+	 */
330
+	public static function tkt_slctr_end_dv()
331
+	{
332
+		return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
333
+	}
334
+
335
+
336
+
337
+	/**
338
+	 * @deprecated
339
+	 * @return string
340
+	 */
341
+	public static function clear_tkt_slctr()
342
+	{
343
+		return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
344
+	}
345
+
346
+
347
+
348
+	/**
349
+	 * @deprecated
350
+	 */
351
+	public static function load_tckt_slctr_assets_admin()
352
+	{
353
+		// todo add doing_it_wrong() notice during next major version
354
+		if (
355
+			\EE_Registry::instance()->REQ->get( 'page' ) === 'espresso_events'
356
+			&& \EE_Registry::instance()->REQ->get( 'action' ) === 'edit'
357
+		) {
358
+			$iframe_embed_button = \EED_Ticket_Selector::getIframeEmbedButton();
359
+			$iframe_embed_button->embedButtonAssets();
360
+		}
361
+	}
362 362
 
363 363
 
364 364
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -3,8 +3,8 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\modules\ticket_selector\TicketSelectorIframe;
4 4
 use EventEspresso\modules\ticket_selector\TicketSelectorIframeEmbedButton;
5 5
 
6
-if ( ! defined( 'EVENT_ESPRESSO_VERSION' ) ) {
7
-	exit( 'No direct script access allowed' );
6
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
7
+	exit('No direct script access allowed');
8 8
 }
9 9
 
10 10
 
@@ -38,15 +38,15 @@  discard block
 block discarded – undo
38 38
 	 * @return EED_Ticket_Selector
39 39
 	 */
40 40
 	public static function instance() {
41
-		return parent::get_instance( __CLASS__ );
41
+		return parent::get_instance(__CLASS__);
42 42
 	}
43 43
 
44 44
 
45 45
 
46
-	protected function set_config(){
47
-		$this->set_config_section( 'template_settings' );
48
-		$this->set_config_class( 'EE_Ticket_Selector_Config' );
49
-		$this->set_config_name( 'EED_Ticket_Selector' );
46
+	protected function set_config() {
47
+		$this->set_config_section('template_settings');
48
+		$this->set_config_class('EE_Ticket_Selector_Config');
49
+		$this->set_config_name('EED_Ticket_Selector');
50 50
 	}
51 51
 
52 52
 
@@ -59,12 +59,12 @@  discard block
 block discarded – undo
59 59
 	 */
60 60
 	public static function set_hooks() {
61 61
 		// routing
62
-		EE_Config::register_route( 'iframe', 'EED_Ticket_Selector', 'ticket_selector_iframe', 'ticket_selector' );
63
-		EE_Config::register_route( 'process_ticket_selections', 'EED_Ticket_Selector', 'process_ticket_selections' );
62
+		EE_Config::register_route('iframe', 'EED_Ticket_Selector', 'ticket_selector_iframe', 'ticket_selector');
63
+		EE_Config::register_route('process_ticket_selections', 'EED_Ticket_Selector', 'process_ticket_selections');
64 64
         EE_Config::register_route('cancel_ticket_selections', 'EED_Ticket_Selector', 'cancel_ticket_selections');
65
-        add_action( 'wp_loaded', array( 'EED_Ticket_Selector', 'set_definitions' ), 2 );
66
-		add_action( 'AHEE_event_details_header_bottom', array( 'EED_Ticket_Selector', 'display_ticket_selector' ), 10, 1 );
67
-		add_action( 'wp_enqueue_scripts', array( 'EED_Ticket_Selector', 'load_tckt_slctr_assets' ), 10 );
65
+        add_action('wp_loaded', array('EED_Ticket_Selector', 'set_definitions'), 2);
66
+		add_action('AHEE_event_details_header_bottom', array('EED_Ticket_Selector', 'display_ticket_selector'), 10, 1);
67
+		add_action('wp_enqueue_scripts', array('EED_Ticket_Selector', 'load_tckt_slctr_assets'), 10);
68 68
 	}
69 69
 
70 70
 
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
 		// to load assets for "espresso_events" page on the "edit" route (action)
81 81
 		add_action(
82 82
 			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__edit',
83
-			array( 'EED_Ticket_Selector', 'ticket_selector_iframe_embed_button' ),
83
+			array('EED_Ticket_Selector', 'ticket_selector_iframe_embed_button'),
84 84
 			10
85 85
 		);
86 86
     }
@@ -94,11 +94,11 @@  discard block
 block discarded – undo
94 94
 	 *  @return 	void
95 95
 	 */
96 96
 	public static function set_definitions() {
97
-		define( 'TICKET_SELECTOR_ASSETS_URL', plugin_dir_url( __FILE__ ) . 'assets' . DS );
98
-		define( 'TICKET_SELECTOR_TEMPLATES_PATH', str_replace( '\\', DS, plugin_dir_path( __FILE__ )) . 'templates' . DS );
97
+		define('TICKET_SELECTOR_ASSETS_URL', plugin_dir_url(__FILE__).'assets'.DS);
98
+		define('TICKET_SELECTOR_TEMPLATES_PATH', str_replace('\\', DS, plugin_dir_path(__FILE__)).'templates'.DS);
99 99
 
100 100
 		//if config is not set, initialize
101
-		if ( ! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config ) {
101
+		if ( ! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config) {
102 102
             \EED_Ticket_Selector::instance()->set_config();
103 103
             \EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector = \EED_Ticket_Selector::instance()->config();
104 104
 		}
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
 	 * 	@param	WP $WP
126 126
 	 * 	@return void
127 127
 	 */
128
-	public function run( $WP ) {}
128
+	public function run($WP) {}
129 129
 
130 130
 
131 131
 
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
 	 * @return \EventEspresso\modules\ticket_selector\TicketSelectorIframeEmbedButton
134 134
 	 */
135 135
 	public static function getIframeEmbedButton() {
136
-		if ( ! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton ) {
136
+		if ( ! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton) {
137 137
 			self::$iframe_embed_button = new TicketSelectorIframeEmbedButton();
138 138
 		}
139 139
 		return self::$iframe_embed_button;
@@ -177,8 +177,8 @@  discard block
 block discarded – undo
177 177
      * @return    string
178 178
      * @throws \EE_Error
179 179
      */
180
-	public static function display_ticket_selector( $event = NULL, $view_details = FALSE ) {
181
-		return EED_Ticket_Selector::ticketSelector()->display( $event, $view_details );
180
+	public static function display_ticket_selector($event = NULL, $view_details = FALSE) {
181
+		return EED_Ticket_Selector::ticketSelector()->display($event, $view_details);
182 182
 	}
183 183
 
184 184
 
@@ -218,14 +218,14 @@  discard block
 block discarded – undo
218 218
 	* 	@return 		void
219 219
 	*/
220 220
 	public static function load_tckt_slctr_assets() {
221
-		if ( apply_filters( 'FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', FALSE ) ) {
221
+		if (apply_filters('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', FALSE)) {
222 222
 			// add some style
223
-			wp_register_style('ticket_selector', TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css');
223
+			wp_register_style('ticket_selector', TICKET_SELECTOR_ASSETS_URL.'ticket_selector.css');
224 224
 			wp_enqueue_style('ticket_selector');
225 225
 			// make it dance
226
-			wp_register_script('ticket_selector', TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js', array('espresso_core'), '', TRUE);
226
+			wp_register_script('ticket_selector', TICKET_SELECTOR_ASSETS_URL.'ticket_selector.js', array('espresso_core'), '', TRUE);
227 227
 			wp_enqueue_script('ticket_selector');
228
-            require_once( EE_LIBRARIES.'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php');
228
+            require_once(EE_LIBRARIES.'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php');
229 229
             \EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
230 230
         }
231 231
 	}
@@ -352,8 +352,8 @@  discard block
 block discarded – undo
352 352
     {
353 353
         // todo add doing_it_wrong() notice during next major version
354 354
 	    if (
355
-		    \EE_Registry::instance()->REQ->get( 'page' ) === 'espresso_events'
356
-		    && \EE_Registry::instance()->REQ->get( 'action' ) === 'edit'
355
+		    \EE_Registry::instance()->REQ->get('page') === 'espresso_events'
356
+		    && \EE_Registry::instance()->REQ->get('action') === 'edit'
357 357
 	    ) {
358 358
 		    $iframe_embed_button = \EED_Ticket_Selector::getIframeEmbedButton();
359 359
             $iframe_embed_button->embedButtonAssets();
Please login to merge, or discard this patch.
modules/ticket_selector/ProcessTicketSelector.php 3 patches
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
     /**
33 33
      * cancelTicketSelections
34 34
      *
35
-     * @return        string
35
+     * @return        false|null
36 36
      */
37 37
     public function cancelTicketSelections()
38 38
     {
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
     /**
100 100
      * process_ticket_selections
101 101
      *
102
-     * @return array|bool
102
+     * @return boolean|null
103 103
      * @throws \EE_Error
104 104
      */
105 105
     public function processTicketSelections()
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
      * validate_post_data
274 274
      *
275 275
      * @param int $id
276
-     * @return array|FALSE
276
+     * @return string
277 277
      */
278 278
     private function validatePostData($id = 0)
279 279
     {
@@ -390,7 +390,7 @@  discard block
 block discarded – undo
390 390
      *
391 391
      * @param \EE_Ticket $ticket
392 392
      * @param int        $qty
393
-     * @return TRUE on success, FALSE on fail
393
+     * @return boolean on success, FALSE on fail
394 394
      * @throws \EE_Error
395 395
      */
396 396
     private function addTicketToCart(\EE_Ticket $ticket = null, $qty = 1)
Please login to merge, or discard this patch.
Indentation   +569 added lines, -569 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 namespace EventEspresso\modules\ticket_selector;
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
 
@@ -19,574 +19,574 @@  discard block
 block discarded – undo
19 19
 class ProcessTicketSelector
20 20
 {
21 21
 
22
-    /**
23
-     * array of datetimes and the spaces available for them
24
-     *
25
-     * @access private
26
-     * @var array
27
-     */
28
-    private static $_available_spaces = array();
29
-
30
-
31
-
32
-    /**
33
-     * cancelTicketSelections
34
-     *
35
-     * @return        string
36
-     */
37
-    public function cancelTicketSelections()
38
-    {
39
-        // check nonce
40
-        if ( ! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
41
-            return false;
42
-        }
43
-        \EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
44
-        if (\EE_Registry::instance()->REQ->is_set('event_id')) {
45
-            wp_safe_redirect(
46
-                \EEH_Event_View::event_link_url(
47
-                    \EE_Registry::instance()->REQ->get('event_id')
48
-                )
49
-            );
50
-        } else {
51
-            wp_safe_redirect(
52
-                site_url('/' . \EE_Registry::instance()->CFG->core->event_cpt_slug . '/')
53
-            );
54
-        }
55
-        exit();
56
-    }
57
-
58
-
59
-
60
-    /**
61
-     * processTicketSelectorNonce
62
-     *
63
-     * @param  string $nonce_name
64
-     * @param string  $id
65
-     * @return bool
66
-     */
67
-    private function processTicketSelectorNonce($nonce_name, $id = '')
68
-    {
69
-        $nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
70
-        if (
71
-            ! is_admin()
72
-            && (
73
-                ! \EE_Registry::instance()->REQ->is_set($nonce_name_with_id)
74
-                || ! wp_verify_nonce(
75
-                    \EE_Registry::instance()->REQ->get($nonce_name_with_id),
76
-                    $nonce_name
77
-                )
78
-            )
79
-        ) {
80
-            \EE_Error::add_error(
81
-                sprintf(
82
-                    __(
83
-                        'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
84
-                        'event_espresso'
85
-                    ),
86
-                    '<br/>'
87
-                ),
88
-                __FILE__,
89
-                __FUNCTION__,
90
-                __LINE__
91
-            );
92
-            return false;
93
-        }
94
-        return true;
95
-    }
96
-
97
-
98
-
99
-    /**
100
-     * process_ticket_selections
101
-     *
102
-     * @return array|bool
103
-     * @throws \EE_Error
104
-     */
105
-    public function processTicketSelections()
106
-    {
107
-        do_action('EED_Ticket_Selector__process_ticket_selections__before');
108
-        // do we have an event id?
109
-        if ( ! \EE_Registry::instance()->REQ->is_set('tkt-slctr-event-id')) {
110
-            // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
111
-            \EE_Error::add_error(
112
-                sprintf(
113
-                    __(
114
-                        'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
115
-                        'event_espresso'
116
-                    ),
117
-                    '<br/>'
118
-                ),
119
-                __FILE__,
120
-                __FUNCTION__,
121
-                __LINE__
122
-            );
123
-        }
124
-        //if event id is valid
125
-        $id = absint(\EE_Registry::instance()->REQ->get('tkt-slctr-event-id'));
126
-        // check nonce
127
-        if ( ! $this->processTicketSelectorNonce('process_ticket_selections', $id)) {
128
-            return false;
129
-        }
130
-        //		d( \EE_Registry::instance()->REQ );
131
-        self::$_available_spaces = array(
132
-            'tickets'   => array(),
133
-            'datetimes' => array(),
134
-        );
135
-        //we should really only have 1 registration in the works now (ie, no MER) so clear any previous items in the cart.
136
-        // When MER happens this will probably need to be tweaked, possibly wrapped in a conditional checking for some constant defined in MER etc.
137
-        \EE_Registry::instance()->load_core('Session');
138
-        // unless otherwise requested, clear the session
139
-        if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
140
-            \EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
141
-        }
142
-        //d( \EE_Registry::instance()->SSN );
143
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
144
-        // validate/sanitize data
145
-        $valid = $this->validatePostData($id);
146
-        //EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
147
-        //EEH_Debug_Tools::printr( $valid, '$valid', __FILE__, __LINE__ );
148
-        //EEH_Debug_Tools::printr( $valid[ 'total_tickets' ], 'total_tickets', __FILE__, __LINE__ );
149
-        //EEH_Debug_Tools::printr( $valid[ 'max_atndz' ], 'max_atndz', __FILE__, __LINE__ );
150
-        //check total tickets ordered vs max number of attendees that can register
151
-        if ($valid['total_tickets'] > $valid['max_atndz']) {
152
-            // ordering too many tickets !!!
153
-            $total_tickets_string = _n(
154
-                'You have attempted to purchase %s ticket.',
155
-                'You have attempted to purchase %s tickets.',
156
-                $valid['total_tickets'],
157
-                'event_espresso'
158
-            );
159
-            $limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
160
-            // dev only message
161
-            $max_atndz_string = _n(
162
-                'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
163
-                'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
164
-                $valid['max_atndz'],
165
-                'event_espresso'
166
-            );
167
-            $limit_error_2 = sprintf($max_atndz_string, $valid['max_atndz'], $valid['max_atndz']);
168
-            \EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
169
-        } else {
170
-            // all data appears to be valid
171
-            $tckts_slctd = false;
172
-            $tickets_added = 0;
173
-            $valid = apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data', $valid);
174
-            if ($valid['total_tickets'] > 0) {
175
-                // load cart
176
-                \EE_Registry::instance()->load_core('Cart');
177
-                // cycle thru the number of data rows sent from the event listing
178
-                for ($x = 0; $x < $valid['rows']; $x++) {
179
-                    // does this row actually contain a ticket quantity?
180
-                    if (isset($valid['qty'][$x]) && $valid['qty'][$x] > 0) {
181
-                        // YES we have a ticket quantity
182
-                        $tckts_slctd = true;
183
-                        //						d( $valid['ticket_obj'][$x] );
184
-                        if ($valid['ticket_obj'][$x] instanceof \EE_Ticket) {
185
-                            // then add ticket to cart
186
-                            $tickets_added += $this->addTicketToCart(
187
-                                $valid['ticket_obj'][$x],
188
-                                $valid['qty'][$x]
189
-                            );
190
-                            if (\EE_Error::has_error()) {
191
-                                break;
192
-                            }
193
-                        } else {
194
-                            // nothing added to cart retrieved
195
-                            \EE_Error::add_error(
196
-                                sprintf(
197
-                                    __(
198
-                                        'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
199
-                                        'event_espresso'
200
-                                    ),
201
-                                    '<br/>'
202
-                                ),
203
-                                __FILE__, __FUNCTION__, __LINE__
204
-                            );
205
-                        }
206
-                    }
207
-                }
208
-            }
209
-            do_action(
210
-                'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
211
-                \EE_Registry::instance()->CART,
212
-                $this
213
-            );
214
-            //d( \EE_Registry::instance()->CART );
215
-            //die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
216
-            if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tckts_slctd)) {
217
-                if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
218
-                    do_action(
219
-                        'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
220
-                        \EE_Registry::instance()->CART,
221
-                        $this
222
-                    );
223
-                    \EE_Registry::instance()->CART->recalculate_all_cart_totals();
224
-                    \EE_Registry::instance()->CART->save_cart(false);
225
-                    // exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
226
-                    // just return TRUE for registrations being made from admin
227
-                    if (is_admin()) {
228
-                        return true;
229
-                    }
230
-                    \EE_Error::get_notices(false, true);
231
-                    wp_safe_redirect(
232
-                        apply_filters(
233
-                            'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
234
-                            \EE_Registry::instance()->CFG->core->reg_page_url()
235
-                        )
236
-                    );
237
-                    exit();
238
-                } else {
239
-                    if ( ! \EE_Error::has_error() && ! \EE_Error::has_error(true, 'attention')) {
240
-                        // nothing added to cart
241
-                        \EE_Error::add_attention(__('No tickets were added for the event', 'event_espresso'),
242
-                            __FILE__, __FUNCTION__, __LINE__);
243
-                    }
244
-                }
245
-            } else {
246
-                // no ticket quantities were selected
247
-                \EE_Error::add_error(__('You need to select a ticket quantity before you can proceed.',
248
-                    'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
249
-            }
250
-        }
251
-        //die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
252
-        // at this point, just return if registration is being made from admin
253
-        if (is_admin()) {
254
-            return false;
255
-        }
256
-        if ($valid['return_url']) {
257
-            \EE_Error::get_notices(false, true);
258
-            wp_safe_redirect($valid['return_url']);
259
-            exit();
260
-        } elseif (isset($event_to_add['id'])) {
261
-            \EE_Error::get_notices(false, true);
262
-            wp_safe_redirect(get_permalink($event_to_add['id']));
263
-            exit();
264
-        } else {
265
-            echo \EE_Error::get_notices();
266
-        }
267
-        return false;
268
-    }
269
-
270
-
271
-
272
-    /**
273
-     * validate_post_data
274
-     *
275
-     * @param int $id
276
-     * @return array|FALSE
277
-     */
278
-    private function validatePostData($id = 0)
279
-    {
280
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
281
-        if ( ! $id) {
282
-            \EE_Error::add_error(
283
-                __('The event id provided was not valid.', 'event_espresso'),
284
-                __FILE__,
285
-                __FUNCTION__,
286
-                __LINE__
287
-            );
288
-            return false;
289
-        }
290
-        // start with an empty array()
291
-        $valid_data = array();
292
-        // grab valid id
293
-        $valid_data['id'] = $id;
294
-        // array of other form names
295
-        $inputs_to_clean = array(
296
-            'event_id'   => 'tkt-slctr-event-id',
297
-            'max_atndz'  => 'tkt-slctr-max-atndz-',
298
-            'rows'       => 'tkt-slctr-rows-',
299
-            'qty'        => 'tkt-slctr-qty-',
300
-            'ticket_id'  => 'tkt-slctr-ticket-id-',
301
-            'return_url' => 'tkt-slctr-return-url-',
302
-        );
303
-        // let's track the total number of tickets ordered.'
304
-        $valid_data['total_tickets'] = 0;
305
-        // cycle through $inputs_to_clean array
306
-        foreach ($inputs_to_clean as $what => $input_to_clean) {
307
-            // check for POST data
308
-            if (\EE_Registry::instance()->REQ->is_set($input_to_clean . $id)) {
309
-                // grab value
310
-                $input_value = \EE_Registry::instance()->REQ->get($input_to_clean . $id);
311
-                switch ($what) {
312
-                    // integers
313
-                    case 'event_id':
314
-                        $valid_data[$what] = absint($input_value);
315
-                        // get event via the event id we put in the form
316
-                        $valid_data['event'] = \EE_Registry::instance()
317
-                                                           ->load_model('Event')
318
-                                                           ->get_one_by_ID($valid_data['event_id']);
319
-                        break;
320
-                    case 'rows':
321
-                    case 'max_atndz':
322
-                        $valid_data[$what] = absint($input_value);
323
-                        break;
324
-                    // arrays of integers
325
-                    case 'qty':
326
-                        /** @var array $row_qty */
327
-                        $row_qty = $input_value;
328
-                        // if qty is coming from a radio button input, then we need to assemble an array of rows
329
-                        if ( ! is_array($row_qty)) {
330
-                            // get number of rows
331
-                            $rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-' . $id)
332
-                                ? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-' . $id))
333
-                                : 1;
334
-                            // explode ints by the dash
335
-                            $row_qty = explode('-', $row_qty);
336
-                            $row = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
337
-                            $qty = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
338
-                            $row_qty = array($row => $qty);
339
-                            for ($x = 1; $x <= $rows; $x++) {
340
-                                if ( ! isset($row_qty[$x])) {
341
-                                    $row_qty[$x] = 0;
342
-                                }
343
-                            }
344
-                        }
345
-                        ksort($row_qty);
346
-                        // cycle thru values
347
-                        foreach ($row_qty as $qty) {
348
-                            $qty = absint($qty);
349
-                            // sanitize as integers
350
-                            $valid_data[$what][] = $qty;
351
-                            $valid_data['total_tickets'] += $qty;
352
-                        }
353
-                        break;
354
-                    // array of integers
355
-                    case 'ticket_id':
356
-                        $value_array = array();
357
-                        // cycle thru values
358
-                        foreach ((array)$input_value as $key => $value) {
359
-                            // allow only numbers, letters,  spaces, commas and dashes
360
-                            $value_array[$key] = wp_strip_all_tags($value);
361
-                            // get ticket via the ticket id we put in the form
362
-                            $ticket_obj = \EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($value);
363
-                            $valid_data['ticket_obj'][$key] = $ticket_obj;
364
-                        }
365
-                        $valid_data[$what] = $value_array;
366
-                        break;
367
-                    case 'return_url' :
368
-                        // grab and sanitize return-url
369
-                        $input_value = esc_url_raw($input_value);
370
-                        // was the request coming from an iframe ? if so, then:
371
-                        if (strpos($input_value, 'event_list=iframe')) {
372
-                            // get anchor fragment
373
-                            $input_value = explode('#', $input_value);
374
-                            $input_value = end($input_value);
375
-                            // use event list url instead, but append anchor
376
-                            $input_value = \EEH_Event_View::event_archive_url() . '#' . $input_value;
377
-                        }
378
-                        $valid_data[$what] = $input_value;
379
-                        break;
380
-                }    // end switch $what
381
-            }
382
-        }    // end foreach $inputs_to_clean
383
-        return $valid_data;
384
-    }
385
-
386
-
387
-
388
-    /**
389
-     * adds a ticket to the cart
390
-     *
391
-     * @param \EE_Ticket $ticket
392
-     * @param int        $qty
393
-     * @return TRUE on success, FALSE on fail
394
-     * @throws \EE_Error
395
-     */
396
-    private function addTicketToCart(\EE_Ticket $ticket = null, $qty = 1)
397
-    {
398
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
399
-        // get the number of spaces left for this datetime ticket
400
-        $available_spaces = $this->ticketDatetimeAvailability($ticket);
401
-        // compare available spaces against the number of tickets being purchased
402
-        if ($available_spaces >= $qty) {
403
-            // allow addons to prevent a ticket from being added to cart
404
-            if (
405
-            ! apply_filters(
406
-                'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
407
-                true,
408
-                $ticket,
409
-                $qty,
410
-                $available_spaces
411
-            )
412
-            ) {
413
-                return false;
414
-            }
415
-            $qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
416
-            // add event to cart
417
-            if (\EE_Registry::instance()->CART->add_ticket_to_cart($ticket, $qty)) {
418
-                $this->recalculateTicketDatetimeAvailability($ticket, $qty);
419
-                return true;
420
-            }
421
-            return false;
422
-        }
423
-        // tickets can not be purchased but let's find the exact number left
424
-        // for the last ticket selected PRIOR to subtracting tickets
425
-        $available_spaces = $this->ticketDatetimeAvailability($ticket, true);
426
-        // greedy greedy greedy eh?
427
-        if ($available_spaces > 0) {
428
-            if (
429
-            apply_filters(
430
-                'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_display_availability_error',
431
-                true,
432
-                $ticket,
433
-                $qty,
434
-                $available_spaces
435
-            )
436
-            ) {
437
-                $this->displayAvailabilityError($available_spaces);
438
-            }
439
-        } else {
440
-            \EE_Error::add_error(
441
-                __(
442
-                    'We\'re sorry, but there are no available spaces left for this event at this particular date and time.',
443
-                    'event_espresso'
444
-                ),
445
-                __FILE__, __FUNCTION__, __LINE__
446
-            );
447
-        }
448
-        return false;
449
-    }
450
-
451
-
452
-
453
-    /**
454
-     * @param int $available_spaces
455
-     * @throws \EE_Error
456
-     */
457
-    private function displayAvailabilityError($available_spaces = 1)
458
-    {
459
-        // add error messaging - we're using the _n function that will generate
460
-        // the appropriate singular or plural message based on the number of $available_spaces
461
-        if (\EE_Registry::instance()->CART->all_ticket_quantity_count()) {
462
-            $msg = sprintf(
463
-                _n(
464
-                    'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
465
-                    'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
466
-                    $available_spaces,
467
-                    'event_espresso'
468
-                ),
469
-                $available_spaces,
470
-                '<br />'
471
-            );
472
-        } else {
473
-            $msg = sprintf(
474
-                _n(
475
-                    'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
476
-                    'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
477
-                    $available_spaces,
478
-                    'event_espresso'
479
-                ),
480
-                $available_spaces,
481
-                '<br />'
482
-            );
483
-        }
484
-        \EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
-    }
486
-
487
-
488
-
489
-    /**
490
-     * ticketDatetimeAvailability
491
-     * creates an array of tickets plus all of the datetimes available to each ticket
492
-     * and tracks the spaces remaining for each of those datetimes
493
-     *
494
-     * @param \EE_Ticket $ticket - selected ticket
495
-     * @param bool       $get_original_ticket_spaces
496
-     * @return int
497
-     * @throws \EE_Error
498
-     */
499
-    private function ticketDatetimeAvailability(\EE_Ticket $ticket, $get_original_ticket_spaces = false)
500
-    {
501
-        // if the $_available_spaces array has not been set up yet...
502
-        if ( ! isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
503
-            $this->setInitialTicketDatetimeAvailability($ticket);
504
-        }
505
-        $available_spaces = $ticket->qty() - $ticket->sold();
506
-        if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
507
-            // loop thru tickets, which will ALSO include individual ticket records AND a total
508
-            foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
509
-                // if we want the original datetime availability BEFORE we started subtracting tickets ?
510
-                if ($get_original_ticket_spaces) {
511
-                    // then grab the available spaces from the "tickets" array
512
-                    // and compare with the above to get the lowest number
513
-                    $available_spaces = min(
514
-                        $available_spaces,
515
-                        self::$_available_spaces['tickets'][$ticket->ID()][$DTD_ID]
516
-                    );
517
-                } else {
518
-                    // we want the updated ticket availability as stored in the "datetimes" array
519
-                    $available_spaces = min($available_spaces, self::$_available_spaces['datetimes'][$DTD_ID]);
520
-                }
521
-            }
522
-        }
523
-        return $available_spaces;
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * @param \EE_Ticket $ticket
530
-     * @return void
531
-     * @throws \EE_Error
532
-     */
533
-    private function setInitialTicketDatetimeAvailability(\EE_Ticket $ticket)
534
-    {
535
-        // first, get all of the datetimes that are available to this ticket
536
-        $datetimes = $ticket->get_many_related(
537
-            'Datetime',
538
-            array(
539
-                array(
540
-                    'DTT_EVT_end' => array(
541
-                        '>=',
542
-                        \EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
543
-                    ),
544
-                ),
545
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
546
-            )
547
-        );
548
-        if ( ! empty($datetimes)) {
549
-            // now loop thru all of the datetimes
550
-            foreach ($datetimes as $datetime) {
551
-                if ($datetime instanceof \EE_Datetime) {
552
-                    // the number of spaces available for the datetime without considering individual ticket quantities
553
-                    $spaces_remaining = $datetime->spaces_remaining();
554
-                    // save the total available spaces ( the lesser of the ticket qty minus the number of tickets sold
555
-                    // or the datetime spaces remaining) to this ticket using the datetime ID as the key
556
-                    self::$_available_spaces['tickets'][$ticket->ID()][$datetime->ID()] = min(
557
-                        $ticket->qty() - $ticket->sold(),
558
-                        $spaces_remaining
559
-                    );
560
-                    // if the remaining spaces for this datetime is already set,
561
-                    // then compare that against the datetime spaces remaining, and take the lowest number,
562
-                    // else just take the datetime spaces remaining, and assign to the datetimes array
563
-                    self::$_available_spaces['datetimes'][$datetime->ID()] = isset(
564
-                        self::$_available_spaces['datetimes'][$datetime->ID()]
565
-                    )
566
-                        ? min(self::$_available_spaces['datetimes'][$datetime->ID()], $spaces_remaining)
567
-                        : $spaces_remaining;
568
-                }
569
-            }
570
-        }
571
-    }
572
-
573
-
574
-
575
-    /**
576
-     * @param    \EE_Ticket $ticket
577
-     * @param    int        $qty
578
-     * @return    void
579
-     */
580
-    private function recalculateTicketDatetimeAvailability(\EE_Ticket $ticket, $qty = 0)
581
-    {
582
-        if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
583
-            // loop thru tickets, which will ALSO include individual ticket records AND a total
584
-            foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
585
-                // subtract the qty of selected tickets from each datetime's available spaces this ticket has access to,
586
-                self::$_available_spaces['datetimes'][$DTD_ID] -= $qty;
587
-            }
588
-        }
589
-    }
22
+	/**
23
+	 * array of datetimes and the spaces available for them
24
+	 *
25
+	 * @access private
26
+	 * @var array
27
+	 */
28
+	private static $_available_spaces = array();
29
+
30
+
31
+
32
+	/**
33
+	 * cancelTicketSelections
34
+	 *
35
+	 * @return        string
36
+	 */
37
+	public function cancelTicketSelections()
38
+	{
39
+		// check nonce
40
+		if ( ! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
41
+			return false;
42
+		}
43
+		\EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
44
+		if (\EE_Registry::instance()->REQ->is_set('event_id')) {
45
+			wp_safe_redirect(
46
+				\EEH_Event_View::event_link_url(
47
+					\EE_Registry::instance()->REQ->get('event_id')
48
+				)
49
+			);
50
+		} else {
51
+			wp_safe_redirect(
52
+				site_url('/' . \EE_Registry::instance()->CFG->core->event_cpt_slug . '/')
53
+			);
54
+		}
55
+		exit();
56
+	}
57
+
58
+
59
+
60
+	/**
61
+	 * processTicketSelectorNonce
62
+	 *
63
+	 * @param  string $nonce_name
64
+	 * @param string  $id
65
+	 * @return bool
66
+	 */
67
+	private function processTicketSelectorNonce($nonce_name, $id = '')
68
+	{
69
+		$nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
70
+		if (
71
+			! is_admin()
72
+			&& (
73
+				! \EE_Registry::instance()->REQ->is_set($nonce_name_with_id)
74
+				|| ! wp_verify_nonce(
75
+					\EE_Registry::instance()->REQ->get($nonce_name_with_id),
76
+					$nonce_name
77
+				)
78
+			)
79
+		) {
80
+			\EE_Error::add_error(
81
+				sprintf(
82
+					__(
83
+						'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
84
+						'event_espresso'
85
+					),
86
+					'<br/>'
87
+				),
88
+				__FILE__,
89
+				__FUNCTION__,
90
+				__LINE__
91
+			);
92
+			return false;
93
+		}
94
+		return true;
95
+	}
96
+
97
+
98
+
99
+	/**
100
+	 * process_ticket_selections
101
+	 *
102
+	 * @return array|bool
103
+	 * @throws \EE_Error
104
+	 */
105
+	public function processTicketSelections()
106
+	{
107
+		do_action('EED_Ticket_Selector__process_ticket_selections__before');
108
+		// do we have an event id?
109
+		if ( ! \EE_Registry::instance()->REQ->is_set('tkt-slctr-event-id')) {
110
+			// $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
111
+			\EE_Error::add_error(
112
+				sprintf(
113
+					__(
114
+						'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
115
+						'event_espresso'
116
+					),
117
+					'<br/>'
118
+				),
119
+				__FILE__,
120
+				__FUNCTION__,
121
+				__LINE__
122
+			);
123
+		}
124
+		//if event id is valid
125
+		$id = absint(\EE_Registry::instance()->REQ->get('tkt-slctr-event-id'));
126
+		// check nonce
127
+		if ( ! $this->processTicketSelectorNonce('process_ticket_selections', $id)) {
128
+			return false;
129
+		}
130
+		//		d( \EE_Registry::instance()->REQ );
131
+		self::$_available_spaces = array(
132
+			'tickets'   => array(),
133
+			'datetimes' => array(),
134
+		);
135
+		//we should really only have 1 registration in the works now (ie, no MER) so clear any previous items in the cart.
136
+		// When MER happens this will probably need to be tweaked, possibly wrapped in a conditional checking for some constant defined in MER etc.
137
+		\EE_Registry::instance()->load_core('Session');
138
+		// unless otherwise requested, clear the session
139
+		if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
140
+			\EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
141
+		}
142
+		//d( \EE_Registry::instance()->SSN );
143
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
144
+		// validate/sanitize data
145
+		$valid = $this->validatePostData($id);
146
+		//EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
147
+		//EEH_Debug_Tools::printr( $valid, '$valid', __FILE__, __LINE__ );
148
+		//EEH_Debug_Tools::printr( $valid[ 'total_tickets' ], 'total_tickets', __FILE__, __LINE__ );
149
+		//EEH_Debug_Tools::printr( $valid[ 'max_atndz' ], 'max_atndz', __FILE__, __LINE__ );
150
+		//check total tickets ordered vs max number of attendees that can register
151
+		if ($valid['total_tickets'] > $valid['max_atndz']) {
152
+			// ordering too many tickets !!!
153
+			$total_tickets_string = _n(
154
+				'You have attempted to purchase %s ticket.',
155
+				'You have attempted to purchase %s tickets.',
156
+				$valid['total_tickets'],
157
+				'event_espresso'
158
+			);
159
+			$limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
160
+			// dev only message
161
+			$max_atndz_string = _n(
162
+				'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
163
+				'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
164
+				$valid['max_atndz'],
165
+				'event_espresso'
166
+			);
167
+			$limit_error_2 = sprintf($max_atndz_string, $valid['max_atndz'], $valid['max_atndz']);
168
+			\EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
169
+		} else {
170
+			// all data appears to be valid
171
+			$tckts_slctd = false;
172
+			$tickets_added = 0;
173
+			$valid = apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data', $valid);
174
+			if ($valid['total_tickets'] > 0) {
175
+				// load cart
176
+				\EE_Registry::instance()->load_core('Cart');
177
+				// cycle thru the number of data rows sent from the event listing
178
+				for ($x = 0; $x < $valid['rows']; $x++) {
179
+					// does this row actually contain a ticket quantity?
180
+					if (isset($valid['qty'][$x]) && $valid['qty'][$x] > 0) {
181
+						// YES we have a ticket quantity
182
+						$tckts_slctd = true;
183
+						//						d( $valid['ticket_obj'][$x] );
184
+						if ($valid['ticket_obj'][$x] instanceof \EE_Ticket) {
185
+							// then add ticket to cart
186
+							$tickets_added += $this->addTicketToCart(
187
+								$valid['ticket_obj'][$x],
188
+								$valid['qty'][$x]
189
+							);
190
+							if (\EE_Error::has_error()) {
191
+								break;
192
+							}
193
+						} else {
194
+							// nothing added to cart retrieved
195
+							\EE_Error::add_error(
196
+								sprintf(
197
+									__(
198
+										'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
199
+										'event_espresso'
200
+									),
201
+									'<br/>'
202
+								),
203
+								__FILE__, __FUNCTION__, __LINE__
204
+							);
205
+						}
206
+					}
207
+				}
208
+			}
209
+			do_action(
210
+				'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
211
+				\EE_Registry::instance()->CART,
212
+				$this
213
+			);
214
+			//d( \EE_Registry::instance()->CART );
215
+			//die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
216
+			if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tckts_slctd)) {
217
+				if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
218
+					do_action(
219
+						'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
220
+						\EE_Registry::instance()->CART,
221
+						$this
222
+					);
223
+					\EE_Registry::instance()->CART->recalculate_all_cart_totals();
224
+					\EE_Registry::instance()->CART->save_cart(false);
225
+					// exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
226
+					// just return TRUE for registrations being made from admin
227
+					if (is_admin()) {
228
+						return true;
229
+					}
230
+					\EE_Error::get_notices(false, true);
231
+					wp_safe_redirect(
232
+						apply_filters(
233
+							'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
234
+							\EE_Registry::instance()->CFG->core->reg_page_url()
235
+						)
236
+					);
237
+					exit();
238
+				} else {
239
+					if ( ! \EE_Error::has_error() && ! \EE_Error::has_error(true, 'attention')) {
240
+						// nothing added to cart
241
+						\EE_Error::add_attention(__('No tickets were added for the event', 'event_espresso'),
242
+							__FILE__, __FUNCTION__, __LINE__);
243
+					}
244
+				}
245
+			} else {
246
+				// no ticket quantities were selected
247
+				\EE_Error::add_error(__('You need to select a ticket quantity before you can proceed.',
248
+					'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
249
+			}
250
+		}
251
+		//die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
252
+		// at this point, just return if registration is being made from admin
253
+		if (is_admin()) {
254
+			return false;
255
+		}
256
+		if ($valid['return_url']) {
257
+			\EE_Error::get_notices(false, true);
258
+			wp_safe_redirect($valid['return_url']);
259
+			exit();
260
+		} elseif (isset($event_to_add['id'])) {
261
+			\EE_Error::get_notices(false, true);
262
+			wp_safe_redirect(get_permalink($event_to_add['id']));
263
+			exit();
264
+		} else {
265
+			echo \EE_Error::get_notices();
266
+		}
267
+		return false;
268
+	}
269
+
270
+
271
+
272
+	/**
273
+	 * validate_post_data
274
+	 *
275
+	 * @param int $id
276
+	 * @return array|FALSE
277
+	 */
278
+	private function validatePostData($id = 0)
279
+	{
280
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
281
+		if ( ! $id) {
282
+			\EE_Error::add_error(
283
+				__('The event id provided was not valid.', 'event_espresso'),
284
+				__FILE__,
285
+				__FUNCTION__,
286
+				__LINE__
287
+			);
288
+			return false;
289
+		}
290
+		// start with an empty array()
291
+		$valid_data = array();
292
+		// grab valid id
293
+		$valid_data['id'] = $id;
294
+		// array of other form names
295
+		$inputs_to_clean = array(
296
+			'event_id'   => 'tkt-slctr-event-id',
297
+			'max_atndz'  => 'tkt-slctr-max-atndz-',
298
+			'rows'       => 'tkt-slctr-rows-',
299
+			'qty'        => 'tkt-slctr-qty-',
300
+			'ticket_id'  => 'tkt-slctr-ticket-id-',
301
+			'return_url' => 'tkt-slctr-return-url-',
302
+		);
303
+		// let's track the total number of tickets ordered.'
304
+		$valid_data['total_tickets'] = 0;
305
+		// cycle through $inputs_to_clean array
306
+		foreach ($inputs_to_clean as $what => $input_to_clean) {
307
+			// check for POST data
308
+			if (\EE_Registry::instance()->REQ->is_set($input_to_clean . $id)) {
309
+				// grab value
310
+				$input_value = \EE_Registry::instance()->REQ->get($input_to_clean . $id);
311
+				switch ($what) {
312
+					// integers
313
+					case 'event_id':
314
+						$valid_data[$what] = absint($input_value);
315
+						// get event via the event id we put in the form
316
+						$valid_data['event'] = \EE_Registry::instance()
317
+														   ->load_model('Event')
318
+														   ->get_one_by_ID($valid_data['event_id']);
319
+						break;
320
+					case 'rows':
321
+					case 'max_atndz':
322
+						$valid_data[$what] = absint($input_value);
323
+						break;
324
+					// arrays of integers
325
+					case 'qty':
326
+						/** @var array $row_qty */
327
+						$row_qty = $input_value;
328
+						// if qty is coming from a radio button input, then we need to assemble an array of rows
329
+						if ( ! is_array($row_qty)) {
330
+							// get number of rows
331
+							$rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-' . $id)
332
+								? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-' . $id))
333
+								: 1;
334
+							// explode ints by the dash
335
+							$row_qty = explode('-', $row_qty);
336
+							$row = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
337
+							$qty = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
338
+							$row_qty = array($row => $qty);
339
+							for ($x = 1; $x <= $rows; $x++) {
340
+								if ( ! isset($row_qty[$x])) {
341
+									$row_qty[$x] = 0;
342
+								}
343
+							}
344
+						}
345
+						ksort($row_qty);
346
+						// cycle thru values
347
+						foreach ($row_qty as $qty) {
348
+							$qty = absint($qty);
349
+							// sanitize as integers
350
+							$valid_data[$what][] = $qty;
351
+							$valid_data['total_tickets'] += $qty;
352
+						}
353
+						break;
354
+					// array of integers
355
+					case 'ticket_id':
356
+						$value_array = array();
357
+						// cycle thru values
358
+						foreach ((array)$input_value as $key => $value) {
359
+							// allow only numbers, letters,  spaces, commas and dashes
360
+							$value_array[$key] = wp_strip_all_tags($value);
361
+							// get ticket via the ticket id we put in the form
362
+							$ticket_obj = \EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($value);
363
+							$valid_data['ticket_obj'][$key] = $ticket_obj;
364
+						}
365
+						$valid_data[$what] = $value_array;
366
+						break;
367
+					case 'return_url' :
368
+						// grab and sanitize return-url
369
+						$input_value = esc_url_raw($input_value);
370
+						// was the request coming from an iframe ? if so, then:
371
+						if (strpos($input_value, 'event_list=iframe')) {
372
+							// get anchor fragment
373
+							$input_value = explode('#', $input_value);
374
+							$input_value = end($input_value);
375
+							// use event list url instead, but append anchor
376
+							$input_value = \EEH_Event_View::event_archive_url() . '#' . $input_value;
377
+						}
378
+						$valid_data[$what] = $input_value;
379
+						break;
380
+				}    // end switch $what
381
+			}
382
+		}    // end foreach $inputs_to_clean
383
+		return $valid_data;
384
+	}
385
+
386
+
387
+
388
+	/**
389
+	 * adds a ticket to the cart
390
+	 *
391
+	 * @param \EE_Ticket $ticket
392
+	 * @param int        $qty
393
+	 * @return TRUE on success, FALSE on fail
394
+	 * @throws \EE_Error
395
+	 */
396
+	private function addTicketToCart(\EE_Ticket $ticket = null, $qty = 1)
397
+	{
398
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
399
+		// get the number of spaces left for this datetime ticket
400
+		$available_spaces = $this->ticketDatetimeAvailability($ticket);
401
+		// compare available spaces against the number of tickets being purchased
402
+		if ($available_spaces >= $qty) {
403
+			// allow addons to prevent a ticket from being added to cart
404
+			if (
405
+			! apply_filters(
406
+				'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
407
+				true,
408
+				$ticket,
409
+				$qty,
410
+				$available_spaces
411
+			)
412
+			) {
413
+				return false;
414
+			}
415
+			$qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
416
+			// add event to cart
417
+			if (\EE_Registry::instance()->CART->add_ticket_to_cart($ticket, $qty)) {
418
+				$this->recalculateTicketDatetimeAvailability($ticket, $qty);
419
+				return true;
420
+			}
421
+			return false;
422
+		}
423
+		// tickets can not be purchased but let's find the exact number left
424
+		// for the last ticket selected PRIOR to subtracting tickets
425
+		$available_spaces = $this->ticketDatetimeAvailability($ticket, true);
426
+		// greedy greedy greedy eh?
427
+		if ($available_spaces > 0) {
428
+			if (
429
+			apply_filters(
430
+				'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_display_availability_error',
431
+				true,
432
+				$ticket,
433
+				$qty,
434
+				$available_spaces
435
+			)
436
+			) {
437
+				$this->displayAvailabilityError($available_spaces);
438
+			}
439
+		} else {
440
+			\EE_Error::add_error(
441
+				__(
442
+					'We\'re sorry, but there are no available spaces left for this event at this particular date and time.',
443
+					'event_espresso'
444
+				),
445
+				__FILE__, __FUNCTION__, __LINE__
446
+			);
447
+		}
448
+		return false;
449
+	}
450
+
451
+
452
+
453
+	/**
454
+	 * @param int $available_spaces
455
+	 * @throws \EE_Error
456
+	 */
457
+	private function displayAvailabilityError($available_spaces = 1)
458
+	{
459
+		// add error messaging - we're using the _n function that will generate
460
+		// the appropriate singular or plural message based on the number of $available_spaces
461
+		if (\EE_Registry::instance()->CART->all_ticket_quantity_count()) {
462
+			$msg = sprintf(
463
+				_n(
464
+					'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
465
+					'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
466
+					$available_spaces,
467
+					'event_espresso'
468
+				),
469
+				$available_spaces,
470
+				'<br />'
471
+			);
472
+		} else {
473
+			$msg = sprintf(
474
+				_n(
475
+					'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
476
+					'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
477
+					$available_spaces,
478
+					'event_espresso'
479
+				),
480
+				$available_spaces,
481
+				'<br />'
482
+			);
483
+		}
484
+		\EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
+	}
486
+
487
+
488
+
489
+	/**
490
+	 * ticketDatetimeAvailability
491
+	 * creates an array of tickets plus all of the datetimes available to each ticket
492
+	 * and tracks the spaces remaining for each of those datetimes
493
+	 *
494
+	 * @param \EE_Ticket $ticket - selected ticket
495
+	 * @param bool       $get_original_ticket_spaces
496
+	 * @return int
497
+	 * @throws \EE_Error
498
+	 */
499
+	private function ticketDatetimeAvailability(\EE_Ticket $ticket, $get_original_ticket_spaces = false)
500
+	{
501
+		// if the $_available_spaces array has not been set up yet...
502
+		if ( ! isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
503
+			$this->setInitialTicketDatetimeAvailability($ticket);
504
+		}
505
+		$available_spaces = $ticket->qty() - $ticket->sold();
506
+		if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
507
+			// loop thru tickets, which will ALSO include individual ticket records AND a total
508
+			foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
509
+				// if we want the original datetime availability BEFORE we started subtracting tickets ?
510
+				if ($get_original_ticket_spaces) {
511
+					// then grab the available spaces from the "tickets" array
512
+					// and compare with the above to get the lowest number
513
+					$available_spaces = min(
514
+						$available_spaces,
515
+						self::$_available_spaces['tickets'][$ticket->ID()][$DTD_ID]
516
+					);
517
+				} else {
518
+					// we want the updated ticket availability as stored in the "datetimes" array
519
+					$available_spaces = min($available_spaces, self::$_available_spaces['datetimes'][$DTD_ID]);
520
+				}
521
+			}
522
+		}
523
+		return $available_spaces;
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * @param \EE_Ticket $ticket
530
+	 * @return void
531
+	 * @throws \EE_Error
532
+	 */
533
+	private function setInitialTicketDatetimeAvailability(\EE_Ticket $ticket)
534
+	{
535
+		// first, get all of the datetimes that are available to this ticket
536
+		$datetimes = $ticket->get_many_related(
537
+			'Datetime',
538
+			array(
539
+				array(
540
+					'DTT_EVT_end' => array(
541
+						'>=',
542
+						\EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
543
+					),
544
+				),
545
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
546
+			)
547
+		);
548
+		if ( ! empty($datetimes)) {
549
+			// now loop thru all of the datetimes
550
+			foreach ($datetimes as $datetime) {
551
+				if ($datetime instanceof \EE_Datetime) {
552
+					// the number of spaces available for the datetime without considering individual ticket quantities
553
+					$spaces_remaining = $datetime->spaces_remaining();
554
+					// save the total available spaces ( the lesser of the ticket qty minus the number of tickets sold
555
+					// or the datetime spaces remaining) to this ticket using the datetime ID as the key
556
+					self::$_available_spaces['tickets'][$ticket->ID()][$datetime->ID()] = min(
557
+						$ticket->qty() - $ticket->sold(),
558
+						$spaces_remaining
559
+					);
560
+					// if the remaining spaces for this datetime is already set,
561
+					// then compare that against the datetime spaces remaining, and take the lowest number,
562
+					// else just take the datetime spaces remaining, and assign to the datetimes array
563
+					self::$_available_spaces['datetimes'][$datetime->ID()] = isset(
564
+						self::$_available_spaces['datetimes'][$datetime->ID()]
565
+					)
566
+						? min(self::$_available_spaces['datetimes'][$datetime->ID()], $spaces_remaining)
567
+						: $spaces_remaining;
568
+				}
569
+			}
570
+		}
571
+	}
572
+
573
+
574
+
575
+	/**
576
+	 * @param    \EE_Ticket $ticket
577
+	 * @param    int        $qty
578
+	 * @return    void
579
+	 */
580
+	private function recalculateTicketDatetimeAvailability(\EE_Ticket $ticket, $qty = 0)
581
+	{
582
+		if (isset(self::$_available_spaces['tickets'][$ticket->ID()])) {
583
+			// loop thru tickets, which will ALSO include individual ticket records AND a total
584
+			foreach (self::$_available_spaces['tickets'][$ticket->ID()] as $DTD_ID => $spaces) {
585
+				// subtract the qty of selected tickets from each datetime's available spaces this ticket has access to,
586
+				self::$_available_spaces['datetimes'][$DTD_ID] -= $qty;
587
+			}
588
+		}
589
+	}
590 590
 
591 591
 
592 592
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
             );
50 50
         } else {
51 51
             wp_safe_redirect(
52
-                site_url('/' . \EE_Registry::instance()->CFG->core->event_cpt_slug . '/')
52
+                site_url('/'.\EE_Registry::instance()->CFG->core->event_cpt_slug.'/')
53 53
             );
54 54
         }
55 55
         exit();
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
                 'event_espresso'
166 166
             );
167 167
             $limit_error_2 = sprintf($max_atndz_string, $valid['max_atndz'], $valid['max_atndz']);
168
-            \EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
168
+            \EE_Error::add_error($limit_error_1.'<br/>'.$limit_error_2, __FILE__, __FUNCTION__, __LINE__);
169 169
         } else {
170 170
             // all data appears to be valid
171 171
             $tckts_slctd = false;
@@ -305,9 +305,9 @@  discard block
 block discarded – undo
305 305
         // cycle through $inputs_to_clean array
306 306
         foreach ($inputs_to_clean as $what => $input_to_clean) {
307 307
             // check for POST data
308
-            if (\EE_Registry::instance()->REQ->is_set($input_to_clean . $id)) {
308
+            if (\EE_Registry::instance()->REQ->is_set($input_to_clean.$id)) {
309 309
                 // grab value
310
-                $input_value = \EE_Registry::instance()->REQ->get($input_to_clean . $id);
310
+                $input_value = \EE_Registry::instance()->REQ->get($input_to_clean.$id);
311 311
                 switch ($what) {
312 312
                     // integers
313 313
                     case 'event_id':
@@ -328,8 +328,8 @@  discard block
 block discarded – undo
328 328
                         // if qty is coming from a radio button input, then we need to assemble an array of rows
329 329
                         if ( ! is_array($row_qty)) {
330 330
                             // get number of rows
331
-                            $rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-' . $id)
332
-                                ? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-' . $id))
331
+                            $rows = \EE_Registry::instance()->REQ->is_set('tkt-slctr-rows-'.$id)
332
+                                ? absint(\EE_Registry::instance()->REQ->get('tkt-slctr-rows-'.$id))
333 333
                                 : 1;
334 334
                             // explode ints by the dash
335 335
                             $row_qty = explode('-', $row_qty);
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
                     case 'ticket_id':
356 356
                         $value_array = array();
357 357
                         // cycle thru values
358
-                        foreach ((array)$input_value as $key => $value) {
358
+                        foreach ((array) $input_value as $key => $value) {
359 359
                             // allow only numbers, letters,  spaces, commas and dashes
360 360
                             $value_array[$key] = wp_strip_all_tags($value);
361 361
                             // get ticket via the ticket id we put in the form
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
                             $input_value = explode('#', $input_value);
374 374
                             $input_value = end($input_value);
375 375
                             // use event list url instead, but append anchor
376
-                            $input_value = \EEH_Event_View::event_archive_url() . '#' . $input_value;
376
+                            $input_value = \EEH_Event_View::event_archive_url().'#'.$input_value;
377 377
                         }
378 378
                         $valid_data[$what] = $input_value;
379 379
                         break;
Please login to merge, or discard this patch.