Completed
Branch FET-10416-autoload-b4-bootstra... (0e880d)
by
unknown
104:12 queued 92:13
created
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 1 patch
Indentation   +1260 added lines, -1260 removed lines patch added patch discarded remove patch
@@ -14,1264 +14,1264 @@
 block discarded – undo
14 14
 {
15 15
 
16 16
 
17
-    /**
18
-     * Extend_Events_Admin_Page constructor.
19
-     *
20
-     * @param bool $routing
21
-     */
22
-    public function __construct($routing = true)
23
-    {
24
-        parent::__construct($routing);
25
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
27
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
28
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
29
-        }
30
-    }
31
-
32
-
33
-    /**
34
-     * Sets routes.
35
-     */
36
-    protected function _extend_page_config()
37
-    {
38
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
39
-        //is there a evt_id in the request?
40
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
41
-            ? $this->_req_data['EVT_ID']
42
-            : 0;
43
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
44
-        //tkt_id?
45
-        $tkt_id             = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
46
-            ? $this->_req_data['TKT_ID']
47
-            : 0;
48
-        $new_page_routes    = array(
49
-            'duplicate_event'          => array(
50
-                'func'       => '_duplicate_event',
51
-                'capability' => 'ee_edit_event',
52
-                'obj_id'     => $evt_id,
53
-                'noheader'   => true,
54
-            ),
55
-            'ticket_list_table'        => array(
56
-                'func'       => '_tickets_overview_list_table',
57
-                'capability' => 'ee_read_default_tickets',
58
-            ),
59
-            'trash_ticket'             => array(
60
-                'func'       => '_trash_or_restore_ticket',
61
-                'capability' => 'ee_delete_default_ticket',
62
-                'obj_id'     => $tkt_id,
63
-                'noheader'   => true,
64
-                'args'       => array('trash' => true),
65
-            ),
66
-            'trash_tickets'            => array(
67
-                'func'       => '_trash_or_restore_ticket',
68
-                'capability' => 'ee_delete_default_tickets',
69
-                'noheader'   => true,
70
-                'args'       => array('trash' => true),
71
-            ),
72
-            'restore_ticket'           => array(
73
-                'func'       => '_trash_or_restore_ticket',
74
-                'capability' => 'ee_delete_default_ticket',
75
-                'obj_id'     => $tkt_id,
76
-                'noheader'   => true,
77
-            ),
78
-            'restore_tickets'          => array(
79
-                'func'       => '_trash_or_restore_ticket',
80
-                'capability' => 'ee_delete_default_tickets',
81
-                'noheader'   => true,
82
-            ),
83
-            'delete_ticket'            => array(
84
-                'func'       => '_delete_ticket',
85
-                'capability' => 'ee_delete_default_ticket',
86
-                'obj_id'     => $tkt_id,
87
-                'noheader'   => true,
88
-            ),
89
-            'delete_tickets'           => array(
90
-                'func'       => '_delete_ticket',
91
-                'capability' => 'ee_delete_default_tickets',
92
-                'noheader'   => true,
93
-            ),
94
-            'import_page'              => array(
95
-                'func'       => '_import_page',
96
-                'capability' => 'import',
97
-            ),
98
-            'import'                   => array(
99
-                'func'       => '_import_events',
100
-                'capability' => 'import',
101
-                'noheader'   => true,
102
-            ),
103
-            'import_events'            => array(
104
-                'func'       => '_import_events',
105
-                'capability' => 'import',
106
-                'noheader'   => true,
107
-            ),
108
-            'export_events'            => array(
109
-                'func'       => '_events_export',
110
-                'capability' => 'export',
111
-                'noheader'   => true,
112
-            ),
113
-            'export_categories'        => array(
114
-                'func'       => '_categories_export',
115
-                'capability' => 'export',
116
-                'noheader'   => true,
117
-            ),
118
-            'sample_export_file'       => array(
119
-                'func'       => '_sample_export_file',
120
-                'capability' => 'export',
121
-                'noheader'   => true,
122
-            ),
123
-            'update_template_settings' => array(
124
-                'func'       => '_update_template_settings',
125
-                'capability' => 'manage_options',
126
-                'noheader'   => true,
127
-            ),
128
-        );
129
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
130
-        //partial route/config override
131
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
132
-        $this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
133
-        $this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
134
-        $this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
135
-        $this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
136
-        $this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
137
-        //add tickets tab but only if there are more than one default ticket!
138
-        $tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
139
-            array(array('TKT_is_default' => 1)),
140
-            'TKT_ID',
141
-            true
142
-        );
143
-        if ($tkt_count > 1) {
144
-            $new_page_config = array(
145
-                'ticket_list_table' => array(
146
-                    'nav'           => array(
147
-                        'label' => esc_html__('Default Tickets', 'event_espresso'),
148
-                        'order' => 60,
149
-                    ),
150
-                    'list_table'    => 'Tickets_List_Table',
151
-                    'require_nonce' => false,
152
-                ),
153
-            );
154
-        }
155
-        //template settings
156
-        $new_page_config['template_settings'] = array(
157
-            'nav'           => array(
158
-                'label' => esc_html__('Templates', 'event_espresso'),
159
-                'order' => 30,
160
-            ),
161
-            'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
162
-            'help_tabs'     => array(
163
-                'general_settings_templates_help_tab' => array(
164
-                    'title'    => esc_html__('Templates', 'event_espresso'),
165
-                    'filename' => 'general_settings_templates',
166
-                ),
167
-            ),
168
-            'help_tour'     => array('Templates_Help_Tour'),
169
-            'require_nonce' => false,
170
-        );
171
-        $this->_page_config                   = array_merge($this->_page_config, $new_page_config);
172
-        //add filters and actions
173
-        //modifying _views
174
-        add_filter(
175
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
176
-            array($this, 'add_additional_datetime_button'),
177
-            10,
178
-            2
179
-        );
180
-        add_filter(
181
-            'FHEE_event_datetime_metabox_clone_button_template',
182
-            array($this, 'add_datetime_clone_button'),
183
-            10,
184
-            2
185
-        );
186
-        add_filter(
187
-            'FHEE_event_datetime_metabox_timezones_template',
188
-            array($this, 'datetime_timezones_template'),
189
-            10,
190
-            2
191
-        );
192
-        //filters for event list table
193
-        add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
194
-        add_filter(
195
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
196
-            array($this, 'extra_list_table_actions'),
197
-            10,
198
-            2
199
-        );
200
-        //legend item
201
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
202
-        add_action('admin_init', array($this, 'admin_init'));
203
-        //heartbeat stuff
204
-        add_filter('heartbeat_received', array($this, 'heartbeat_response'), 10, 2);
205
-    }
206
-
207
-
208
-    /**
209
-     * admin_init
210
-     */
211
-    public function admin_init()
212
-    {
213
-        EE_Registry::$i18n_js_strings = array_merge(
214
-            EE_Registry::$i18n_js_strings,
215
-            array(
216
-                'image_confirm'          => esc_html__(
217
-                    'Do you really want to delete this image? Please remember to update your event to complete the removal.',
218
-                    'event_espresso'
219
-                ),
220
-                'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
221
-                'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
222
-                'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
223
-                'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
224
-                'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
225
-            )
226
-        );
227
-    }
228
-
229
-
230
-    /**
231
-     * This will be used to listen for any heartbeat data packages coming via the WordPress heartbeat API and handle
232
-     * accordingly.
233
-     *
234
-     * @param array $response The existing heartbeat response array.
235
-     * @param array $data     The incoming data package.
236
-     * @return array  possibly appended response.
237
-     */
238
-    public function heartbeat_response($response, $data)
239
-    {
240
-        /**
241
-         * check whether count of tickets is approaching the potential
242
-         * limits for the server.
243
-         */
244
-        if (! empty($data['input_count'])) {
245
-            $response['max_input_vars_check'] = EE_Registry::instance()->CFG->environment->max_input_vars_limit_check(
246
-                $data['input_count']
247
-            );
248
-        }
249
-        return $response;
250
-    }
251
-
252
-
253
-    /**
254
-     * Add per page screen options to the default ticket list table view.
255
-     */
256
-    protected function _add_screen_options_ticket_list_table()
257
-    {
258
-        $this->_per_page_screen_option();
259
-    }
260
-
261
-
262
-    /**
263
-     * @param string $return
264
-     * @param int    $id
265
-     * @param string $new_title
266
-     * @param string $new_slug
267
-     * @return string
268
-     */
269
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
270
-    {
271
-        $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
272
-        //make sure this is only when editing
273
-        if (! empty($id)) {
274
-            $href   = EE_Admin_Page::add_query_args_and_nonce(
275
-                array('action' => 'duplicate_event', 'EVT_ID' => $id),
276
-                $this->_admin_base_url
277
-            );
278
-            $title  = esc_attr__('Duplicate Event', 'event_espresso');
279
-            $return .= '<a href="'
280
-                       . $href
281
-                       . '" title="'
282
-                       . $title
283
-                       . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
284
-                       . $title
285
-                       . '</button>';
286
-        }
287
-        return $return;
288
-    }
289
-
290
-
291
-    /**
292
-     * Set the list table views for the default ticket list table view.
293
-     */
294
-    public function _set_list_table_views_ticket_list_table()
295
-    {
296
-        $this->_views = array(
297
-            'all'     => array(
298
-                'slug'        => 'all',
299
-                'label'       => esc_html__('All', 'event_espresso'),
300
-                'count'       => 0,
301
-                'bulk_action' => array(
302
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
303
-                ),
304
-            ),
305
-            'trashed' => array(
306
-                'slug'        => 'trashed',
307
-                'label'       => esc_html__('Trash', 'event_espresso'),
308
-                'count'       => 0,
309
-                'bulk_action' => array(
310
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
311
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
312
-                ),
313
-            ),
314
-        );
315
-    }
316
-
317
-
318
-    /**
319
-     * Enqueue scripts and styles for the event editor.
320
-     */
321
-    public function load_scripts_styles_edit()
322
-    {
323
-        wp_register_script(
324
-            'ee-event-editor-heartbeat',
325
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
326
-            array('ee_admin_js', 'heartbeat'),
327
-            EVENT_ESPRESSO_VERSION,
328
-            true
329
-        );
330
-        wp_enqueue_script('ee-accounting');
331
-        //styles
332
-        wp_enqueue_style('espresso-ui-theme');
333
-        wp_enqueue_script('event_editor_js');
334
-        wp_enqueue_script('ee-event-editor-heartbeat');
335
-    }
336
-
337
-
338
-    /**
339
-     * Returns template for the additional datetime.
340
-     * @param $template
341
-     * @param $template_args
342
-     * @return mixed
343
-     * @throws DomainException
344
-     */
345
-    public function add_additional_datetime_button($template, $template_args)
346
-    {
347
-        return EEH_Template::display_template(
348
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
349
-            $template_args,
350
-            true
351
-        );
352
-    }
353
-
354
-
355
-    /**
356
-     * Returns the template for cloning a datetime.
357
-     * @param $template
358
-     * @param $template_args
359
-     * @return mixed
360
-     * @throws DomainException
361
-     */
362
-    public function add_datetime_clone_button($template, $template_args)
363
-    {
364
-        return EEH_Template::display_template(
365
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
366
-            $template_args,
367
-            true
368
-        );
369
-    }
370
-
371
-
372
-    /**
373
-     * Returns the template for datetime timezones.
374
-     * @param $template
375
-     * @param $template_args
376
-     * @return mixed
377
-     * @throws DomainException
378
-     */
379
-    public function datetime_timezones_template($template, $template_args)
380
-    {
381
-        return EEH_Template::display_template(
382
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
383
-            $template_args,
384
-            true
385
-        );
386
-    }
387
-
388
-
389
-    /**
390
-     * Sets the views for the default list table view.
391
-     */
392
-    protected function _set_list_table_views_default()
393
-    {
394
-        parent::_set_list_table_views_default();
395
-        $new_views    = array(
396
-            'today' => array(
397
-                'slug'        => 'today',
398
-                'label'       => esc_html__('Today', 'event_espresso'),
399
-                'count'       => $this->total_events_today(),
400
-                'bulk_action' => array(
401
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
402
-                ),
403
-            ),
404
-            'month' => array(
405
-                'slug'        => 'month',
406
-                'label'       => esc_html__('This Month', 'event_espresso'),
407
-                'count'       => $this->total_events_this_month(),
408
-                'bulk_action' => array(
409
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
410
-                ),
411
-            ),
412
-        );
413
-        $this->_views = array_merge($this->_views, $new_views);
414
-    }
415
-
416
-
417
-    /**
418
-     * Returns the extra action links for the default list table view.
419
-     * @param array     $action_links
420
-     * @param \EE_Event $event
421
-     * @return array
422
-     * @throws EE_Error
423
-     */
424
-    public function extra_list_table_actions(array $action_links, \EE_Event $event)
425
-    {
426
-        if (EE_Registry::instance()->CAP->current_user_can(
427
-            'ee_read_registrations',
428
-            'espresso_registrations_reports',
429
-            $event->ID()
430
-        )
431
-        ) {
432
-            $reports_query_args = array(
433
-                'action' => 'reports',
434
-                'EVT_ID' => $event->ID(),
435
-            );
436
-            $reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
437
-            $action_links[]     = '<a href="'
438
-                                  . $reports_link
439
-                                  . '" title="'
440
-                                  . esc_attr__('View Report', 'event_espresso')
441
-                                  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
442
-                                  . "\n\t";
443
-        }
444
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
445
-            EE_Registry::instance()->load_helper('MSG_Template');
446
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
447
-                'see_notifications_for',
448
-                null,
449
-                array('EVT_ID' => $event->ID())
450
-            );
451
-        }
452
-        return $action_links;
453
-    }
454
-
455
-
456
-    /**
457
-     * @param $items
458
-     * @return mixed
459
-     */
460
-    public function additional_legend_items($items)
461
-    {
462
-        if (EE_Registry::instance()->CAP->current_user_can(
463
-            'ee_read_registrations',
464
-            'espresso_registrations_reports'
465
-        )
466
-        ) {
467
-            $items['reports'] = array(
468
-                'class' => 'dashicons dashicons-chart-bar',
469
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
470
-            );
471
-        }
472
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
473
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
474
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
475
-                $items['view_related_messages'] = array(
476
-                    'class' => $related_for_icon['css_class'],
477
-                    'desc'  => $related_for_icon['label'],
478
-                );
479
-            }
480
-        }
481
-        return $items;
482
-    }
483
-
484
-
485
-    /**
486
-     * This is the callback method for the duplicate event route
487
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
488
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
489
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
490
-     * After duplication the redirect is to the new event edit page.
491
-     *
492
-     * @return void
493
-     * @access protected
494
-     * @throws EE_Error If EE_Event is not available with given ID
495
-     */
496
-    protected function _duplicate_event()
497
-    {
498
-        // first make sure the ID for the event is in the request.
499
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
500
-        if (! isset($this->_req_data['EVT_ID'])) {
501
-            EE_Error::add_error(
502
-                esc_html__(
503
-                    'In order to duplicate an event an Event ID is required.  None was given.',
504
-                    'event_espresso'
505
-                ),
506
-                __FILE__,
507
-                __FUNCTION__,
508
-                __LINE__
509
-            );
510
-            $this->_redirect_after_action(false, '', '', array(), true);
511
-            return;
512
-        }
513
-        //k we've got EVT_ID so let's use that to get the event we'll duplicate
514
-        $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
515
-        if (! $orig_event instanceof EE_Event) {
516
-            throw new EE_Error(
517
-                sprintf(
518
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
519
-                    $this->_req_data['EVT_ID']
520
-                )
521
-            );
522
-        }
523
-        //k now let's clone the $orig_event before getting relations
524
-        $new_event = clone $orig_event;
525
-        //original datetimes
526
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
527
-        //other original relations
528
-        $orig_ven = $orig_event->get_many_related('Venue');
529
-        //reset the ID and modify other details to make it clear this is a dupe
530
-        $new_event->set('EVT_ID', 0);
531
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
532
-        $new_event->set('EVT_name', $new_name);
533
-        $new_event->set(
534
-            'EVT_slug',
535
-            wp_unique_post_slug(
536
-                sanitize_title($orig_event->name()),
537
-                0,
538
-                'publish',
539
-                'espresso_events',
540
-                0
541
-            )
542
-        );
543
-        $new_event->set('status', 'draft');
544
-        //duplicate discussion settings
545
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
546
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
547
-        //save the new event
548
-        $new_event->save();
549
-        //venues
550
-        foreach ($orig_ven as $ven) {
551
-            $new_event->_add_relation_to($ven, 'Venue');
552
-        }
553
-        $new_event->save();
554
-        //now we need to get the question group relations and handle that
555
-        //first primary question groups
556
-        $orig_primary_qgs = $orig_event->get_many_related(
557
-            'Question_Group',
558
-            array(array('Event_Question_Group.EQG_primary' => 1))
559
-        );
560
-        if (! empty($orig_primary_qgs)) {
561
-            foreach ($orig_primary_qgs as $id => $obj) {
562
-                if ($obj instanceof EE_Question_Group) {
563
-                    $new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 1));
564
-                }
565
-            }
566
-        }
567
-        //next additional attendee question groups
568
-        $orig_additional_qgs = $orig_event->get_many_related(
569
-            'Question_Group',
570
-            array(array('Event_Question_Group.EQG_primary' => 0))
571
-        );
572
-        if (! empty($orig_additional_qgs)) {
573
-            foreach ($orig_additional_qgs as $id => $obj) {
574
-                if ($obj instanceof EE_Question_Group) {
575
-                    $new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 0));
576
-                }
577
-            }
578
-        }
579
-
580
-        $new_event->save();
581
-
582
-        //k now that we have the new event saved we can loop through the datetimes and start adding relations.
583
-        $cloned_tickets = array();
584
-        foreach ($orig_datetimes as $orig_dtt) {
585
-            if (! $orig_dtt instanceof EE_Datetime) {
586
-                continue;
587
-            }
588
-            $new_dtt   = clone $orig_dtt;
589
-            $orig_tkts = $orig_dtt->tickets();
590
-            //save new dtt then add to event
591
-            $new_dtt->set('DTT_ID', 0);
592
-            $new_dtt->set('DTT_sold', 0);
593
-            $new_dtt->set_reserved(0);
594
-            $new_dtt->save();
595
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
596
-            $new_event->save();
597
-            //now let's get the ticket relations setup.
598
-            foreach ((array)$orig_tkts as $orig_tkt) {
599
-                //it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
600
-                if (! $orig_tkt instanceof EE_Ticket) {
601
-                    continue;
602
-                }
603
-                //is this ticket archived?  If it is then let's skip
604
-                if ($orig_tkt->get('TKT_deleted')) {
605
-                    continue;
606
-                }
607
-                // does this original ticket already exist in the clone_tickets cache?
608
-                //  If so we'll just use the new ticket from it.
609
-                if (isset($cloned_tickets[$orig_tkt->ID()])) {
610
-                    $new_tkt = $cloned_tickets[$orig_tkt->ID()];
611
-                } else {
612
-                    $new_tkt = clone $orig_tkt;
613
-                    //get relations on the $orig_tkt that we need to setup.
614
-                    $orig_prices = $orig_tkt->prices();
615
-                    $new_tkt->set('TKT_ID', 0);
616
-                    $new_tkt->set('TKT_sold', 0);
617
-                    $new_tkt->set('TKT_reserved', 0);
618
-                    $new_tkt->save(); //make sure new ticket has ID.
619
-                    //price relations on new ticket need to be setup.
620
-                    foreach ($orig_prices as $orig_price) {
621
-                        $new_price = clone $orig_price;
622
-                        $new_price->set('PRC_ID', 0);
623
-                        $new_price->save();
624
-                        $new_tkt->_add_relation_to($new_price, 'Price');
625
-                        $new_tkt->save();
626
-                    }
627
-
628
-                    do_action(
629
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
630
-                        $orig_tkt,
631
-                        $new_tkt,
632
-                        $orig_prices,
633
-                        $orig_event,
634
-                        $orig_dtt,
635
-                        $new_dtt
636
-                    );
637
-                }
638
-                // k now we can add the new ticket as a relation to the new datetime
639
-                // and make sure its added to our cached $cloned_tickets array
640
-                // for use with later datetimes that have the same ticket.
641
-                $new_dtt->_add_relation_to($new_tkt, 'Ticket');
642
-                $new_dtt->save();
643
-                $cloned_tickets[$orig_tkt->ID()] = $new_tkt;
644
-            }
645
-        }
646
-        //clone taxonomy information
647
-        $taxonomies_to_clone_with = apply_filters(
648
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
649
-            array('espresso_event_categories', 'espresso_event_type', 'post_tag')
650
-        );
651
-        //get terms for original event (notice)
652
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
653
-        //loop through terms and add them to new event.
654
-        foreach ($orig_terms as $term) {
655
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
656
-        }
657
-
658
-        //duplicate other core WP_Post items for this event.
659
-        //post thumbnail (feature image).
660
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
661
-        if ($feature_image_id) {
662
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
663
-        }
664
-
665
-        //duplicate page_template setting
666
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
667
-        if ($page_template) {
668
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
669
-        }
670
-
671
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
672
-        //now let's redirect to the edit page for this duplicated event if we have a new event id.
673
-        if ($new_event->ID()) {
674
-            $redirect_args = array(
675
-                'post'   => $new_event->ID(),
676
-                'action' => 'edit',
677
-            );
678
-            EE_Error::add_success(
679
-                esc_html__(
680
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
681
-                    'event_espresso'
682
-                )
683
-            );
684
-        } else {
685
-            $redirect_args = array(
686
-                'action' => 'default',
687
-            );
688
-            EE_Error::add_error(
689
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
690
-                __FILE__,
691
-                __FUNCTION__,
692
-                __LINE__
693
-            );
694
-        }
695
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
696
-    }
697
-
698
-
699
-    /**
700
-     * Generates output for the import page.
701
-     * @throws DomainException
702
-     */
703
-    protected function _import_page()
704
-    {
705
-        $title                                      = esc_html__('Import', 'event_espresso');
706
-        $intro                                      = esc_html__(
707
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
708
-            'event_espresso'
709
-        );
710
-        $form_url                                   = EVENTS_ADMIN_URL;
711
-        $action                                     = 'import_events';
712
-        $type                                       = 'csv';
713
-        $this->_template_args['form']               = EE_Import::instance()->upload_form(
714
-            $title, $intro, $form_url, $action, $type
715
-        );
716
-        $this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
717
-            array('action' => 'sample_export_file'),
718
-            $this->_admin_base_url
719
-        );
720
-        $content                                    = EEH_Template::display_template(
721
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
722
-            $this->_template_args,
723
-            true
724
-        );
725
-        $this->_template_args['admin_page_content'] = $content;
726
-        $this->display_admin_page_with_sidebar();
727
-    }
728
-
729
-
730
-    /**
731
-     * _import_events
732
-     * This handles displaying the screen and running imports for importing events.
733
-     *
734
-     * @return void
735
-     */
736
-    protected function _import_events()
737
-    {
738
-        require_once(EE_CLASSES . 'EE_Import.class.php');
739
-        $success = EE_Import::instance()->import();
740
-        $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
741
-    }
742
-
743
-
744
-    /**
745
-     * _events_export
746
-     * Will export all (or just the given event) to a Excel compatible file.
747
-     *
748
-     * @access protected
749
-     * @return void
750
-     */
751
-    protected function _events_export()
752
-    {
753
-        if (isset($this->_req_data['EVT_ID'])) {
754
-            $event_ids = $this->_req_data['EVT_ID'];
755
-        } elseif (isset($this->_req_data['EVT_IDs'])) {
756
-            $event_ids = $this->_req_data['EVT_IDs'];
757
-        } else {
758
-            $event_ids = null;
759
-        }
760
-        //todo: I don't like doing this but it'll do until we modify EE_Export Class.
761
-        $new_request_args = array(
762
-            'export' => 'report',
763
-            'action' => 'all_event_data',
764
-            'EVT_ID' => $event_ids,
765
-        );
766
-        $this->_req_data  = array_merge($this->_req_data, $new_request_args);
767
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
768
-            require_once(EE_CLASSES . 'EE_Export.class.php');
769
-            $EE_Export = EE_Export::instance($this->_req_data);
770
-            $EE_Export->export();
771
-        }
772
-    }
773
-
774
-
775
-    /**
776
-     * handle category exports()
777
-     *
778
-     * @return void
779
-     */
780
-    protected function _categories_export()
781
-    {
782
-        //todo: I don't like doing this but it'll do until we modify EE_Export Class.
783
-        $new_request_args = array(
784
-            'export'       => 'report',
785
-            'action'       => 'categories',
786
-            'category_ids' => $this->_req_data['EVT_CAT_ID'],
787
-        );
788
-        $this->_req_data  = array_merge($this->_req_data, $new_request_args);
789
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
790
-            require_once(EE_CLASSES . 'EE_Export.class.php');
791
-            $EE_Export = EE_Export::instance($this->_req_data);
792
-            $EE_Export->export();
793
-        }
794
-    }
795
-
796
-
797
-    /**
798
-     * Creates a sample CSV file for importing
799
-     */
800
-    protected function _sample_export_file()
801
-    {
802
-        //		require_once(EE_CLASSES . 'EE_Export.class.php');
803
-        EE_Export::instance()->export_sample();
804
-    }
805
-
806
-
807
-    /*************        Template Settings        *************/
808
-    /**
809
-     * Generates template settings page output
810
-     * @throws DomainException
811
-     * @throws EE_Error
812
-     */
813
-    protected function _template_settings()
814
-    {
815
-        $this->_template_args['values'] = $this->_yes_no_values;
816
-        /**
817
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
818
-         * from General_Settings_Admin_Page to here.
819
-         */
820
-        $this->_template_args = apply_filters(
821
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
822
-            $this->_template_args
823
-        );
824
-        $this->_set_add_edit_form_tags('update_template_settings');
825
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
826
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
827
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
828
-            $this->_template_args,
829
-            true
830
-        );
831
-        $this->display_admin_page_with_sidebar();
832
-    }
833
-
834
-
835
-    /**
836
-     * Handler for updating template settings.
837
-     */
838
-    protected function _update_template_settings()
839
-    {
840
-        /**
841
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
842
-         * from General_Settings_Admin_Page to here.
843
-         */
844
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
845
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
846
-            EE_Registry::instance()->CFG->template_settings,
847
-            $this->_req_data
848
-        );
849
-        //update custom post type slugs and detect if we need to flush rewrite rules
850
-        $old_slug                                          = EE_Registry::instance()->CFG->core->event_cpt_slug;
851
-        EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
852
-            ? EE_Registry::instance()->CFG->core->event_cpt_slug
853
-            : sanitize_title_with_dashes($this->_req_data['event_cpt_slug']);
854
-        $what                                              = 'Template Settings';
855
-        $success                                           = $this->_update_espresso_configuration(
856
-            $what,
857
-            EE_Registry::instance()->CFG->template_settings,
858
-            __FILE__,
859
-            __FUNCTION__,
860
-            __LINE__
861
-        );
862
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
863
-            update_option('ee_flush_rewrite_rules', true);
864
-        }
865
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
866
-    }
867
-
868
-
869
-    /**
870
-     * _premium_event_editor_meta_boxes
871
-     * add all metaboxes related to the event_editor
872
-     *
873
-     * @access protected
874
-     * @return void
875
-     * @throws EE_Error
876
-     */
877
-    protected function _premium_event_editor_meta_boxes()
878
-    {
879
-        $this->verify_cpt_object();
880
-        add_meta_box(
881
-            'espresso_event_editor_event_options',
882
-            esc_html__('Event Registration Options', 'event_espresso'),
883
-            array($this, 'registration_options_meta_box'),
884
-            $this->page_slug,
885
-            'side',
886
-            'core'
887
-        );
888
-    }
889
-
890
-
891
-    /**
892
-     * override caf metabox
893
-     *
894
-     * @return void
895
-     * @throws DomainException
896
-     */
897
-    public function registration_options_meta_box()
898
-    {
899
-        $yes_no_values                                    = array(
900
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
901
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
902
-        );
903
-        $default_reg_status_values                        = EEM_Registration::reg_status_array(
904
-            array(
905
-                EEM_Registration::status_id_cancelled,
906
-                EEM_Registration::status_id_declined,
907
-                EEM_Registration::status_id_incomplete,
908
-                EEM_Registration::status_id_wait_list,
909
-            ),
910
-            true
911
-        );
912
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
913
-        $template_args['_event']                          = $this->_cpt_model_obj;
914
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
915
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
916
-            'default_reg_status',
917
-            $default_reg_status_values,
918
-            $this->_cpt_model_obj->default_registration_status()
919
-        );
920
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
921
-            'display_desc',
922
-            $yes_no_values,
923
-            $this->_cpt_model_obj->display_description()
924
-        );
925
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
926
-            'display_ticket_selector',
927
-            $yes_no_values,
928
-            $this->_cpt_model_obj->display_ticket_selector(),
929
-            '',
930
-            '',
931
-            false
932
-        );
933
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
934
-            'EVT_default_registration_status',
935
-            $default_reg_status_values,
936
-            $this->_cpt_model_obj->default_registration_status()
937
-        );
938
-        $template_args['additional_registration_options'] = apply_filters(
939
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
940
-            '',
941
-            $template_args,
942
-            $yes_no_values,
943
-            $default_reg_status_values
944
-        );
945
-        EEH_Template::display_template(
946
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
947
-            $template_args
948
-        );
949
-    }
950
-
951
-
952
-
953
-    /**
954
-     * wp_list_table_mods for caf
955
-     * ============================
956
-     */
957
-    /**
958
-     * hook into list table filters and provide filters for caffeinated list table
959
-     *
960
-     * @param  array $old_filters    any existing filters present
961
-     * @param  array $list_table_obj the list table object
962
-     * @return array                  new filters
963
-     */
964
-    public function list_table_filters($old_filters, $list_table_obj)
965
-    {
966
-        $filters = array();
967
-        //first month/year filters
968
-        $filters[] = $this->espresso_event_months_dropdown();
969
-        $status    = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
970
-        //active status dropdown
971
-        if ($status !== 'draft') {
972
-            $filters[] = $this->active_status_dropdown(
973
-                isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
974
-            );
975
-        }
976
-        //category filter
977
-        $filters[] = $this->category_dropdown();
978
-        return array_merge($old_filters, $filters);
979
-    }
980
-
981
-
982
-    /**
983
-     * espresso_event_months_dropdown
984
-     *
985
-     * @access public
986
-     * @return string                dropdown listing month/year selections for events.
987
-     */
988
-    public function espresso_event_months_dropdown()
989
-    {
990
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
991
-        // Note we need to include any other filters that are set!
992
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
993
-        //categories?
994
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
995
-            ? $this->_req_data['EVT_CAT']
996
-            : null;
997
-        //active status?
998
-        $active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
999
-        $cur_date      = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1000
-        return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * returns a list of "active" statuses on the event
1006
-     *
1007
-     * @param  string $current_value whatever the current active status is
1008
-     * @return string
1009
-     */
1010
-    public function active_status_dropdown($current_value = '')
1011
-    {
1012
-        $select_name = 'active_status';
1013
-        $values      = array(
1014
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1015
-            'active'   => esc_html__('Active', 'event_espresso'),
1016
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1017
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1018
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1019
-        );
1020
-        $id          = 'id="espresso-active-status-dropdown-filter"';
1021
-        $class       = 'wide';
1022
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * output a dropdown of the categories for the category filter on the event admin list table
1028
-     *
1029
-     * @access  public
1030
-     * @return string html
1031
-     */
1032
-    public function category_dropdown()
1033
-    {
1034
-        $cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1035
-        return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * get total number of events today
1041
-     *
1042
-     * @access public
1043
-     * @return int
1044
-     * @throws EE_Error
1045
-     */
1046
-    public function total_events_today()
1047
-    {
1048
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1049
-            'DTT_EVT_start',
1050
-            date('Y-m-d') . ' 00:00:00',
1051
-            'Y-m-d H:i:s',
1052
-            'UTC'
1053
-        );
1054
-        $end   = EEM_Datetime::instance()->convert_datetime_for_query(
1055
-            'DTT_EVT_start',
1056
-            date('Y-m-d') . ' 23:59:59',
1057
-            'Y-m-d H:i:s',
1058
-            'UTC'
1059
-        );
1060
-        $where = array(
1061
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1062
-        );
1063
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1064
-        return $count;
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * get total number of events this month
1070
-     *
1071
-     * @access public
1072
-     * @return int
1073
-     * @throws EE_Error
1074
-     */
1075
-    public function total_events_this_month()
1076
-    {
1077
-        //Dates
1078
-        $this_year_r     = date('Y');
1079
-        $this_month_r    = date('m');
1080
-        $days_this_month = date('t');
1081
-        $start           = EEM_Datetime::instance()->convert_datetime_for_query(
1082
-            'DTT_EVT_start',
1083
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1084
-            'Y-m-d H:i:s',
1085
-            'UTC'
1086
-        );
1087
-        $end             = EEM_Datetime::instance()->convert_datetime_for_query(
1088
-            'DTT_EVT_start',
1089
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1090
-            'Y-m-d H:i:s',
1091
-            'UTC'
1092
-        );
1093
-        $where           = array(
1094
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1095
-        );
1096
-        $count           = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1097
-        return $count;
1098
-    }
1099
-
1100
-
1101
-    /** DEFAULT TICKETS STUFF **/
1102
-
1103
-    /**
1104
-     * Output default tickets list table view.
1105
-     */
1106
-    public function _tickets_overview_list_table()
1107
-    {
1108
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1109
-        $this->display_admin_list_table_page_with_no_sidebar();
1110
-    }
1111
-
1112
-
1113
-    /**
1114
-     * @param int  $per_page
1115
-     * @param bool $count
1116
-     * @param bool $trashed
1117
-     * @return \EE_Soft_Delete_Base_Class[]|int
1118
-     */
1119
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1120
-    {
1121
-        $orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1122
-        $order   = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1123
-        switch ($orderby) {
1124
-            case 'TKT_name':
1125
-                $orderby = array('TKT_name' => $order);
1126
-                break;
1127
-            case 'TKT_price':
1128
-                $orderby = array('TKT_price' => $order);
1129
-                break;
1130
-            case 'TKT_uses':
1131
-                $orderby = array('TKT_uses' => $order);
1132
-                break;
1133
-            case 'TKT_min':
1134
-                $orderby = array('TKT_min' => $order);
1135
-                break;
1136
-            case 'TKT_max':
1137
-                $orderby = array('TKT_max' => $order);
1138
-                break;
1139
-            case 'TKT_qty':
1140
-                $orderby = array('TKT_qty' => $order);
1141
-                break;
1142
-        }
1143
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1144
-            ? $this->_req_data['paged']
1145
-            : 1;
1146
-        $per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1147
-            ? $this->_req_data['perpage']
1148
-            : $per_page;
1149
-        $_where       = array(
1150
-            'TKT_is_default' => 1,
1151
-            'TKT_deleted'    => $trashed,
1152
-        );
1153
-        $offset       = ($current_page - 1) * $per_page;
1154
-        $limit        = array($offset, $per_page);
1155
-        if (isset($this->_req_data['s'])) {
1156
-            $sstr         = '%' . $this->_req_data['s'] . '%';
1157
-            $_where['OR'] = array(
1158
-                'TKT_name'        => array('LIKE', $sstr),
1159
-                'TKT_description' => array('LIKE', $sstr),
1160
-            );
1161
-        }
1162
-        $query_params = array(
1163
-            $_where,
1164
-            'order_by' => $orderby,
1165
-            'limit'    => $limit,
1166
-            'group_by' => 'TKT_ID',
1167
-        );
1168
-        if ($count) {
1169
-            return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1170
-        } else {
1171
-            return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1172
-        }
1173
-    }
1174
-
1175
-
1176
-    /**
1177
-     * @param bool $trash
1178
-     * @throws EE_Error
1179
-     */
1180
-    protected function _trash_or_restore_ticket($trash = false)
1181
-    {
1182
-        $success = 1;
1183
-        $TKT     = EEM_Ticket::instance();
1184
-        //checkboxes?
1185
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1186
-            //if array has more than one element then success message should be plural
1187
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1188
-            //cycle thru the boxes
1189
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1190
-                if ($trash) {
1191
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1192
-                        $success = 0;
1193
-                    }
1194
-                } else {
1195
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1196
-                        $success = 0;
1197
-                    }
1198
-                }
1199
-            }
1200
-        } else {
1201
-            //grab single id and trash
1202
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1203
-            if ($trash) {
1204
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1205
-                    $success = 0;
1206
-                }
1207
-            } else {
1208
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1209
-                    $success = 0;
1210
-                }
1211
-            }
1212
-        }
1213
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1214
-        $query_args  = array(
1215
-            'action' => 'ticket_list_table',
1216
-            'status' => $trash ? '' : 'trashed',
1217
-        );
1218
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1219
-    }
1220
-
1221
-
1222
-    /**
1223
-     * Handles trashing default ticket.
1224
-     */
1225
-    protected function _delete_ticket()
1226
-    {
1227
-        $success = 1;
1228
-        //checkboxes?
1229
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1230
-            //if array has more than one element then success message should be plural
1231
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1232
-            //cycle thru the boxes
1233
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1234
-                //delete
1235
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1236
-                    $success = 0;
1237
-                }
1238
-            }
1239
-        } else {
1240
-            //grab single id and trash
1241
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1242
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1243
-                $success = 0;
1244
-            }
1245
-        }
1246
-        $action_desc = 'deleted';
1247
-        $query_args  = array(
1248
-            'action' => 'ticket_list_table',
1249
-            'status' => 'trashed',
1250
-        );
1251
-        //fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1252
-        if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1253
-            array(array('TKT_is_default' => 1)),
1254
-            'TKT_ID',
1255
-            true
1256
-        )
1257
-        ) {
1258
-            $query_args = array();
1259
-        }
1260
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1261
-    }
1262
-
1263
-
1264
-    /**
1265
-     * @param int $TKT_ID
1266
-     * @return bool|int
1267
-     * @throws EE_Error
1268
-     */
1269
-    protected function _delete_the_ticket($TKT_ID)
1270
-    {
1271
-        $tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1272
-        $tkt->_remove_relations('Datetime');
1273
-        //delete all related prices first
1274
-        $tkt->delete_related_permanently('Price');
1275
-        return $tkt->delete_permanently();
1276
-    }
17
+	/**
18
+	 * Extend_Events_Admin_Page constructor.
19
+	 *
20
+	 * @param bool $routing
21
+	 */
22
+	public function __construct($routing = true)
23
+	{
24
+		parent::__construct($routing);
25
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
27
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
28
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
29
+		}
30
+	}
31
+
32
+
33
+	/**
34
+	 * Sets routes.
35
+	 */
36
+	protected function _extend_page_config()
37
+	{
38
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
39
+		//is there a evt_id in the request?
40
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
41
+			? $this->_req_data['EVT_ID']
42
+			: 0;
43
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
44
+		//tkt_id?
45
+		$tkt_id             = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
46
+			? $this->_req_data['TKT_ID']
47
+			: 0;
48
+		$new_page_routes    = array(
49
+			'duplicate_event'          => array(
50
+				'func'       => '_duplicate_event',
51
+				'capability' => 'ee_edit_event',
52
+				'obj_id'     => $evt_id,
53
+				'noheader'   => true,
54
+			),
55
+			'ticket_list_table'        => array(
56
+				'func'       => '_tickets_overview_list_table',
57
+				'capability' => 'ee_read_default_tickets',
58
+			),
59
+			'trash_ticket'             => array(
60
+				'func'       => '_trash_or_restore_ticket',
61
+				'capability' => 'ee_delete_default_ticket',
62
+				'obj_id'     => $tkt_id,
63
+				'noheader'   => true,
64
+				'args'       => array('trash' => true),
65
+			),
66
+			'trash_tickets'            => array(
67
+				'func'       => '_trash_or_restore_ticket',
68
+				'capability' => 'ee_delete_default_tickets',
69
+				'noheader'   => true,
70
+				'args'       => array('trash' => true),
71
+			),
72
+			'restore_ticket'           => array(
73
+				'func'       => '_trash_or_restore_ticket',
74
+				'capability' => 'ee_delete_default_ticket',
75
+				'obj_id'     => $tkt_id,
76
+				'noheader'   => true,
77
+			),
78
+			'restore_tickets'          => array(
79
+				'func'       => '_trash_or_restore_ticket',
80
+				'capability' => 'ee_delete_default_tickets',
81
+				'noheader'   => true,
82
+			),
83
+			'delete_ticket'            => array(
84
+				'func'       => '_delete_ticket',
85
+				'capability' => 'ee_delete_default_ticket',
86
+				'obj_id'     => $tkt_id,
87
+				'noheader'   => true,
88
+			),
89
+			'delete_tickets'           => array(
90
+				'func'       => '_delete_ticket',
91
+				'capability' => 'ee_delete_default_tickets',
92
+				'noheader'   => true,
93
+			),
94
+			'import_page'              => array(
95
+				'func'       => '_import_page',
96
+				'capability' => 'import',
97
+			),
98
+			'import'                   => array(
99
+				'func'       => '_import_events',
100
+				'capability' => 'import',
101
+				'noheader'   => true,
102
+			),
103
+			'import_events'            => array(
104
+				'func'       => '_import_events',
105
+				'capability' => 'import',
106
+				'noheader'   => true,
107
+			),
108
+			'export_events'            => array(
109
+				'func'       => '_events_export',
110
+				'capability' => 'export',
111
+				'noheader'   => true,
112
+			),
113
+			'export_categories'        => array(
114
+				'func'       => '_categories_export',
115
+				'capability' => 'export',
116
+				'noheader'   => true,
117
+			),
118
+			'sample_export_file'       => array(
119
+				'func'       => '_sample_export_file',
120
+				'capability' => 'export',
121
+				'noheader'   => true,
122
+			),
123
+			'update_template_settings' => array(
124
+				'func'       => '_update_template_settings',
125
+				'capability' => 'manage_options',
126
+				'noheader'   => true,
127
+			),
128
+		);
129
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
130
+		//partial route/config override
131
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
132
+		$this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
133
+		$this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
134
+		$this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
135
+		$this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
136
+		$this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
137
+		//add tickets tab but only if there are more than one default ticket!
138
+		$tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
139
+			array(array('TKT_is_default' => 1)),
140
+			'TKT_ID',
141
+			true
142
+		);
143
+		if ($tkt_count > 1) {
144
+			$new_page_config = array(
145
+				'ticket_list_table' => array(
146
+					'nav'           => array(
147
+						'label' => esc_html__('Default Tickets', 'event_espresso'),
148
+						'order' => 60,
149
+					),
150
+					'list_table'    => 'Tickets_List_Table',
151
+					'require_nonce' => false,
152
+				),
153
+			);
154
+		}
155
+		//template settings
156
+		$new_page_config['template_settings'] = array(
157
+			'nav'           => array(
158
+				'label' => esc_html__('Templates', 'event_espresso'),
159
+				'order' => 30,
160
+			),
161
+			'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
162
+			'help_tabs'     => array(
163
+				'general_settings_templates_help_tab' => array(
164
+					'title'    => esc_html__('Templates', 'event_espresso'),
165
+					'filename' => 'general_settings_templates',
166
+				),
167
+			),
168
+			'help_tour'     => array('Templates_Help_Tour'),
169
+			'require_nonce' => false,
170
+		);
171
+		$this->_page_config                   = array_merge($this->_page_config, $new_page_config);
172
+		//add filters and actions
173
+		//modifying _views
174
+		add_filter(
175
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
176
+			array($this, 'add_additional_datetime_button'),
177
+			10,
178
+			2
179
+		);
180
+		add_filter(
181
+			'FHEE_event_datetime_metabox_clone_button_template',
182
+			array($this, 'add_datetime_clone_button'),
183
+			10,
184
+			2
185
+		);
186
+		add_filter(
187
+			'FHEE_event_datetime_metabox_timezones_template',
188
+			array($this, 'datetime_timezones_template'),
189
+			10,
190
+			2
191
+		);
192
+		//filters for event list table
193
+		add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
194
+		add_filter(
195
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
196
+			array($this, 'extra_list_table_actions'),
197
+			10,
198
+			2
199
+		);
200
+		//legend item
201
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
202
+		add_action('admin_init', array($this, 'admin_init'));
203
+		//heartbeat stuff
204
+		add_filter('heartbeat_received', array($this, 'heartbeat_response'), 10, 2);
205
+	}
206
+
207
+
208
+	/**
209
+	 * admin_init
210
+	 */
211
+	public function admin_init()
212
+	{
213
+		EE_Registry::$i18n_js_strings = array_merge(
214
+			EE_Registry::$i18n_js_strings,
215
+			array(
216
+				'image_confirm'          => esc_html__(
217
+					'Do you really want to delete this image? Please remember to update your event to complete the removal.',
218
+					'event_espresso'
219
+				),
220
+				'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
221
+				'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
222
+				'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
223
+				'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
224
+				'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
225
+			)
226
+		);
227
+	}
228
+
229
+
230
+	/**
231
+	 * This will be used to listen for any heartbeat data packages coming via the WordPress heartbeat API and handle
232
+	 * accordingly.
233
+	 *
234
+	 * @param array $response The existing heartbeat response array.
235
+	 * @param array $data     The incoming data package.
236
+	 * @return array  possibly appended response.
237
+	 */
238
+	public function heartbeat_response($response, $data)
239
+	{
240
+		/**
241
+		 * check whether count of tickets is approaching the potential
242
+		 * limits for the server.
243
+		 */
244
+		if (! empty($data['input_count'])) {
245
+			$response['max_input_vars_check'] = EE_Registry::instance()->CFG->environment->max_input_vars_limit_check(
246
+				$data['input_count']
247
+			);
248
+		}
249
+		return $response;
250
+	}
251
+
252
+
253
+	/**
254
+	 * Add per page screen options to the default ticket list table view.
255
+	 */
256
+	protected function _add_screen_options_ticket_list_table()
257
+	{
258
+		$this->_per_page_screen_option();
259
+	}
260
+
261
+
262
+	/**
263
+	 * @param string $return
264
+	 * @param int    $id
265
+	 * @param string $new_title
266
+	 * @param string $new_slug
267
+	 * @return string
268
+	 */
269
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
270
+	{
271
+		$return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
272
+		//make sure this is only when editing
273
+		if (! empty($id)) {
274
+			$href   = EE_Admin_Page::add_query_args_and_nonce(
275
+				array('action' => 'duplicate_event', 'EVT_ID' => $id),
276
+				$this->_admin_base_url
277
+			);
278
+			$title  = esc_attr__('Duplicate Event', 'event_espresso');
279
+			$return .= '<a href="'
280
+					   . $href
281
+					   . '" title="'
282
+					   . $title
283
+					   . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
284
+					   . $title
285
+					   . '</button>';
286
+		}
287
+		return $return;
288
+	}
289
+
290
+
291
+	/**
292
+	 * Set the list table views for the default ticket list table view.
293
+	 */
294
+	public function _set_list_table_views_ticket_list_table()
295
+	{
296
+		$this->_views = array(
297
+			'all'     => array(
298
+				'slug'        => 'all',
299
+				'label'       => esc_html__('All', 'event_espresso'),
300
+				'count'       => 0,
301
+				'bulk_action' => array(
302
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
303
+				),
304
+			),
305
+			'trashed' => array(
306
+				'slug'        => 'trashed',
307
+				'label'       => esc_html__('Trash', 'event_espresso'),
308
+				'count'       => 0,
309
+				'bulk_action' => array(
310
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
311
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
312
+				),
313
+			),
314
+		);
315
+	}
316
+
317
+
318
+	/**
319
+	 * Enqueue scripts and styles for the event editor.
320
+	 */
321
+	public function load_scripts_styles_edit()
322
+	{
323
+		wp_register_script(
324
+			'ee-event-editor-heartbeat',
325
+			EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
326
+			array('ee_admin_js', 'heartbeat'),
327
+			EVENT_ESPRESSO_VERSION,
328
+			true
329
+		);
330
+		wp_enqueue_script('ee-accounting');
331
+		//styles
332
+		wp_enqueue_style('espresso-ui-theme');
333
+		wp_enqueue_script('event_editor_js');
334
+		wp_enqueue_script('ee-event-editor-heartbeat');
335
+	}
336
+
337
+
338
+	/**
339
+	 * Returns template for the additional datetime.
340
+	 * @param $template
341
+	 * @param $template_args
342
+	 * @return mixed
343
+	 * @throws DomainException
344
+	 */
345
+	public function add_additional_datetime_button($template, $template_args)
346
+	{
347
+		return EEH_Template::display_template(
348
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
349
+			$template_args,
350
+			true
351
+		);
352
+	}
353
+
354
+
355
+	/**
356
+	 * Returns the template for cloning a datetime.
357
+	 * @param $template
358
+	 * @param $template_args
359
+	 * @return mixed
360
+	 * @throws DomainException
361
+	 */
362
+	public function add_datetime_clone_button($template, $template_args)
363
+	{
364
+		return EEH_Template::display_template(
365
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
366
+			$template_args,
367
+			true
368
+		);
369
+	}
370
+
371
+
372
+	/**
373
+	 * Returns the template for datetime timezones.
374
+	 * @param $template
375
+	 * @param $template_args
376
+	 * @return mixed
377
+	 * @throws DomainException
378
+	 */
379
+	public function datetime_timezones_template($template, $template_args)
380
+	{
381
+		return EEH_Template::display_template(
382
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
383
+			$template_args,
384
+			true
385
+		);
386
+	}
387
+
388
+
389
+	/**
390
+	 * Sets the views for the default list table view.
391
+	 */
392
+	protected function _set_list_table_views_default()
393
+	{
394
+		parent::_set_list_table_views_default();
395
+		$new_views    = array(
396
+			'today' => array(
397
+				'slug'        => 'today',
398
+				'label'       => esc_html__('Today', 'event_espresso'),
399
+				'count'       => $this->total_events_today(),
400
+				'bulk_action' => array(
401
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
402
+				),
403
+			),
404
+			'month' => array(
405
+				'slug'        => 'month',
406
+				'label'       => esc_html__('This Month', 'event_espresso'),
407
+				'count'       => $this->total_events_this_month(),
408
+				'bulk_action' => array(
409
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
410
+				),
411
+			),
412
+		);
413
+		$this->_views = array_merge($this->_views, $new_views);
414
+	}
415
+
416
+
417
+	/**
418
+	 * Returns the extra action links for the default list table view.
419
+	 * @param array     $action_links
420
+	 * @param \EE_Event $event
421
+	 * @return array
422
+	 * @throws EE_Error
423
+	 */
424
+	public function extra_list_table_actions(array $action_links, \EE_Event $event)
425
+	{
426
+		if (EE_Registry::instance()->CAP->current_user_can(
427
+			'ee_read_registrations',
428
+			'espresso_registrations_reports',
429
+			$event->ID()
430
+		)
431
+		) {
432
+			$reports_query_args = array(
433
+				'action' => 'reports',
434
+				'EVT_ID' => $event->ID(),
435
+			);
436
+			$reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
437
+			$action_links[]     = '<a href="'
438
+								  . $reports_link
439
+								  . '" title="'
440
+								  . esc_attr__('View Report', 'event_espresso')
441
+								  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
442
+								  . "\n\t";
443
+		}
444
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
445
+			EE_Registry::instance()->load_helper('MSG_Template');
446
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
447
+				'see_notifications_for',
448
+				null,
449
+				array('EVT_ID' => $event->ID())
450
+			);
451
+		}
452
+		return $action_links;
453
+	}
454
+
455
+
456
+	/**
457
+	 * @param $items
458
+	 * @return mixed
459
+	 */
460
+	public function additional_legend_items($items)
461
+	{
462
+		if (EE_Registry::instance()->CAP->current_user_can(
463
+			'ee_read_registrations',
464
+			'espresso_registrations_reports'
465
+		)
466
+		) {
467
+			$items['reports'] = array(
468
+				'class' => 'dashicons dashicons-chart-bar',
469
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
470
+			);
471
+		}
472
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
473
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
474
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
475
+				$items['view_related_messages'] = array(
476
+					'class' => $related_for_icon['css_class'],
477
+					'desc'  => $related_for_icon['label'],
478
+				);
479
+			}
480
+		}
481
+		return $items;
482
+	}
483
+
484
+
485
+	/**
486
+	 * This is the callback method for the duplicate event route
487
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
488
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
489
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
490
+	 * After duplication the redirect is to the new event edit page.
491
+	 *
492
+	 * @return void
493
+	 * @access protected
494
+	 * @throws EE_Error If EE_Event is not available with given ID
495
+	 */
496
+	protected function _duplicate_event()
497
+	{
498
+		// first make sure the ID for the event is in the request.
499
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
500
+		if (! isset($this->_req_data['EVT_ID'])) {
501
+			EE_Error::add_error(
502
+				esc_html__(
503
+					'In order to duplicate an event an Event ID is required.  None was given.',
504
+					'event_espresso'
505
+				),
506
+				__FILE__,
507
+				__FUNCTION__,
508
+				__LINE__
509
+			);
510
+			$this->_redirect_after_action(false, '', '', array(), true);
511
+			return;
512
+		}
513
+		//k we've got EVT_ID so let's use that to get the event we'll duplicate
514
+		$orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
515
+		if (! $orig_event instanceof EE_Event) {
516
+			throw new EE_Error(
517
+				sprintf(
518
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
519
+					$this->_req_data['EVT_ID']
520
+				)
521
+			);
522
+		}
523
+		//k now let's clone the $orig_event before getting relations
524
+		$new_event = clone $orig_event;
525
+		//original datetimes
526
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
527
+		//other original relations
528
+		$orig_ven = $orig_event->get_many_related('Venue');
529
+		//reset the ID and modify other details to make it clear this is a dupe
530
+		$new_event->set('EVT_ID', 0);
531
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
532
+		$new_event->set('EVT_name', $new_name);
533
+		$new_event->set(
534
+			'EVT_slug',
535
+			wp_unique_post_slug(
536
+				sanitize_title($orig_event->name()),
537
+				0,
538
+				'publish',
539
+				'espresso_events',
540
+				0
541
+			)
542
+		);
543
+		$new_event->set('status', 'draft');
544
+		//duplicate discussion settings
545
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
546
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
547
+		//save the new event
548
+		$new_event->save();
549
+		//venues
550
+		foreach ($orig_ven as $ven) {
551
+			$new_event->_add_relation_to($ven, 'Venue');
552
+		}
553
+		$new_event->save();
554
+		//now we need to get the question group relations and handle that
555
+		//first primary question groups
556
+		$orig_primary_qgs = $orig_event->get_many_related(
557
+			'Question_Group',
558
+			array(array('Event_Question_Group.EQG_primary' => 1))
559
+		);
560
+		if (! empty($orig_primary_qgs)) {
561
+			foreach ($orig_primary_qgs as $id => $obj) {
562
+				if ($obj instanceof EE_Question_Group) {
563
+					$new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 1));
564
+				}
565
+			}
566
+		}
567
+		//next additional attendee question groups
568
+		$orig_additional_qgs = $orig_event->get_many_related(
569
+			'Question_Group',
570
+			array(array('Event_Question_Group.EQG_primary' => 0))
571
+		);
572
+		if (! empty($orig_additional_qgs)) {
573
+			foreach ($orig_additional_qgs as $id => $obj) {
574
+				if ($obj instanceof EE_Question_Group) {
575
+					$new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 0));
576
+				}
577
+			}
578
+		}
579
+
580
+		$new_event->save();
581
+
582
+		//k now that we have the new event saved we can loop through the datetimes and start adding relations.
583
+		$cloned_tickets = array();
584
+		foreach ($orig_datetimes as $orig_dtt) {
585
+			if (! $orig_dtt instanceof EE_Datetime) {
586
+				continue;
587
+			}
588
+			$new_dtt   = clone $orig_dtt;
589
+			$orig_tkts = $orig_dtt->tickets();
590
+			//save new dtt then add to event
591
+			$new_dtt->set('DTT_ID', 0);
592
+			$new_dtt->set('DTT_sold', 0);
593
+			$new_dtt->set_reserved(0);
594
+			$new_dtt->save();
595
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
596
+			$new_event->save();
597
+			//now let's get the ticket relations setup.
598
+			foreach ((array)$orig_tkts as $orig_tkt) {
599
+				//it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
600
+				if (! $orig_tkt instanceof EE_Ticket) {
601
+					continue;
602
+				}
603
+				//is this ticket archived?  If it is then let's skip
604
+				if ($orig_tkt->get('TKT_deleted')) {
605
+					continue;
606
+				}
607
+				// does this original ticket already exist in the clone_tickets cache?
608
+				//  If so we'll just use the new ticket from it.
609
+				if (isset($cloned_tickets[$orig_tkt->ID()])) {
610
+					$new_tkt = $cloned_tickets[$orig_tkt->ID()];
611
+				} else {
612
+					$new_tkt = clone $orig_tkt;
613
+					//get relations on the $orig_tkt that we need to setup.
614
+					$orig_prices = $orig_tkt->prices();
615
+					$new_tkt->set('TKT_ID', 0);
616
+					$new_tkt->set('TKT_sold', 0);
617
+					$new_tkt->set('TKT_reserved', 0);
618
+					$new_tkt->save(); //make sure new ticket has ID.
619
+					//price relations on new ticket need to be setup.
620
+					foreach ($orig_prices as $orig_price) {
621
+						$new_price = clone $orig_price;
622
+						$new_price->set('PRC_ID', 0);
623
+						$new_price->save();
624
+						$new_tkt->_add_relation_to($new_price, 'Price');
625
+						$new_tkt->save();
626
+					}
627
+
628
+					do_action(
629
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
630
+						$orig_tkt,
631
+						$new_tkt,
632
+						$orig_prices,
633
+						$orig_event,
634
+						$orig_dtt,
635
+						$new_dtt
636
+					);
637
+				}
638
+				// k now we can add the new ticket as a relation to the new datetime
639
+				// and make sure its added to our cached $cloned_tickets array
640
+				// for use with later datetimes that have the same ticket.
641
+				$new_dtt->_add_relation_to($new_tkt, 'Ticket');
642
+				$new_dtt->save();
643
+				$cloned_tickets[$orig_tkt->ID()] = $new_tkt;
644
+			}
645
+		}
646
+		//clone taxonomy information
647
+		$taxonomies_to_clone_with = apply_filters(
648
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
649
+			array('espresso_event_categories', 'espresso_event_type', 'post_tag')
650
+		);
651
+		//get terms for original event (notice)
652
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
653
+		//loop through terms and add them to new event.
654
+		foreach ($orig_terms as $term) {
655
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
656
+		}
657
+
658
+		//duplicate other core WP_Post items for this event.
659
+		//post thumbnail (feature image).
660
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
661
+		if ($feature_image_id) {
662
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
663
+		}
664
+
665
+		//duplicate page_template setting
666
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
667
+		if ($page_template) {
668
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
669
+		}
670
+
671
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
672
+		//now let's redirect to the edit page for this duplicated event if we have a new event id.
673
+		if ($new_event->ID()) {
674
+			$redirect_args = array(
675
+				'post'   => $new_event->ID(),
676
+				'action' => 'edit',
677
+			);
678
+			EE_Error::add_success(
679
+				esc_html__(
680
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
681
+					'event_espresso'
682
+				)
683
+			);
684
+		} else {
685
+			$redirect_args = array(
686
+				'action' => 'default',
687
+			);
688
+			EE_Error::add_error(
689
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
690
+				__FILE__,
691
+				__FUNCTION__,
692
+				__LINE__
693
+			);
694
+		}
695
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
696
+	}
697
+
698
+
699
+	/**
700
+	 * Generates output for the import page.
701
+	 * @throws DomainException
702
+	 */
703
+	protected function _import_page()
704
+	{
705
+		$title                                      = esc_html__('Import', 'event_espresso');
706
+		$intro                                      = esc_html__(
707
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
708
+			'event_espresso'
709
+		);
710
+		$form_url                                   = EVENTS_ADMIN_URL;
711
+		$action                                     = 'import_events';
712
+		$type                                       = 'csv';
713
+		$this->_template_args['form']               = EE_Import::instance()->upload_form(
714
+			$title, $intro, $form_url, $action, $type
715
+		);
716
+		$this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
717
+			array('action' => 'sample_export_file'),
718
+			$this->_admin_base_url
719
+		);
720
+		$content                                    = EEH_Template::display_template(
721
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
722
+			$this->_template_args,
723
+			true
724
+		);
725
+		$this->_template_args['admin_page_content'] = $content;
726
+		$this->display_admin_page_with_sidebar();
727
+	}
728
+
729
+
730
+	/**
731
+	 * _import_events
732
+	 * This handles displaying the screen and running imports for importing events.
733
+	 *
734
+	 * @return void
735
+	 */
736
+	protected function _import_events()
737
+	{
738
+		require_once(EE_CLASSES . 'EE_Import.class.php');
739
+		$success = EE_Import::instance()->import();
740
+		$this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
741
+	}
742
+
743
+
744
+	/**
745
+	 * _events_export
746
+	 * Will export all (or just the given event) to a Excel compatible file.
747
+	 *
748
+	 * @access protected
749
+	 * @return void
750
+	 */
751
+	protected function _events_export()
752
+	{
753
+		if (isset($this->_req_data['EVT_ID'])) {
754
+			$event_ids = $this->_req_data['EVT_ID'];
755
+		} elseif (isset($this->_req_data['EVT_IDs'])) {
756
+			$event_ids = $this->_req_data['EVT_IDs'];
757
+		} else {
758
+			$event_ids = null;
759
+		}
760
+		//todo: I don't like doing this but it'll do until we modify EE_Export Class.
761
+		$new_request_args = array(
762
+			'export' => 'report',
763
+			'action' => 'all_event_data',
764
+			'EVT_ID' => $event_ids,
765
+		);
766
+		$this->_req_data  = array_merge($this->_req_data, $new_request_args);
767
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
768
+			require_once(EE_CLASSES . 'EE_Export.class.php');
769
+			$EE_Export = EE_Export::instance($this->_req_data);
770
+			$EE_Export->export();
771
+		}
772
+	}
773
+
774
+
775
+	/**
776
+	 * handle category exports()
777
+	 *
778
+	 * @return void
779
+	 */
780
+	protected function _categories_export()
781
+	{
782
+		//todo: I don't like doing this but it'll do until we modify EE_Export Class.
783
+		$new_request_args = array(
784
+			'export'       => 'report',
785
+			'action'       => 'categories',
786
+			'category_ids' => $this->_req_data['EVT_CAT_ID'],
787
+		);
788
+		$this->_req_data  = array_merge($this->_req_data, $new_request_args);
789
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
790
+			require_once(EE_CLASSES . 'EE_Export.class.php');
791
+			$EE_Export = EE_Export::instance($this->_req_data);
792
+			$EE_Export->export();
793
+		}
794
+	}
795
+
796
+
797
+	/**
798
+	 * Creates a sample CSV file for importing
799
+	 */
800
+	protected function _sample_export_file()
801
+	{
802
+		//		require_once(EE_CLASSES . 'EE_Export.class.php');
803
+		EE_Export::instance()->export_sample();
804
+	}
805
+
806
+
807
+	/*************        Template Settings        *************/
808
+	/**
809
+	 * Generates template settings page output
810
+	 * @throws DomainException
811
+	 * @throws EE_Error
812
+	 */
813
+	protected function _template_settings()
814
+	{
815
+		$this->_template_args['values'] = $this->_yes_no_values;
816
+		/**
817
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
818
+		 * from General_Settings_Admin_Page to here.
819
+		 */
820
+		$this->_template_args = apply_filters(
821
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
822
+			$this->_template_args
823
+		);
824
+		$this->_set_add_edit_form_tags('update_template_settings');
825
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
826
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
827
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
828
+			$this->_template_args,
829
+			true
830
+		);
831
+		$this->display_admin_page_with_sidebar();
832
+	}
833
+
834
+
835
+	/**
836
+	 * Handler for updating template settings.
837
+	 */
838
+	protected function _update_template_settings()
839
+	{
840
+		/**
841
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
842
+		 * from General_Settings_Admin_Page to here.
843
+		 */
844
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
845
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
846
+			EE_Registry::instance()->CFG->template_settings,
847
+			$this->_req_data
848
+		);
849
+		//update custom post type slugs and detect if we need to flush rewrite rules
850
+		$old_slug                                          = EE_Registry::instance()->CFG->core->event_cpt_slug;
851
+		EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
852
+			? EE_Registry::instance()->CFG->core->event_cpt_slug
853
+			: sanitize_title_with_dashes($this->_req_data['event_cpt_slug']);
854
+		$what                                              = 'Template Settings';
855
+		$success                                           = $this->_update_espresso_configuration(
856
+			$what,
857
+			EE_Registry::instance()->CFG->template_settings,
858
+			__FILE__,
859
+			__FUNCTION__,
860
+			__LINE__
861
+		);
862
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
863
+			update_option('ee_flush_rewrite_rules', true);
864
+		}
865
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
866
+	}
867
+
868
+
869
+	/**
870
+	 * _premium_event_editor_meta_boxes
871
+	 * add all metaboxes related to the event_editor
872
+	 *
873
+	 * @access protected
874
+	 * @return void
875
+	 * @throws EE_Error
876
+	 */
877
+	protected function _premium_event_editor_meta_boxes()
878
+	{
879
+		$this->verify_cpt_object();
880
+		add_meta_box(
881
+			'espresso_event_editor_event_options',
882
+			esc_html__('Event Registration Options', 'event_espresso'),
883
+			array($this, 'registration_options_meta_box'),
884
+			$this->page_slug,
885
+			'side',
886
+			'core'
887
+		);
888
+	}
889
+
890
+
891
+	/**
892
+	 * override caf metabox
893
+	 *
894
+	 * @return void
895
+	 * @throws DomainException
896
+	 */
897
+	public function registration_options_meta_box()
898
+	{
899
+		$yes_no_values                                    = array(
900
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
901
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
902
+		);
903
+		$default_reg_status_values                        = EEM_Registration::reg_status_array(
904
+			array(
905
+				EEM_Registration::status_id_cancelled,
906
+				EEM_Registration::status_id_declined,
907
+				EEM_Registration::status_id_incomplete,
908
+				EEM_Registration::status_id_wait_list,
909
+			),
910
+			true
911
+		);
912
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
913
+		$template_args['_event']                          = $this->_cpt_model_obj;
914
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
915
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
916
+			'default_reg_status',
917
+			$default_reg_status_values,
918
+			$this->_cpt_model_obj->default_registration_status()
919
+		);
920
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
921
+			'display_desc',
922
+			$yes_no_values,
923
+			$this->_cpt_model_obj->display_description()
924
+		);
925
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
926
+			'display_ticket_selector',
927
+			$yes_no_values,
928
+			$this->_cpt_model_obj->display_ticket_selector(),
929
+			'',
930
+			'',
931
+			false
932
+		);
933
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
934
+			'EVT_default_registration_status',
935
+			$default_reg_status_values,
936
+			$this->_cpt_model_obj->default_registration_status()
937
+		);
938
+		$template_args['additional_registration_options'] = apply_filters(
939
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
940
+			'',
941
+			$template_args,
942
+			$yes_no_values,
943
+			$default_reg_status_values
944
+		);
945
+		EEH_Template::display_template(
946
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
947
+			$template_args
948
+		);
949
+	}
950
+
951
+
952
+
953
+	/**
954
+	 * wp_list_table_mods for caf
955
+	 * ============================
956
+	 */
957
+	/**
958
+	 * hook into list table filters and provide filters for caffeinated list table
959
+	 *
960
+	 * @param  array $old_filters    any existing filters present
961
+	 * @param  array $list_table_obj the list table object
962
+	 * @return array                  new filters
963
+	 */
964
+	public function list_table_filters($old_filters, $list_table_obj)
965
+	{
966
+		$filters = array();
967
+		//first month/year filters
968
+		$filters[] = $this->espresso_event_months_dropdown();
969
+		$status    = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
970
+		//active status dropdown
971
+		if ($status !== 'draft') {
972
+			$filters[] = $this->active_status_dropdown(
973
+				isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
974
+			);
975
+		}
976
+		//category filter
977
+		$filters[] = $this->category_dropdown();
978
+		return array_merge($old_filters, $filters);
979
+	}
980
+
981
+
982
+	/**
983
+	 * espresso_event_months_dropdown
984
+	 *
985
+	 * @access public
986
+	 * @return string                dropdown listing month/year selections for events.
987
+	 */
988
+	public function espresso_event_months_dropdown()
989
+	{
990
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
991
+		// Note we need to include any other filters that are set!
992
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
993
+		//categories?
994
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
995
+			? $this->_req_data['EVT_CAT']
996
+			: null;
997
+		//active status?
998
+		$active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
999
+		$cur_date      = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1000
+		return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * returns a list of "active" statuses on the event
1006
+	 *
1007
+	 * @param  string $current_value whatever the current active status is
1008
+	 * @return string
1009
+	 */
1010
+	public function active_status_dropdown($current_value = '')
1011
+	{
1012
+		$select_name = 'active_status';
1013
+		$values      = array(
1014
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1015
+			'active'   => esc_html__('Active', 'event_espresso'),
1016
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1017
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1018
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1019
+		);
1020
+		$id          = 'id="espresso-active-status-dropdown-filter"';
1021
+		$class       = 'wide';
1022
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * output a dropdown of the categories for the category filter on the event admin list table
1028
+	 *
1029
+	 * @access  public
1030
+	 * @return string html
1031
+	 */
1032
+	public function category_dropdown()
1033
+	{
1034
+		$cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1035
+		return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * get total number of events today
1041
+	 *
1042
+	 * @access public
1043
+	 * @return int
1044
+	 * @throws EE_Error
1045
+	 */
1046
+	public function total_events_today()
1047
+	{
1048
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1049
+			'DTT_EVT_start',
1050
+			date('Y-m-d') . ' 00:00:00',
1051
+			'Y-m-d H:i:s',
1052
+			'UTC'
1053
+		);
1054
+		$end   = EEM_Datetime::instance()->convert_datetime_for_query(
1055
+			'DTT_EVT_start',
1056
+			date('Y-m-d') . ' 23:59:59',
1057
+			'Y-m-d H:i:s',
1058
+			'UTC'
1059
+		);
1060
+		$where = array(
1061
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1062
+		);
1063
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1064
+		return $count;
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * get total number of events this month
1070
+	 *
1071
+	 * @access public
1072
+	 * @return int
1073
+	 * @throws EE_Error
1074
+	 */
1075
+	public function total_events_this_month()
1076
+	{
1077
+		//Dates
1078
+		$this_year_r     = date('Y');
1079
+		$this_month_r    = date('m');
1080
+		$days_this_month = date('t');
1081
+		$start           = EEM_Datetime::instance()->convert_datetime_for_query(
1082
+			'DTT_EVT_start',
1083
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1084
+			'Y-m-d H:i:s',
1085
+			'UTC'
1086
+		);
1087
+		$end             = EEM_Datetime::instance()->convert_datetime_for_query(
1088
+			'DTT_EVT_start',
1089
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1090
+			'Y-m-d H:i:s',
1091
+			'UTC'
1092
+		);
1093
+		$where           = array(
1094
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1095
+		);
1096
+		$count           = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1097
+		return $count;
1098
+	}
1099
+
1100
+
1101
+	/** DEFAULT TICKETS STUFF **/
1102
+
1103
+	/**
1104
+	 * Output default tickets list table view.
1105
+	 */
1106
+	public function _tickets_overview_list_table()
1107
+	{
1108
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1109
+		$this->display_admin_list_table_page_with_no_sidebar();
1110
+	}
1111
+
1112
+
1113
+	/**
1114
+	 * @param int  $per_page
1115
+	 * @param bool $count
1116
+	 * @param bool $trashed
1117
+	 * @return \EE_Soft_Delete_Base_Class[]|int
1118
+	 */
1119
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1120
+	{
1121
+		$orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1122
+		$order   = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1123
+		switch ($orderby) {
1124
+			case 'TKT_name':
1125
+				$orderby = array('TKT_name' => $order);
1126
+				break;
1127
+			case 'TKT_price':
1128
+				$orderby = array('TKT_price' => $order);
1129
+				break;
1130
+			case 'TKT_uses':
1131
+				$orderby = array('TKT_uses' => $order);
1132
+				break;
1133
+			case 'TKT_min':
1134
+				$orderby = array('TKT_min' => $order);
1135
+				break;
1136
+			case 'TKT_max':
1137
+				$orderby = array('TKT_max' => $order);
1138
+				break;
1139
+			case 'TKT_qty':
1140
+				$orderby = array('TKT_qty' => $order);
1141
+				break;
1142
+		}
1143
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1144
+			? $this->_req_data['paged']
1145
+			: 1;
1146
+		$per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1147
+			? $this->_req_data['perpage']
1148
+			: $per_page;
1149
+		$_where       = array(
1150
+			'TKT_is_default' => 1,
1151
+			'TKT_deleted'    => $trashed,
1152
+		);
1153
+		$offset       = ($current_page - 1) * $per_page;
1154
+		$limit        = array($offset, $per_page);
1155
+		if (isset($this->_req_data['s'])) {
1156
+			$sstr         = '%' . $this->_req_data['s'] . '%';
1157
+			$_where['OR'] = array(
1158
+				'TKT_name'        => array('LIKE', $sstr),
1159
+				'TKT_description' => array('LIKE', $sstr),
1160
+			);
1161
+		}
1162
+		$query_params = array(
1163
+			$_where,
1164
+			'order_by' => $orderby,
1165
+			'limit'    => $limit,
1166
+			'group_by' => 'TKT_ID',
1167
+		);
1168
+		if ($count) {
1169
+			return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1170
+		} else {
1171
+			return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1172
+		}
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * @param bool $trash
1178
+	 * @throws EE_Error
1179
+	 */
1180
+	protected function _trash_or_restore_ticket($trash = false)
1181
+	{
1182
+		$success = 1;
1183
+		$TKT     = EEM_Ticket::instance();
1184
+		//checkboxes?
1185
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1186
+			//if array has more than one element then success message should be plural
1187
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1188
+			//cycle thru the boxes
1189
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1190
+				if ($trash) {
1191
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1192
+						$success = 0;
1193
+					}
1194
+				} else {
1195
+					if (! $TKT->restore_by_ID($TKT_ID)) {
1196
+						$success = 0;
1197
+					}
1198
+				}
1199
+			}
1200
+		} else {
1201
+			//grab single id and trash
1202
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1203
+			if ($trash) {
1204
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1205
+					$success = 0;
1206
+				}
1207
+			} else {
1208
+				if (! $TKT->restore_by_ID($TKT_ID)) {
1209
+					$success = 0;
1210
+				}
1211
+			}
1212
+		}
1213
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1214
+		$query_args  = array(
1215
+			'action' => 'ticket_list_table',
1216
+			'status' => $trash ? '' : 'trashed',
1217
+		);
1218
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1219
+	}
1220
+
1221
+
1222
+	/**
1223
+	 * Handles trashing default ticket.
1224
+	 */
1225
+	protected function _delete_ticket()
1226
+	{
1227
+		$success = 1;
1228
+		//checkboxes?
1229
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1230
+			//if array has more than one element then success message should be plural
1231
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1232
+			//cycle thru the boxes
1233
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1234
+				//delete
1235
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1236
+					$success = 0;
1237
+				}
1238
+			}
1239
+		} else {
1240
+			//grab single id and trash
1241
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1242
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1243
+				$success = 0;
1244
+			}
1245
+		}
1246
+		$action_desc = 'deleted';
1247
+		$query_args  = array(
1248
+			'action' => 'ticket_list_table',
1249
+			'status' => 'trashed',
1250
+		);
1251
+		//fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1252
+		if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1253
+			array(array('TKT_is_default' => 1)),
1254
+			'TKT_ID',
1255
+			true
1256
+		)
1257
+		) {
1258
+			$query_args = array();
1259
+		}
1260
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1261
+	}
1262
+
1263
+
1264
+	/**
1265
+	 * @param int $TKT_ID
1266
+	 * @return bool|int
1267
+	 * @throws EE_Error
1268
+	 */
1269
+	protected function _delete_the_ticket($TKT_ID)
1270
+	{
1271
+		$tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1272
+		$tkt->_remove_relations('Datetime');
1273
+		//delete all related prices first
1274
+		$tkt->delete_related_permanently('Price');
1275
+		return $tkt->delete_permanently();
1276
+	}
1277 1277
 }
Please login to merge, or discard this patch.
core/EE_Request_Handler.core.php 1 patch
Spacing   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\interfaces\InterminableInterface;
2 2
 
3
-if ( ! defined( 'EVENT_ESPRESSO_VERSION')) {exit('No direct script access allowed');}
3
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {exit('No direct script access allowed'); }
4 4
 /**
5 5
  * class EE_Request_Handler
6 6
  *
@@ -51,13 +51,13 @@  discard block
 block discarded – undo
51 51
 	 * @access public
52 52
 	 * @param  EE_Request $request
53 53
 	 */
54
-	public function __construct( EE_Request $request ) {
54
+	public function __construct(EE_Request $request) {
55 55
 		// grab request vars
56 56
 		$this->_params = $request->params();
57 57
 		// AJAX ???
58
-		$this->ajax = defined( 'DOING_AJAX' ) && DOING_AJAX ? true : false;
59
-		$this->front_ajax = defined( 'EE_FRONT_AJAX' ) && EE_FRONT_AJAX ? true : false;
60
-		do_action( 'AHEE__EE_Request_Handler__construct__complete' );
58
+		$this->ajax = defined('DOING_AJAX') && DOING_AJAX ? true : false;
59
+		$this->front_ajax = defined('EE_FRONT_AJAX') && EE_FRONT_AJAX ? true : false;
60
+		do_action('AHEE__EE_Request_Handler__construct__complete');
61 61
 	}
62 62
 
63 63
 
@@ -69,12 +69,12 @@  discard block
 block discarded – undo
69 69
 	 * @param WP $wp
70 70
 	 * @return void
71 71
 	 */
72
-	public function parse_request( $wp = null ) {
72
+	public function parse_request($wp = null) {
73 73
 		//if somebody forgot to provide us with WP, that's ok because its global
74
-		if ( ! $wp instanceof WP ) {
74
+		if ( ! $wp instanceof WP) {
75 75
 			global $wp;
76 76
 		}
77
-		$this->set_request_vars( $wp );
77
+		$this->set_request_vars($wp);
78 78
 	}
79 79
 
80 80
 
@@ -86,14 +86,14 @@  discard block
 block discarded – undo
86 86
 	 * @param WP $wp
87 87
 	 * @return void
88 88
 	 */
89
-	public function set_request_vars( $wp = null ) {
90
-		if ( ! is_admin() ) {
89
+	public function set_request_vars($wp = null) {
90
+		if ( ! is_admin()) {
91 91
 			// set request post_id
92
-			$this->set( 'post_id', $this->get_post_id_from_request( $wp ));
92
+			$this->set('post_id', $this->get_post_id_from_request($wp));
93 93
 			// set request post name
94
-			$this->set( 'post_name', $this->get_post_name_from_request( $wp ));
94
+			$this->set('post_name', $this->get_post_name_from_request($wp));
95 95
 			// set request post_type
96
-			$this->set( 'post_type', $this->get_post_type_from_request( $wp ));
96
+			$this->set('post_type', $this->get_post_type_from_request($wp));
97 97
 			// true or false ? is this page being used by EE ?
98 98
 			$this->set_espresso_page();
99 99
 		}
@@ -108,19 +108,19 @@  discard block
 block discarded – undo
108 108
 	 * @param WP $wp
109 109
 	 * @return int
110 110
 	 */
111
-	public function get_post_id_from_request( $wp = null ) {
112
-		if ( ! $wp instanceof WP ){
111
+	public function get_post_id_from_request($wp = null) {
112
+		if ( ! $wp instanceof WP) {
113 113
 			global $wp;
114 114
 		}
115 115
 		$post_id = null;
116
-		if ( isset( $wp->query_vars['p'] )) {
116
+		if (isset($wp->query_vars['p'])) {
117 117
 			$post_id = $wp->query_vars['p'];
118 118
 		}
119
-		if ( ! $post_id && isset( $wp->query_vars['page_id'] )) {
119
+		if ( ! $post_id && isset($wp->query_vars['page_id'])) {
120 120
 			$post_id = $wp->query_vars['page_id'];
121 121
 		}
122
-		if ( ! $post_id && isset( $wp->request ) && is_numeric( basename( $wp->request ))) {
123
-			$post_id = basename( $wp->request );
122
+		if ( ! $post_id && isset($wp->request) && is_numeric(basename($wp->request))) {
123
+			$post_id = basename($wp->request);
124 124
 		}
125 125
 		return $post_id;
126 126
 	}
@@ -134,35 +134,35 @@  discard block
 block discarded – undo
134 134
 	 * @param WP $wp
135 135
 	 * @return string
136 136
 	 */
137
-	public function get_post_name_from_request( $wp = null ) {
138
-		if ( ! $wp instanceof WP ){
137
+	public function get_post_name_from_request($wp = null) {
138
+		if ( ! $wp instanceof WP) {
139 139
 			global $wp;
140 140
 		}
141 141
 		$post_name = null;
142
-		if ( isset( $wp->query_vars['name'] ) && ! empty( $wp->query_vars['name'] )) {
142
+		if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
143 143
 			$post_name = $wp->query_vars['name'];
144 144
 		}
145
-		if ( ! $post_name && isset( $wp->query_vars['pagename'] ) && ! empty( $wp->query_vars['pagename'] )) {
145
+		if ( ! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
146 146
 			$post_name = $wp->query_vars['pagename'];
147 147
 		}
148
-		if ( ! $post_name && isset( $wp->request ) && ! empty( $wp->request )) {
149
-			$possible_post_name = basename( $wp->request );
150
-			if ( ! is_numeric( $possible_post_name )) {
148
+		if ( ! $post_name && isset($wp->request) && ! empty($wp->request)) {
149
+			$possible_post_name = basename($wp->request);
150
+			if ( ! is_numeric($possible_post_name)) {
151 151
 				/** @type WPDB $wpdb */
152 152
 				global $wpdb;
153 153
 				$SQL = "SELECT ID from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s";
154
-				$possible_post_name = $wpdb->get_var( $wpdb->prepare( $SQL, $possible_post_name ));
155
-				if ( $possible_post_name ) {
154
+				$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
155
+				if ($possible_post_name) {
156 156
 					$post_name = $possible_post_name;
157 157
 				}
158 158
 			}
159 159
 		}
160
-		if ( ! $post_name && $this->get( 'post_id' )) {
160
+		if ( ! $post_name && $this->get('post_id')) {
161 161
 			/** @type WPDB $wpdb */
162 162
 			global $wpdb;
163 163
 			$SQL = "SELECT post_name from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d";
164
-			$possible_post_name = $wpdb->get_var( $wpdb->prepare( $SQL, $this->get( 'post_id' )));
165
-			if( $possible_post_name ) {
164
+			$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->get('post_id')));
165
+			if ($possible_post_name) {
166 166
 				$post_name = $possible_post_name;
167 167
 			}
168 168
 		}
@@ -178,11 +178,11 @@  discard block
 block discarded – undo
178 178
 	 * @param WP $wp
179 179
 	 * @return mixed
180 180
 	 */
181
-	public function get_post_type_from_request( $wp = null ) {
182
-		if ( ! $wp instanceof WP ){
181
+	public function get_post_type_from_request($wp = null) {
182
+		if ( ! $wp instanceof WP) {
183 183
 			global $wp;
184 184
 		}
185
-		return isset( $wp->query_vars['post_type'] ) ? $wp->query_vars['post_type'] : null;
185
+		return isset($wp->query_vars['post_type']) ? $wp->query_vars['post_type'] : null;
186 186
 	}
187 187
 
188 188
 
@@ -192,18 +192,18 @@  discard block
 block discarded – undo
192 192
 	 * @param  WP $wp
193 193
 	 * @return string
194 194
 	 */
195
-	public function get_current_page_permalink( $wp = null ) {
196
-		$post_id = $this->get_post_id_from_request( $wp );
197
-		if ( $post_id ) {
198
-			$current_page_permalink = get_permalink( $post_id );
195
+	public function get_current_page_permalink($wp = null) {
196
+		$post_id = $this->get_post_id_from_request($wp);
197
+		if ($post_id) {
198
+			$current_page_permalink = get_permalink($post_id);
199 199
 		} else {
200
-			if ( ! $wp instanceof WP ) {
200
+			if ( ! $wp instanceof WP) {
201 201
 				global $wp;
202 202
 			}
203
-			if ( $wp->request ) {
204
-				$current_page_permalink = site_url( $wp->request );
203
+			if ($wp->request) {
204
+				$current_page_permalink = site_url($wp->request);
205 205
 			} else {
206
-				$current_page_permalink = esc_url( site_url( $_SERVER[ 'REQUEST_URI' ] ) );
206
+				$current_page_permalink = esc_url(site_url($_SERVER['REQUEST_URI']));
207 207
 			}
208 208
 		}
209 209
 		return $current_page_permalink;
@@ -220,31 +220,31 @@  discard block
 block discarded – undo
220 220
 	public function test_for_espresso_page() {
221 221
 		global $wp;
222 222
 		/** @type EE_CPT_Strategy $EE_CPT_Strategy */
223
-		$EE_CPT_Strategy = EE_Registry::instance()->load_core( 'CPT_Strategy' );
223
+		$EE_CPT_Strategy = EE_Registry::instance()->load_core('CPT_Strategy');
224 224
 		$espresso_CPT_taxonomies = $EE_CPT_Strategy->get_CPT_taxonomies();
225
-		if ( is_array( $espresso_CPT_taxonomies ) ) {
226
-			foreach ( $espresso_CPT_taxonomies as $espresso_CPT_taxonomy =>$details ) {
227
-				if ( isset( $wp->query_vars, $wp->query_vars[ $espresso_CPT_taxonomy ] ) ) {
225
+		if (is_array($espresso_CPT_taxonomies)) {
226
+			foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy =>$details) {
227
+				if (isset($wp->query_vars, $wp->query_vars[$espresso_CPT_taxonomy])) {
228 228
 					return true;
229 229
 				}
230 230
 			}
231 231
 		}
232 232
 		// load espresso CPT endpoints
233 233
 		$espresso_CPT_endpoints = $EE_CPT_Strategy->get_CPT_endpoints();
234
-		$post_type_CPT_endpoints = array_flip( $espresso_CPT_endpoints );
235
-		$post_types = (array)$this->get( 'post_type' );
236
-		foreach ( $post_types as $post_type ) {
234
+		$post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
235
+		$post_types = (array) $this->get('post_type');
236
+		foreach ($post_types as $post_type) {
237 237
 			// was a post name passed ?
238
-			if ( isset( $post_type_CPT_endpoints[ $post_type ] ) ) {
238
+			if (isset($post_type_CPT_endpoints[$post_type])) {
239 239
 				// kk we know this is an espresso page, but is it a specific post ?
240
-				if ( ! $this->get( 'post_name' ) ) {
240
+				if ( ! $this->get('post_name')) {
241 241
 					// there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
242
-					$post_name = isset( $post_type_CPT_endpoints[ $this->get( 'post_type' ) ] )
243
-                        ? $post_type_CPT_endpoints[ $this->get( 'post_type' ) ]
242
+					$post_name = isset($post_type_CPT_endpoints[$this->get('post_type')])
243
+                        ? $post_type_CPT_endpoints[$this->get('post_type')]
244 244
                         : '';
245 245
 					// if the post type matches on of our then set the endpoint
246
-					if ( $post_name ) {
247
-						$this->set( 'post_name', $post_name );
246
+					if ($post_name) {
247
+						$this->set('post_name', $post_name);
248 248
 					}
249 249
 				}
250 250
 				return true;
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
 	 * @param null|bool $value
263 263
 	 * @return    void
264 264
 	 */
265
-	public function set_espresso_page( $value = null ) {
265
+	public function set_espresso_page($value = null) {
266 266
         $this->_params['is_espresso_page'] = ! empty($value) ? $value : $this->test_for_espresso_page();
267 267
 	}
268 268
 
@@ -275,7 +275,7 @@  discard block
 block discarded – undo
275 275
 	 *  @return 	mixed
276 276
 	 */
277 277
 	public function is_espresso_page() {
278
-		return isset( $this->_params['is_espresso_page'] ) ? $this->_params['is_espresso_page'] : false;
278
+		return isset($this->_params['is_espresso_page']) ? $this->_params['is_espresso_page'] : false;
279 279
 	}
280 280
 
281 281
 
@@ -299,14 +299,14 @@  discard block
 block discarded – undo
299 299
 	 * @param bool $override_ee
300 300
 	 * @return    void
301 301
 	 */
302
-	public function set( $key, $value, $override_ee = false ) {
302
+	public function set($key, $value, $override_ee = false) {
303 303
 		// don't allow "ee" to be overwritten unless explicitly instructed to do so
304 304
 		if (
305 305
 			$key !== 'ee' ||
306
-			( $key === 'ee' && empty( $this->_params['ee'] ))
307
-			|| ( $key === 'ee' && ! empty( $this->_params['ee'] ) && $override_ee )
306
+			($key === 'ee' && empty($this->_params['ee']))
307
+			|| ($key === 'ee' && ! empty($this->_params['ee']) && $override_ee)
308 308
 		) {
309
-			$this->_params[ $key ] = $value;
309
+			$this->_params[$key] = $value;
310 310
 		}
311 311
 	}
312 312
 
@@ -320,8 +320,8 @@  discard block
 block discarded – undo
320 320
 	 * @param null $default
321 321
 	 * @return    mixed
322 322
 	 */
323
-	public function get( $key, $default = null ) {
324
-		return isset( $this->_params[ $key ] ) ? $this->_params[ $key ] : $default;
323
+	public function get($key, $default = null) {
324
+		return isset($this->_params[$key]) ? $this->_params[$key] : $default;
325 325
 	}
326 326
 
327 327
 
@@ -333,8 +333,8 @@  discard block
 block discarded – undo
333 333
 	 * @param $key
334 334
 	 * @return    boolean
335 335
 	 */
336
-	public function is_set( $key ) {
337
-		return isset( $this->_params[ $key ] ) ? true : false;
336
+	public function is_set($key) {
337
+		return isset($this->_params[$key]) ? true : false;
338 338
 	}
339 339
 
340 340
 
@@ -346,8 +346,8 @@  discard block
 block discarded – undo
346 346
 	 * @param $key
347 347
 	 * @return    void
348 348
 	 */
349
-	public function un_set( $key ) {
350
-		unset( $this->_params[ $key ] );
349
+	public function un_set($key) {
350
+		unset($this->_params[$key]);
351 351
 	}
352 352
 
353 353
 
@@ -360,8 +360,8 @@  discard block
 block discarded – undo
360 360
 	 * @param $value
361 361
 	 * @return    void
362 362
 	 */
363
-	public function set_notice( $key, $value ) {
364
-		$this->_notice[ $key ] = $value;
363
+	public function set_notice($key, $value) {
364
+		$this->_notice[$key] = $value;
365 365
 	}
366 366
 
367 367
 
@@ -373,8 +373,8 @@  discard block
 block discarded – undo
373 373
 	 * @param $key
374 374
 	 * @return    mixed
375 375
 	 */
376
-	public function get_notice( $key ) {
377
-		return isset( $this->_notice[ $key ] ) ? $this->_notice[ $key ] : null;
376
+	public function get_notice($key) {
377
+		return isset($this->_notice[$key]) ? $this->_notice[$key] : null;
378 378
 	}
379 379
 
380 380
 
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
 	 * @param $string
387 387
 	 * @return    void
388 388
 	 */
389
-	public function add_output( $string ) {
389
+	public function add_output($string) {
390 390
 		$this->_output .= $string;
391 391
 	}
392 392
 
@@ -408,8 +408,8 @@  discard block
 block discarded – undo
408 408
 	 * @param $item
409 409
 	 * @param $key
410 410
 	 */
411
-	public function sanitize_text_field_for_array_walk( &$item, &$key ) {
412
-		$item = strpos( $item, 'email' ) !== false ? sanitize_email( $item ) : sanitize_text_field( $item );
411
+	public function sanitize_text_field_for_array_walk(&$item, &$key) {
412
+		$item = strpos($item, 'email') !== false ? sanitize_email($item) : sanitize_text_field($item);
413 413
 	}
414 414
 
415 415
 
@@ -419,7 +419,7 @@  discard block
 block discarded – undo
419 419
 	 * @param $b
420 420
 	 * @return bool
421 421
 	 */
422
-	public function __set($a,$b) { return false; }
422
+	public function __set($a, $b) { return false; }
423 423
 
424 424
 
425 425
 
Please login to merge, or discard this patch.
core/EE_Module_Request_Router.core.php 2 patches
Indentation   +307 added lines, -307 removed lines patch added patch discarded remove patch
@@ -17,316 +17,316 @@
 block discarded – undo
17 17
 final class EE_Module_Request_Router implements InterminableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var array $_previous_routes
22
-     */
23
-    private static $_previous_routes = array();
24
-
25
-    /**
26
-     * @var WP_Query $WP_Query
27
-     */
28
-    public $WP_Query;
29
-
30
-
31
-
32
-    /**
33
-     * EE_Module_Request_Router constructor.
34
-     */
35
-    public function __construct()
36
-    {
37
-    }
38
-
39
-
40
-
41
-    /**
42
-     * on the first call  to this method, it checks the EE_Request_Handler for a "route"
43
-     * on subsequent calls to this method,
44
-     * instead of checking the EE_Request_Handler for a route, it checks the previous routes array,
45
-     * and checks if the last called route has any forwarding routes registered for it
46
-     *
47
-     * @param WP_Query $WP_Query
48
-     * @return NULL|string
49
-     * @throws EE_Error
50
-     * @throws ReflectionException
51
-     */
52
-    public function get_route(WP_Query $WP_Query)
53
-    {
54
-        $this->WP_Query = $WP_Query;
55
-        // assume this if first route being called
56
-        $previous_route = false;
57
-        // but is it really ???
58
-        if (! empty(self::$_previous_routes)) {
59
-            // get last run route
60
-            $previous_routes = array_values(self::$_previous_routes);
61
-            $previous_route = array_pop($previous_routes);
62
-        }
63
-        //  has another route already been run ?
64
-        if ($previous_route) {
65
-            // check if  forwarding has been set
66
-            $current_route = $this->get_forward($previous_route);
67
-            try {
68
-                //check for recursive forwarding
69
-                if (isset(self::$_previous_routes[$current_route])) {
70
-                    throw new EE_Error(
71
-                        sprintf(
72
-                            __(
73
-                                'An error occurred. The %s route has already been called, and therefore can not be forwarded to, because an infinite loop would be created and break the interweb.',
74
-                                'event_espresso'
75
-                            ),
76
-                            $current_route
77
-                        )
78
-                    );
79
-                }
80
-            } catch (EE_Error $e) {
81
-                $e->get_error();
82
-                return null;
83
-            }
84
-        } else {
85
-            // first route called
86
-            $current_route = null;
87
-            // grab all routes
88
-            $routes = EE_Config::get_routes();
89
-            //d( $routes );
90
-            foreach ($routes as $key => $route) {
91
-                // check request for module route
92
-                if (EE_Registry::instance()->REQ->is_set($key)) {
93
-                    //echo '<b style="color:#2EA2CC;">key : <span style="color:#E76700">' . $key . '</span></b><br />';
94
-                    $current_route = sanitize_text_field(EE_Registry::instance()->REQ->get($key));
95
-                    if ($current_route) {
96
-                        $current_route = array($key, $current_route);
97
-                        //echo '<b style="color:#2EA2CC;">current_route : <span style="color:#E76700">' . $current_route . '</span></b><br />';
98
-                        break;
99
-                    }
100
-                }
101
-            }
102
-        }
103
-        // sorry, but I can't read what you route !
104
-        if (empty($current_route)) {
105
-            return null;
106
-        }
107
-        //add route to previous routes array
108
-        self::$_previous_routes[] = $current_route;
109
-        return $current_route;
110
-    }
111
-
112
-
113
-
114
-    /**
115
-     * this method simply takes a valid route, and resolves what module class method the route points to
116
-     *
117
-     * @param string $key
118
-     * @param string $current_route
119
-     * @return mixed EED_Module | boolean
120
-     * @throws EE_Error
121
-     * @throws ReflectionException
122
-     */
123
-    public function resolve_route($key, $current_route)
124
-    {
125
-        // get module method that route has been mapped to
126
-        $module_method = EE_Config::get_route($current_route, $key);
127
-        //EEH_Debug_Tools::printr( $module_method, '$module_method  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
128
-        // verify result was returned
129
-        if (empty($module_method)) {
130
-            $msg = sprintf(
131
-                __('The requested route %s could not be mapped to any registered modules.', 'event_espresso'),
132
-                $current_route
133
-            );
134
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
135
-            return false;
136
-        }
137
-        // verify that result is an array
138
-        if (! is_array($module_method)) {
139
-            $msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
140
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
141
-            return false;
142
-        }
143
-        // grab module name
144
-        $module_name = $module_method[0];
145
-        // verify that a class method was registered properly
146
-        if (! isset($module_method[1])) {
147
-            $msg = sprintf(
148
-                __('A class method for the %s  route has not been properly registered.', 'event_espresso'),
149
-                $current_route
150
-            );
151
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
152
-            return false;
153
-        }
154
-        // grab method
155
-        $method = $module_method[1];
156
-        // verify that class exists
157
-        if (! class_exists($module_name)) {
158
-            $msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
159
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
160
-            return false;
161
-        }
162
-        // verify that method exists
163
-        if (! method_exists($module_name, $method)) {
164
-            $msg = sprintf(
165
-                __('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
166
-            );
167
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
168
-            return false;
169
-        }
170
-        // instantiate module and call route method
171
-        return $this->_module_router($module_name, $method);
172
-    }
173
-
174
-
175
-
176
-    /**
177
-     * this method instantiates modules and calls the method that was defined when the route was registered
178
-     *
179
-     * @param string $module_name
180
-     * @return EED_Module|object|null
181
-     * @throws ReflectionException
182
-     */
183
-    public static function module_factory($module_name)
184
-    {
185
-        if ($module_name === 'EED_Module') {
186
-            EE_Error::add_error(
187
-                sprintf(
188
-                    __(
189
-                        'EED_Module is an abstract parent class an can not be instantiated. Please provide a proper module name.',
190
-                        'event_espresso'
191
-                    ), $module_name
192
-                ), __FILE__, __FUNCTION__, __LINE__
193
-            );
194
-            return null;
195
-        }
196
-        // let's pause to reflect on this...
197
-        $mod_reflector = new ReflectionClass($module_name);
198
-        // ensure that class is actually a module
199
-        if (! $mod_reflector->isSubclassOf('EED_Module')) {
200
-            EE_Error::add_error(
201
-                sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
202
-                __FILE__, __FUNCTION__, __LINE__
203
-            );
204
-            return null;
205
-        }
206
-        // instantiate and return module class
207
-        return $mod_reflector->newInstance();
208
-    }
209
-
210
-
211
-
212
-    /**
213
-     * this method instantiates modules and calls the method that was defined when the route was registered
214
-     *
215
-     * @param string $module_name
216
-     * @param string $method
217
-     * @return EED_Module|null
218
-     * @throws EE_Error
219
-     * @throws ReflectionException
220
-     */
221
-    private function _module_router($module_name, $method)
222
-    {
223
-        // instantiate module class
224
-        $module = EE_Module_Request_Router::module_factory($module_name);
225
-        if ($module instanceof EED_Module) {
226
-            // and call whatever action the route was for
227
-            try {
228
-                call_user_func(array($module, $method), $this->WP_Query);
229
-            } catch (EE_Error $e) {
230
-                $e->get_error();
231
-                return null;
232
-            }
233
-        }
234
-        return $module;
235
-    }
236
-
237
-
238
-
239
-    /**
240
-     * @param $current_route
241
-     * @return string
242
-     */
243
-    public function get_forward($current_route)
244
-    {
245
-        return EE_Config::get_forward($current_route);
246
-    }
247
-
248
-
249
-
250
-    /**
251
-     * @param $current_route
252
-     * @return string
253
-     */
254
-    public function get_view($current_route)
255
-    {
256
-        return EE_Config::get_view($current_route);
257
-    }
258
-
259
-
260
-
261
-    /**
262
-     * @param $a
263
-     * @param $b
264
-     * @return bool
265
-     */
266
-    public function __set($a, $b)
267
-    {
268
-        return false;
269
-    }
270
-
271
-
272
-
273
-    /**
274
-     * @param $a
275
-     * @return bool
276
-     */
277
-    public function __get($a)
278
-    {
279
-        return false;
280
-    }
281
-
282
-
283
-
284
-    /**
285
-     * @param $a
286
-     * @return bool
287
-     */
288
-    public function __isset($a)
289
-    {
290
-        return false;
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     * @param $a
297
-     * @return bool
298
-     */
299
-    public function __unset($a)
300
-    {
301
-        return false;
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @return void
308
-     */
309
-    public function __clone()
310
-    {
311
-    }
312
-
313
-
314
-
315
-    /**
316
-     * @return void
317
-     */
318
-    public function __wakeup()
319
-    {
320
-    }
20
+	/**
21
+	 * @var array $_previous_routes
22
+	 */
23
+	private static $_previous_routes = array();
24
+
25
+	/**
26
+	 * @var WP_Query $WP_Query
27
+	 */
28
+	public $WP_Query;
29
+
30
+
31
+
32
+	/**
33
+	 * EE_Module_Request_Router constructor.
34
+	 */
35
+	public function __construct()
36
+	{
37
+	}
38
+
39
+
40
+
41
+	/**
42
+	 * on the first call  to this method, it checks the EE_Request_Handler for a "route"
43
+	 * on subsequent calls to this method,
44
+	 * instead of checking the EE_Request_Handler for a route, it checks the previous routes array,
45
+	 * and checks if the last called route has any forwarding routes registered for it
46
+	 *
47
+	 * @param WP_Query $WP_Query
48
+	 * @return NULL|string
49
+	 * @throws EE_Error
50
+	 * @throws ReflectionException
51
+	 */
52
+	public function get_route(WP_Query $WP_Query)
53
+	{
54
+		$this->WP_Query = $WP_Query;
55
+		// assume this if first route being called
56
+		$previous_route = false;
57
+		// but is it really ???
58
+		if (! empty(self::$_previous_routes)) {
59
+			// get last run route
60
+			$previous_routes = array_values(self::$_previous_routes);
61
+			$previous_route = array_pop($previous_routes);
62
+		}
63
+		//  has another route already been run ?
64
+		if ($previous_route) {
65
+			// check if  forwarding has been set
66
+			$current_route = $this->get_forward($previous_route);
67
+			try {
68
+				//check for recursive forwarding
69
+				if (isset(self::$_previous_routes[$current_route])) {
70
+					throw new EE_Error(
71
+						sprintf(
72
+							__(
73
+								'An error occurred. The %s route has already been called, and therefore can not be forwarded to, because an infinite loop would be created and break the interweb.',
74
+								'event_espresso'
75
+							),
76
+							$current_route
77
+						)
78
+					);
79
+				}
80
+			} catch (EE_Error $e) {
81
+				$e->get_error();
82
+				return null;
83
+			}
84
+		} else {
85
+			// first route called
86
+			$current_route = null;
87
+			// grab all routes
88
+			$routes = EE_Config::get_routes();
89
+			//d( $routes );
90
+			foreach ($routes as $key => $route) {
91
+				// check request for module route
92
+				if (EE_Registry::instance()->REQ->is_set($key)) {
93
+					//echo '<b style="color:#2EA2CC;">key : <span style="color:#E76700">' . $key . '</span></b><br />';
94
+					$current_route = sanitize_text_field(EE_Registry::instance()->REQ->get($key));
95
+					if ($current_route) {
96
+						$current_route = array($key, $current_route);
97
+						//echo '<b style="color:#2EA2CC;">current_route : <span style="color:#E76700">' . $current_route . '</span></b><br />';
98
+						break;
99
+					}
100
+				}
101
+			}
102
+		}
103
+		// sorry, but I can't read what you route !
104
+		if (empty($current_route)) {
105
+			return null;
106
+		}
107
+		//add route to previous routes array
108
+		self::$_previous_routes[] = $current_route;
109
+		return $current_route;
110
+	}
111
+
112
+
113
+
114
+	/**
115
+	 * this method simply takes a valid route, and resolves what module class method the route points to
116
+	 *
117
+	 * @param string $key
118
+	 * @param string $current_route
119
+	 * @return mixed EED_Module | boolean
120
+	 * @throws EE_Error
121
+	 * @throws ReflectionException
122
+	 */
123
+	public function resolve_route($key, $current_route)
124
+	{
125
+		// get module method that route has been mapped to
126
+		$module_method = EE_Config::get_route($current_route, $key);
127
+		//EEH_Debug_Tools::printr( $module_method, '$module_method  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
128
+		// verify result was returned
129
+		if (empty($module_method)) {
130
+			$msg = sprintf(
131
+				__('The requested route %s could not be mapped to any registered modules.', 'event_espresso'),
132
+				$current_route
133
+			);
134
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
135
+			return false;
136
+		}
137
+		// verify that result is an array
138
+		if (! is_array($module_method)) {
139
+			$msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
140
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
141
+			return false;
142
+		}
143
+		// grab module name
144
+		$module_name = $module_method[0];
145
+		// verify that a class method was registered properly
146
+		if (! isset($module_method[1])) {
147
+			$msg = sprintf(
148
+				__('A class method for the %s  route has not been properly registered.', 'event_espresso'),
149
+				$current_route
150
+			);
151
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
152
+			return false;
153
+		}
154
+		// grab method
155
+		$method = $module_method[1];
156
+		// verify that class exists
157
+		if (! class_exists($module_name)) {
158
+			$msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
159
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
160
+			return false;
161
+		}
162
+		// verify that method exists
163
+		if (! method_exists($module_name, $method)) {
164
+			$msg = sprintf(
165
+				__('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
166
+			);
167
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
168
+			return false;
169
+		}
170
+		// instantiate module and call route method
171
+		return $this->_module_router($module_name, $method);
172
+	}
173
+
174
+
175
+
176
+	/**
177
+	 * this method instantiates modules and calls the method that was defined when the route was registered
178
+	 *
179
+	 * @param string $module_name
180
+	 * @return EED_Module|object|null
181
+	 * @throws ReflectionException
182
+	 */
183
+	public static function module_factory($module_name)
184
+	{
185
+		if ($module_name === 'EED_Module') {
186
+			EE_Error::add_error(
187
+				sprintf(
188
+					__(
189
+						'EED_Module is an abstract parent class an can not be instantiated. Please provide a proper module name.',
190
+						'event_espresso'
191
+					), $module_name
192
+				), __FILE__, __FUNCTION__, __LINE__
193
+			);
194
+			return null;
195
+		}
196
+		// let's pause to reflect on this...
197
+		$mod_reflector = new ReflectionClass($module_name);
198
+		// ensure that class is actually a module
199
+		if (! $mod_reflector->isSubclassOf('EED_Module')) {
200
+			EE_Error::add_error(
201
+				sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
202
+				__FILE__, __FUNCTION__, __LINE__
203
+			);
204
+			return null;
205
+		}
206
+		// instantiate and return module class
207
+		return $mod_reflector->newInstance();
208
+	}
209
+
210
+
211
+
212
+	/**
213
+	 * this method instantiates modules and calls the method that was defined when the route was registered
214
+	 *
215
+	 * @param string $module_name
216
+	 * @param string $method
217
+	 * @return EED_Module|null
218
+	 * @throws EE_Error
219
+	 * @throws ReflectionException
220
+	 */
221
+	private function _module_router($module_name, $method)
222
+	{
223
+		// instantiate module class
224
+		$module = EE_Module_Request_Router::module_factory($module_name);
225
+		if ($module instanceof EED_Module) {
226
+			// and call whatever action the route was for
227
+			try {
228
+				call_user_func(array($module, $method), $this->WP_Query);
229
+			} catch (EE_Error $e) {
230
+				$e->get_error();
231
+				return null;
232
+			}
233
+		}
234
+		return $module;
235
+	}
236
+
237
+
238
+
239
+	/**
240
+	 * @param $current_route
241
+	 * @return string
242
+	 */
243
+	public function get_forward($current_route)
244
+	{
245
+		return EE_Config::get_forward($current_route);
246
+	}
247
+
248
+
249
+
250
+	/**
251
+	 * @param $current_route
252
+	 * @return string
253
+	 */
254
+	public function get_view($current_route)
255
+	{
256
+		return EE_Config::get_view($current_route);
257
+	}
258
+
259
+
260
+
261
+	/**
262
+	 * @param $a
263
+	 * @param $b
264
+	 * @return bool
265
+	 */
266
+	public function __set($a, $b)
267
+	{
268
+		return false;
269
+	}
270
+
271
+
272
+
273
+	/**
274
+	 * @param $a
275
+	 * @return bool
276
+	 */
277
+	public function __get($a)
278
+	{
279
+		return false;
280
+	}
281
+
282
+
283
+
284
+	/**
285
+	 * @param $a
286
+	 * @return bool
287
+	 */
288
+	public function __isset($a)
289
+	{
290
+		return false;
291
+	}
292
+
293
+
294
+
295
+	/**
296
+	 * @param $a
297
+	 * @return bool
298
+	 */
299
+	public function __unset($a)
300
+	{
301
+		return false;
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @return void
308
+	 */
309
+	public function __clone()
310
+	{
311
+	}
312
+
313
+
314
+
315
+	/**
316
+	 * @return void
317
+	 */
318
+	public function __wakeup()
319
+	{
320
+	}
321 321
 
322 322
 
323 323
 
324
-    /**
325
-     *
326
-     */
327
-    public function __destruct()
328
-    {
329
-    }
324
+	/**
325
+	 *
326
+	 */
327
+	public function __destruct()
328
+	{
329
+	}
330 330
 
331 331
 }
332 332
 // End of file EE_Module_Request_Router.core.php
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@  discard block
 block discarded – undo
55 55
         // assume this if first route being called
56 56
         $previous_route = false;
57 57
         // but is it really ???
58
-        if (! empty(self::$_previous_routes)) {
58
+        if ( ! empty(self::$_previous_routes)) {
59 59
             // get last run route
60 60
             $previous_routes = array_values(self::$_previous_routes);
61 61
             $previous_route = array_pop($previous_routes);
@@ -135,36 +135,36 @@  discard block
 block discarded – undo
135 135
             return false;
136 136
         }
137 137
         // verify that result is an array
138
-        if (! is_array($module_method)) {
138
+        if ( ! is_array($module_method)) {
139 139
             $msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
140
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
140
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
141 141
             return false;
142 142
         }
143 143
         // grab module name
144 144
         $module_name = $module_method[0];
145 145
         // verify that a class method was registered properly
146
-        if (! isset($module_method[1])) {
146
+        if ( ! isset($module_method[1])) {
147 147
             $msg = sprintf(
148 148
                 __('A class method for the %s  route has not been properly registered.', 'event_espresso'),
149 149
                 $current_route
150 150
             );
151
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
151
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
152 152
             return false;
153 153
         }
154 154
         // grab method
155 155
         $method = $module_method[1];
156 156
         // verify that class exists
157
-        if (! class_exists($module_name)) {
157
+        if ( ! class_exists($module_name)) {
158 158
             $msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
159 159
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
160 160
             return false;
161 161
         }
162 162
         // verify that method exists
163
-        if (! method_exists($module_name, $method)) {
163
+        if ( ! method_exists($module_name, $method)) {
164 164
             $msg = sprintf(
165 165
                 __('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
166 166
             );
167
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
167
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
168 168
             return false;
169 169
         }
170 170
         // instantiate module and call route method
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
         // let's pause to reflect on this...
197 197
         $mod_reflector = new ReflectionClass($module_name);
198 198
         // ensure that class is actually a module
199
-        if (! $mod_reflector->isSubclassOf('EED_Module')) {
199
+        if ( ! $mod_reflector->isSubclassOf('EED_Module')) {
200 200
             EE_Error::add_error(
201 201
                 sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
202 202
                 __FILE__, __FUNCTION__, __LINE__
Please login to merge, or discard this patch.
core/EE_Cart.core.php 1 patch
Indentation   +413 added lines, -413 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\interfaces\ResettableInterface;
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
 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
8 8
 
@@ -23,418 +23,418 @@  discard block
 block discarded – undo
23 23
 class EE_Cart implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * instance of the EE_Cart object
28
-     *
29
-     * @access    private
30
-     * @var EE_Cart $_instance
31
-     */
32
-    private static $_instance;
33
-
34
-    /**
35
-     * instance of the EE_Session object
36
-     *
37
-     * @access    protected
38
-     * @var EE_Session $_session
39
-     */
40
-    protected $_session;
41
-
42
-    /**
43
-     * The total Line item which comprises all the children line-item subtotals,
44
-     * which in turn each have their line items.
45
-     * Typically, the line item structure will look like:
46
-     * grand total
47
-     * -tickets-sub-total
48
-     * --ticket1
49
-     * --ticket2
50
-     * --...
51
-     * -taxes-sub-total
52
-     * --tax1
53
-     * --tax2
54
-     *
55
-     * @var EE_Line_Item
56
-     */
57
-    private $_grand_total;
58
-
59
-
60
-
61
-    /**
62
-     * @singleton method used to instantiate class object
63
-     * @access    public
64
-     * @param EE_Line_Item $grand_total
65
-     * @param EE_Session   $session
66
-     * @return \EE_Cart
67
-     * @throws \EE_Error
68
-     */
69
-    public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null)
70
-    {
71
-        if ( ! empty($grand_total)) {
72
-            self::$_instance = new self($grand_total, $session);
73
-        }
74
-        // or maybe retrieve an existing one ?
75
-        if ( ! self::$_instance instanceof EE_Cart) {
76
-            // try getting the cart out of the session
77
-            $saved_cart = $session instanceof EE_Session ? $session->cart() : null;
78
-            self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
79
-            unset($saved_cart);
80
-        }
81
-        // verify that cart is ok and grand total line item exists
82
-        if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
83
-            self::$_instance = new self($grand_total, $session);
84
-        }
85
-        self::$_instance->get_grand_total();
86
-        // once everything is all said and done, save the cart to the EE_Session
87
-        add_action('shutdown', array(self::$_instance, 'save_cart'), 90);
88
-        return self::$_instance;
89
-    }
90
-
91
-
92
-
93
-    /**
94
-     * private constructor to prevent direct creation
95
-     *
96
-     * @Constructor
97
-     * @access private
98
-     * @param EE_Line_Item $grand_total
99
-     * @param EE_Session   $session
100
-     */
101
-    private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null)
102
-    {
103
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
104
-        $this->set_session($session);
105
-        if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
106
-            $this->set_grand_total_line_item($grand_total);
107
-        }
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * Resets the cart completely (whereas empty_cart
114
-     *
115
-     * @param EE_Line_Item $grand_total
116
-     * @param EE_Session   $session
117
-     * @return EE_Cart
118
-     * @throws \EE_Error
119
-     */
120
-    public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null)
121
-    {
122
-        remove_action('shutdown', array(self::$_instance, 'save_cart'), 90);
123
-        if ($session instanceof EE_Session) {
124
-            $session->reset_cart();
125
-        }
126
-        self::$_instance = null;
127
-        return self::instance($grand_total, $session);
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     * @return \EE_Session
134
-     */
135
-    public function session()
136
-    {
137
-        if ( ! $this->_session instanceof EE_Session) {
138
-            $this->set_session();
139
-        }
140
-        return $this->_session;
141
-    }
142
-
143
-
144
-
145
-    /**
146
-     * @param EE_Session $session
147
-     */
148
-    public function set_session(EE_Session $session = null)
149
-    {
150
-        $this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * Sets the cart to match the line item. Especially handy for loading an old cart where you
157
-     *  know the grand total line item on it
158
-     *
159
-     * @param EE_Line_Item $line_item
160
-     */
161
-    public function set_grand_total_line_item(EE_Line_Item $line_item)
162
-    {
163
-        $this->_grand_total = $line_item;
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * get_cart_from_reg_url_link
170
-     *
171
-     * @access public
172
-     * @param EE_Transaction $transaction
173
-     * @param EE_Session     $session
174
-     * @return \EE_Cart
175
-     * @throws \EE_Error
176
-     */
177
-    public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null)
178
-    {
179
-        $grand_total = $transaction->total_line_item();
180
-        $grand_total->get_items();
181
-        $grand_total->tax_descendants();
182
-        return EE_Cart::instance($grand_total, $session);
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
189
-     *
190
-     * @return EE_Line_Item
191
-     * @throws \EE_Error
192
-     */
193
-    private function _create_grand_total()
194
-    {
195
-        $this->_grand_total = EEH_Line_Item::create_total_line_item();
196
-        return $this->_grand_total;
197
-    }
198
-
199
-
200
-
201
-    /**
202
-     * Gets all the line items of object type Ticket
203
-     *
204
-     * @access public
205
-     * @return \EE_Line_Item[]
206
-     */
207
-    public function get_tickets()
208
-    {
209
-        if ($this->_grand_total === null ) {
210
-            return array();
211
-        }
212
-        return EEH_Line_Item::get_ticket_line_items($this->_grand_total);
213
-    }
214
-
215
-
216
-
217
-    /**
218
-     * returns the total quantity of tickets in the cart
219
-     *
220
-     * @access public
221
-     * @return int
222
-     * @throws \EE_Error
223
-     */
224
-    public function all_ticket_quantity_count()
225
-    {
226
-        $tickets = $this->get_tickets();
227
-        if (empty($tickets)) {
228
-            return 0;
229
-        }
230
-        $count = 0;
231
-        foreach ($tickets as $ticket) {
232
-            $count += $ticket->get('LIN_quantity');
233
-        }
234
-        return $count;
235
-    }
236
-
237
-
238
-
239
-    /**
240
-     * Gets all the tax line items
241
-     *
242
-     * @return \EE_Line_Item[]
243
-     * @throws \EE_Error
244
-     */
245
-    public function get_taxes()
246
-    {
247
-        return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children();
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * Gets the total line item (which is a parent of all other line items) on this cart
254
-     *
255
-     * @return EE_Line_Item
256
-     * @throws \EE_Error
257
-     */
258
-    public function get_grand_total()
259
-    {
260
-        return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total();
261
-    }
262
-
263
-
264
-
265
-    /**
266
-     * @process items for adding to cart
267
-     * @access  public
268
-     * @param EE_Ticket $ticket
269
-     * @param int       $qty
270
-     * @return TRUE on success, FALSE on fail
271
-     * @throws \EE_Error
272
-     */
273
-    public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
274
-    {
275
-        EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty);
276
-        return $this->save_cart() ? true : false;
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * get_cart_total_before_tax
283
-     *
284
-     * @access public
285
-     * @return float
286
-     * @throws \EE_Error
287
-     */
288
-    public function get_cart_total_before_tax()
289
-    {
290
-        return $this->get_grand_total()->recalculate_pre_tax_total();
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     * gets the total amount of tax paid for items in this cart
297
-     *
298
-     * @access public
299
-     * @return float
300
-     * @throws \EE_Error
301
-     */
302
-    public function get_applied_taxes()
303
-    {
304
-        return EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
305
-    }
306
-
307
-
308
-
309
-    /**
310
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
311
-     *
312
-     * @access public
313
-     * @return float
314
-     * @throws \EE_Error
315
-     */
316
-    public function get_cart_grand_total()
317
-    {
318
-        EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
319
-        return $this->get_grand_total()->total();
320
-    }
321
-
322
-
323
-
324
-    /**
325
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
326
-     *
327
-     * @access public
328
-     * @return float
329
-     * @throws \EE_Error
330
-     */
331
-    public function recalculate_all_cart_totals()
332
-    {
333
-        $pre_tax_total = $this->get_cart_total_before_tax();
334
-        $taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
335
-        $this->_grand_total->set_total($pre_tax_total + $taxes_total);
336
-        $this->_grand_total->save_this_and_descendants_to_txn();
337
-        return $this->get_grand_total()->total();
338
-    }
339
-
340
-
341
-
342
-    /**
343
-     * deletes an item from the cart
344
-     *
345
-     * @access public
346
-     * @param array|bool|string $line_item_codes
347
-     * @return int on success, FALSE on fail
348
-     * @throws \EE_Error
349
-     */
350
-    public function delete_items($line_item_codes = false)
351
-    {
352
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
353
-        return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * @remove ALL items from cart and zero ALL totals
360
-     * @access public
361
-     * @return bool
362
-     * @throws \EE_Error
363
-     */
364
-    public function empty_cart()
365
-    {
366
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
367
-        $this->_grand_total = $this->_create_grand_total();
368
-        return $this->save_cart(true);
369
-    }
370
-
371
-
372
-
373
-    /**
374
-     * @remove ALL items from cart and delete total as well
375
-     * @access public
376
-     * @return bool
377
-     * @throws \EE_Error
378
-     */
379
-    public function delete_cart()
380
-    {
381
-        $deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total);
382
-        if ($deleted) {
383
-            $deleted += $this->_grand_total->delete();
384
-            $this->_grand_total = null;
385
-        }
386
-        return $deleted;
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     * @save   cart to session
393
-     * @access public
394
-     * @param bool $apply_taxes
395
-     * @return TRUE on success, FALSE on fail
396
-     * @throws \EE_Error
397
-     */
398
-    public function save_cart($apply_taxes = true)
399
-    {
400
-        if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) {
401
-            EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
402
-            //make sure we don't cache the transaction because it can get stale
403
-            if ($this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
404
-                && $this->_grand_total->get_one_from_cache('Transaction')->ID()
405
-            ) {
406
-                $this->_grand_total->clear_cache('Transaction', null, true);
407
-            }
408
-        }
409
-        if ($this->session() instanceof EE_Session) {
410
-            return $this->session()->set_cart($this);
411
-        } else {
412
-            return false;
413
-        }
414
-    }
415
-
416
-
417
-
418
-    public function __wakeup()
419
-    {
420
-        if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
421
-            // $this->_grand_total is actually just an ID, so use it to get the object from the db
422
-            $this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total);
423
-        }
424
-    }
425
-
426
-
427
-
428
-    /**
429
-     * @return array
430
-     */
431
-    public function __sleep()
432
-    {
433
-        if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) {
434
-            $this->_grand_total = $this->_grand_total->ID();
435
-        }
436
-        return array('_grand_total');
437
-    }
26
+	/**
27
+	 * instance of the EE_Cart object
28
+	 *
29
+	 * @access    private
30
+	 * @var EE_Cart $_instance
31
+	 */
32
+	private static $_instance;
33
+
34
+	/**
35
+	 * instance of the EE_Session object
36
+	 *
37
+	 * @access    protected
38
+	 * @var EE_Session $_session
39
+	 */
40
+	protected $_session;
41
+
42
+	/**
43
+	 * The total Line item which comprises all the children line-item subtotals,
44
+	 * which in turn each have their line items.
45
+	 * Typically, the line item structure will look like:
46
+	 * grand total
47
+	 * -tickets-sub-total
48
+	 * --ticket1
49
+	 * --ticket2
50
+	 * --...
51
+	 * -taxes-sub-total
52
+	 * --tax1
53
+	 * --tax2
54
+	 *
55
+	 * @var EE_Line_Item
56
+	 */
57
+	private $_grand_total;
58
+
59
+
60
+
61
+	/**
62
+	 * @singleton method used to instantiate class object
63
+	 * @access    public
64
+	 * @param EE_Line_Item $grand_total
65
+	 * @param EE_Session   $session
66
+	 * @return \EE_Cart
67
+	 * @throws \EE_Error
68
+	 */
69
+	public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null)
70
+	{
71
+		if ( ! empty($grand_total)) {
72
+			self::$_instance = new self($grand_total, $session);
73
+		}
74
+		// or maybe retrieve an existing one ?
75
+		if ( ! self::$_instance instanceof EE_Cart) {
76
+			// try getting the cart out of the session
77
+			$saved_cart = $session instanceof EE_Session ? $session->cart() : null;
78
+			self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
79
+			unset($saved_cart);
80
+		}
81
+		// verify that cart is ok and grand total line item exists
82
+		if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
83
+			self::$_instance = new self($grand_total, $session);
84
+		}
85
+		self::$_instance->get_grand_total();
86
+		// once everything is all said and done, save the cart to the EE_Session
87
+		add_action('shutdown', array(self::$_instance, 'save_cart'), 90);
88
+		return self::$_instance;
89
+	}
90
+
91
+
92
+
93
+	/**
94
+	 * private constructor to prevent direct creation
95
+	 *
96
+	 * @Constructor
97
+	 * @access private
98
+	 * @param EE_Line_Item $grand_total
99
+	 * @param EE_Session   $session
100
+	 */
101
+	private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null)
102
+	{
103
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
104
+		$this->set_session($session);
105
+		if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
106
+			$this->set_grand_total_line_item($grand_total);
107
+		}
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * Resets the cart completely (whereas empty_cart
114
+	 *
115
+	 * @param EE_Line_Item $grand_total
116
+	 * @param EE_Session   $session
117
+	 * @return EE_Cart
118
+	 * @throws \EE_Error
119
+	 */
120
+	public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null)
121
+	{
122
+		remove_action('shutdown', array(self::$_instance, 'save_cart'), 90);
123
+		if ($session instanceof EE_Session) {
124
+			$session->reset_cart();
125
+		}
126
+		self::$_instance = null;
127
+		return self::instance($grand_total, $session);
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 * @return \EE_Session
134
+	 */
135
+	public function session()
136
+	{
137
+		if ( ! $this->_session instanceof EE_Session) {
138
+			$this->set_session();
139
+		}
140
+		return $this->_session;
141
+	}
142
+
143
+
144
+
145
+	/**
146
+	 * @param EE_Session $session
147
+	 */
148
+	public function set_session(EE_Session $session = null)
149
+	{
150
+		$this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * Sets the cart to match the line item. Especially handy for loading an old cart where you
157
+	 *  know the grand total line item on it
158
+	 *
159
+	 * @param EE_Line_Item $line_item
160
+	 */
161
+	public function set_grand_total_line_item(EE_Line_Item $line_item)
162
+	{
163
+		$this->_grand_total = $line_item;
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * get_cart_from_reg_url_link
170
+	 *
171
+	 * @access public
172
+	 * @param EE_Transaction $transaction
173
+	 * @param EE_Session     $session
174
+	 * @return \EE_Cart
175
+	 * @throws \EE_Error
176
+	 */
177
+	public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null)
178
+	{
179
+		$grand_total = $transaction->total_line_item();
180
+		$grand_total->get_items();
181
+		$grand_total->tax_descendants();
182
+		return EE_Cart::instance($grand_total, $session);
183
+	}
184
+
185
+
186
+
187
+	/**
188
+	 * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
189
+	 *
190
+	 * @return EE_Line_Item
191
+	 * @throws \EE_Error
192
+	 */
193
+	private function _create_grand_total()
194
+	{
195
+		$this->_grand_total = EEH_Line_Item::create_total_line_item();
196
+		return $this->_grand_total;
197
+	}
198
+
199
+
200
+
201
+	/**
202
+	 * Gets all the line items of object type Ticket
203
+	 *
204
+	 * @access public
205
+	 * @return \EE_Line_Item[]
206
+	 */
207
+	public function get_tickets()
208
+	{
209
+		if ($this->_grand_total === null ) {
210
+			return array();
211
+		}
212
+		return EEH_Line_Item::get_ticket_line_items($this->_grand_total);
213
+	}
214
+
215
+
216
+
217
+	/**
218
+	 * returns the total quantity of tickets in the cart
219
+	 *
220
+	 * @access public
221
+	 * @return int
222
+	 * @throws \EE_Error
223
+	 */
224
+	public function all_ticket_quantity_count()
225
+	{
226
+		$tickets = $this->get_tickets();
227
+		if (empty($tickets)) {
228
+			return 0;
229
+		}
230
+		$count = 0;
231
+		foreach ($tickets as $ticket) {
232
+			$count += $ticket->get('LIN_quantity');
233
+		}
234
+		return $count;
235
+	}
236
+
237
+
238
+
239
+	/**
240
+	 * Gets all the tax line items
241
+	 *
242
+	 * @return \EE_Line_Item[]
243
+	 * @throws \EE_Error
244
+	 */
245
+	public function get_taxes()
246
+	{
247
+		return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children();
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * Gets the total line item (which is a parent of all other line items) on this cart
254
+	 *
255
+	 * @return EE_Line_Item
256
+	 * @throws \EE_Error
257
+	 */
258
+	public function get_grand_total()
259
+	{
260
+		return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total();
261
+	}
262
+
263
+
264
+
265
+	/**
266
+	 * @process items for adding to cart
267
+	 * @access  public
268
+	 * @param EE_Ticket $ticket
269
+	 * @param int       $qty
270
+	 * @return TRUE on success, FALSE on fail
271
+	 * @throws \EE_Error
272
+	 */
273
+	public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
274
+	{
275
+		EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty);
276
+		return $this->save_cart() ? true : false;
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * get_cart_total_before_tax
283
+	 *
284
+	 * @access public
285
+	 * @return float
286
+	 * @throws \EE_Error
287
+	 */
288
+	public function get_cart_total_before_tax()
289
+	{
290
+		return $this->get_grand_total()->recalculate_pre_tax_total();
291
+	}
292
+
293
+
294
+
295
+	/**
296
+	 * gets the total amount of tax paid for items in this cart
297
+	 *
298
+	 * @access public
299
+	 * @return float
300
+	 * @throws \EE_Error
301
+	 */
302
+	public function get_applied_taxes()
303
+	{
304
+		return EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
305
+	}
306
+
307
+
308
+
309
+	/**
310
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
311
+	 *
312
+	 * @access public
313
+	 * @return float
314
+	 * @throws \EE_Error
315
+	 */
316
+	public function get_cart_grand_total()
317
+	{
318
+		EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
319
+		return $this->get_grand_total()->total();
320
+	}
321
+
322
+
323
+
324
+	/**
325
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
326
+	 *
327
+	 * @access public
328
+	 * @return float
329
+	 * @throws \EE_Error
330
+	 */
331
+	public function recalculate_all_cart_totals()
332
+	{
333
+		$pre_tax_total = $this->get_cart_total_before_tax();
334
+		$taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
335
+		$this->_grand_total->set_total($pre_tax_total + $taxes_total);
336
+		$this->_grand_total->save_this_and_descendants_to_txn();
337
+		return $this->get_grand_total()->total();
338
+	}
339
+
340
+
341
+
342
+	/**
343
+	 * deletes an item from the cart
344
+	 *
345
+	 * @access public
346
+	 * @param array|bool|string $line_item_codes
347
+	 * @return int on success, FALSE on fail
348
+	 * @throws \EE_Error
349
+	 */
350
+	public function delete_items($line_item_codes = false)
351
+	{
352
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
353
+		return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * @remove ALL items from cart and zero ALL totals
360
+	 * @access public
361
+	 * @return bool
362
+	 * @throws \EE_Error
363
+	 */
364
+	public function empty_cart()
365
+	{
366
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
367
+		$this->_grand_total = $this->_create_grand_total();
368
+		return $this->save_cart(true);
369
+	}
370
+
371
+
372
+
373
+	/**
374
+	 * @remove ALL items from cart and delete total as well
375
+	 * @access public
376
+	 * @return bool
377
+	 * @throws \EE_Error
378
+	 */
379
+	public function delete_cart()
380
+	{
381
+		$deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total);
382
+		if ($deleted) {
383
+			$deleted += $this->_grand_total->delete();
384
+			$this->_grand_total = null;
385
+		}
386
+		return $deleted;
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 * @save   cart to session
393
+	 * @access public
394
+	 * @param bool $apply_taxes
395
+	 * @return TRUE on success, FALSE on fail
396
+	 * @throws \EE_Error
397
+	 */
398
+	public function save_cart($apply_taxes = true)
399
+	{
400
+		if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) {
401
+			EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
402
+			//make sure we don't cache the transaction because it can get stale
403
+			if ($this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
404
+				&& $this->_grand_total->get_one_from_cache('Transaction')->ID()
405
+			) {
406
+				$this->_grand_total->clear_cache('Transaction', null, true);
407
+			}
408
+		}
409
+		if ($this->session() instanceof EE_Session) {
410
+			return $this->session()->set_cart($this);
411
+		} else {
412
+			return false;
413
+		}
414
+	}
415
+
416
+
417
+
418
+	public function __wakeup()
419
+	{
420
+		if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
421
+			// $this->_grand_total is actually just an ID, so use it to get the object from the db
422
+			$this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total);
423
+		}
424
+	}
425
+
426
+
427
+
428
+	/**
429
+	 * @return array
430
+	 */
431
+	public function __sleep()
432
+	{
433
+		if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) {
434
+			$this->_grand_total = $this->_grand_total->ID();
435
+		}
436
+		return array('_grand_total');
437
+	}
438 438
 
439 439
 
440 440
 }
Please login to merge, or discard this patch.
core/EE_Payment_Processor.core.php 1 patch
Indentation   +745 added lines, -745 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\interfaces\ResettableInterface;
2 2
 
3 3
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 
7 7
 
@@ -17,748 +17,748 @@  discard block
 block discarded – undo
17 17
 class EE_Payment_Processor extends EE_Processor_Base implements ResettableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var EE_Payment_Processor $_instance
22
-     * @access    private
23
-     */
24
-    private static $_instance;
25
-
26
-
27
-
28
-    /**
29
-     * @singleton method used to instantiate class object
30
-     * @access    public
31
-     * @return EE_Payment_Processor instance
32
-     */
33
-    public static function instance()
34
-    {
35
-        // check if class object is instantiated
36
-        if ( ! self::$_instance instanceof EE_Payment_Processor) {
37
-            self::$_instance = new self();
38
-        }
39
-        return self::$_instance;
40
-    }
41
-
42
-
43
-
44
-    /**
45
-     * @return EE_Payment_Processor
46
-     */
47
-    public static function reset()
48
-    {
49
-        self::$_instance = null;
50
-        return self::instance();
51
-    }
52
-
53
-
54
-
55
-    /**
56
-     *private constructor to prevent direct creation
57
-     *
58
-     * @Constructor
59
-     * @access private
60
-     */
61
-    private function __construct()
62
-    {
63
-        do_action('AHEE__EE_Payment_Processor__construct');
64
-        add_action('http_api_curl', array($this, '_curl_requests_to_paypal_use_tls'), 10, 3);
65
-    }
66
-
67
-
68
-
69
-    /**
70
-     * Using the selected gateway, processes the payment for that transaction, and updates the transaction
71
-     * appropriately. Saves the payment that is generated
72
-     *
73
-     * @param EE_Payment_Method    $payment_method
74
-     * @param EE_Transaction       $transaction
75
-     * @param float                $amount       if only part of the transaction is to be paid for, how much.
76
-     *                                           Leave null if payment is for the full amount owing
77
-     * @param EE_Billing_Info_Form $billing_form (or probably null, if it's an offline or offsite payment method).
78
-     *                                           Receive_form_submission() should have
79
-     *                                           already been called on the billing form
80
-     *                                           (ie, its inputs should have their normalized values set).
81
-     * @param string               $return_url   string used mostly by offsite gateways to specify
82
-     *                                           where to go AFTER the offsite gateway
83
-     * @param string               $method       like 'CART', indicates who the client who called this was
84
-     * @param bool                 $by_admin     TRUE if payment is being attempted from the admin
85
-     * @param boolean              $update_txn   whether or not to call
86
-     *                                           EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
87
-     * @param string               $cancel_url   URL to return to if off-site payments are cancelled
88
-     * @return \EE_Payment
89
-     * @throws \EE_Error
90
-     */
91
-    public function process_payment(
92
-        EE_Payment_Method $payment_method,
93
-        EE_Transaction $transaction,
94
-        $amount = null,
95
-        $billing_form = null,
96
-        $return_url = null,
97
-        $method = 'CART',
98
-        $by_admin = false,
99
-        $update_txn = true,
100
-        $cancel_url = ''
101
-    ) {
102
-        if ((float)$amount < 0) {
103
-            throw new EE_Error(
104
-                sprintf(
105
-                    __(
106
-                        'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
107
-                        'event_espresso'
108
-                    ),
109
-                    $amount,
110
-                    $transaction->ID()
111
-                )
112
-            );
113
-        }
114
-        // verify payment method
115
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
116
-        // verify transaction
117
-        EEM_Transaction::instance()->ensure_is_obj($transaction);
118
-        $transaction->set_payment_method_ID($payment_method->ID());
119
-        // verify payment method type
120
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
121
-            $payment = $payment_method->type_obj()->process_payment(
122
-                $transaction,
123
-                min($amount, $transaction->remaining()),//make sure we don't overcharge
124
-                $billing_form,
125
-                $return_url,
126
-                add_query_arg(array('ee_cancel_payment' => true), $cancel_url),
127
-                $method,
128
-                $by_admin
129
-            );
130
-            // check if payment method uses an off-site gateway
131
-            if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
132
-                // don't process payments for off-site gateways yet because no payment has occurred yet
133
-                $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
134
-            }
135
-            return $payment;
136
-        } else {
137
-            EE_Error::add_error(
138
-                sprintf(
139
-                    __('A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.', 'event_espresso'),
140
-                    '<br/>',
141
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
142
-                ), __FILE__, __FUNCTION__, __LINE__
143
-            );
144
-            return null;
145
-        }
146
-    }
147
-
148
-
149
-
150
-    /**
151
-     * @param EE_Transaction|int $transaction
152
-     * @param EE_Payment_Method  $payment_method
153
-     * @throws EE_Error
154
-     * @return string
155
-     */
156
-    public function get_ipn_url_for_payment_method($transaction, $payment_method)
157
-    {
158
-        /** @type \EE_Transaction $transaction */
159
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
160
-        $primary_reg = $transaction->primary_registration();
161
-        if ( ! $primary_reg instanceof EE_Registration) {
162
-            throw new EE_Error(
163
-                sprintf(
164
-                    __(
165
-                        "Cannot get IPN URL for transaction with ID %d because it has no primary registration",
166
-                        "event_espresso"
167
-                    ),
168
-                    $transaction->ID()
169
-                )
170
-            );
171
-        }
172
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
173
-        $url = add_query_arg(
174
-            array(
175
-                'e_reg_url_link'    => $primary_reg->reg_url_link(),
176
-                'ee_payment_method' => $payment_method->slug(),
177
-            ),
178
-            EE_Registry::instance()->CFG->core->txn_page_url()
179
-        );
180
-        return $url;
181
-    }
182
-
183
-
184
-
185
-    /**
186
-     * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
187
-     * we can easily find what registration the IPN is for and what payment method.
188
-     * However, if not, we'll give all payment methods a chance to claim it and process it.
189
-     * If a payment is found for the IPN info, it is saved.
190
-     *
191
-     * @param array              $_req_data            eg $_REQUEST
192
-     * @param EE_Transaction|int $transaction          optional (or a transactions id)
193
-     * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
194
-     * @param boolean            $update_txn           whether or not to call
195
-     *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
196
-     * @param bool               $separate_IPN_request whether the IPN uses a separate request ( true like PayPal )
197
-     *                                                 or is processed manually ( false like Mijireh )
198
-     * @throws EE_Error
199
-     * @throws Exception
200
-     * @return EE_Payment
201
-     */
202
-    public function process_ipn(
203
-        $_req_data,
204
-        $transaction = null,
205
-        $payment_method = null,
206
-        $update_txn = true,
207
-        $separate_IPN_request = true
208
-    ) {
209
-        EE_Registry::instance()->load_model('Change_Log');
210
-        $_req_data = $this->_remove_unusable_characters_from_array((array)$_req_data);
211
-        EE_Processor_Base::set_IPN($separate_IPN_request);
212
-        $obj_for_log = null;
213
-        if ($transaction instanceof EE_Transaction) {
214
-            $obj_for_log = $transaction;
215
-            if ($payment_method instanceof EE_Payment_Method) {
216
-                $obj_for_log = EEM_Payment::instance()->get_one(
217
-                    array(
218
-                        array('TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()),
219
-                        'order_by' => array('PAY_timestamp' => 'desc'),
220
-                    )
221
-                );
222
-            }
223
-        } else if ($payment_method instanceof EE_Payment) {
224
-            $obj_for_log = $payment_method;
225
-        }
226
-        $log = EEM_Change_Log::instance()->log(
227
-            EEM_Change_Log::type_gateway,
228
-            array('IPN data received' => $_req_data),
229
-            $obj_for_log
230
-        );
231
-        try {
232
-            /**
233
-             * @var EE_Payment $payment
234
-             */
235
-            $payment = null;
236
-            if ($transaction && $payment_method) {
237
-                /** @type EE_Transaction $transaction */
238
-                $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
239
-                /** @type EE_Payment_Method $payment_method */
240
-                $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
241
-                if ($payment_method->type_obj() instanceof EE_PMT_Base) {
242
-                    try {
243
-                        $payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
244
-                        $log->set_object($payment);
245
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
246
-                        EEM_Change_Log::instance()->log(
247
-                            EEM_Change_Log::type_gateway,
248
-                            array(
249
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
250
-                                'current_url' => EEH_URL::current_url(),
251
-                                'payment'     => $e->getPaymentProperties(),
252
-                                'IPN_data'    => $e->getIpnData(),
253
-                            ),
254
-                            $obj_for_log
255
-                        );
256
-                        return $e->getPayment();
257
-                    }
258
-                } else {
259
-                    // not a payment
260
-                    EE_Error::add_error(
261
-                        sprintf(
262
-                            __('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'),
263
-                            '<br/>',
264
-                            EE_Registry::instance()->CFG->organization->get_pretty('email')
265
-                        ),
266
-                        __FILE__, __FUNCTION__, __LINE__
267
-                    );
268
-                }
269
-            } else {
270
-                //that's actually pretty ok. The IPN just wasn't able
271
-                //to identify which transaction or payment method this was for
272
-                // give all active payment methods a chance to claim it
273
-                $active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
274
-                foreach ($active_payment_methods as $active_payment_method) {
275
-                    try {
276
-                        $payment = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
277
-                        $payment_method = $active_payment_method;
278
-                        EEM_Change_Log::instance()->log(
279
-                            EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment
280
-                        );
281
-                        break;
282
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
283
-                        EEM_Change_Log::instance()->log(
284
-                            EEM_Change_Log::type_gateway,
285
-                            array(
286
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
287
-                                'current_url' => EEH_URL::current_url(),
288
-                                'payment'     => $e->getPaymentProperties(),
289
-                                'IPN_data'    => $e->getIpnData(),
290
-                            ),
291
-                            $obj_for_log
292
-                        );
293
-                        return $e->getPayment();
294
-                    } catch (EE_Error $e) {
295
-                        //that's fine- it apparently couldn't handle the IPN
296
-                    }
297
-                }
298
-            }
299
-            // 			EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
300
-            if ($payment instanceof EE_Payment) {
301
-                $payment->save();
302
-                //  update the TXN
303
-                $this->update_txn_based_on_payment($transaction, $payment, $update_txn, $separate_IPN_request);
304
-            } else {
305
-                //we couldn't find the payment for this IPN... let's try and log at least SOMETHING
306
-                if ($payment_method) {
307
-                    EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment_method);
308
-                } elseif ($transaction) {
309
-                    EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $transaction);
310
-                }
311
-            }
312
-            return $payment;
313
-        } catch (EE_Error $e) {
314
-            do_action(
315
-                'AHEE__log', __FILE__, __FUNCTION__, sprintf(
316
-                    __('Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"', 'event_espresso'),
317
-                    print_r($transaction, true),
318
-                    print_r($_req_data, true),
319
-                    $e->getMessage()
320
-                )
321
-            );
322
-            throw $e;
323
-        }
324
-    }
325
-
326
-
327
-
328
-    /**
329
-     * Removes any non-printable illegal characters from the input,
330
-     * which might cause a raucous when trying to insert into the database
331
-     *
332
-     * @param  array $request_data
333
-     * @return array
334
-     */
335
-    protected function _remove_unusable_characters_from_array(array $request_data)
336
-    {
337
-        $return_data = array();
338
-        foreach ($request_data as $key => $value) {
339
-            $return_data[$this->_remove_unusable_characters($key)] = $this->_remove_unusable_characters($value);
340
-        }
341
-        return $return_data;
342
-    }
343
-
344
-
345
-
346
-    /**
347
-     * Removes any non-printable illegal characters from the input,
348
-     * which might cause a raucous when trying to insert into the database
349
-     *
350
-     * @param string $request_data
351
-     * @return string
352
-     */
353
-    protected function _remove_unusable_characters($request_data)
354
-    {
355
-        return preg_replace('/[^[:print:]]/', '', $request_data);
356
-    }
357
-
358
-
359
-
360
-    /**
361
-     * Should be called just before displaying the payment attempt results to the user,
362
-     * when the payment attempt has finished. Some payment methods may have special
363
-     * logic to perform here. For example, if process_payment() happens on a special request
364
-     * and then the user is redirected to a page that displays the payment's status, this
365
-     * should be called while loading the page that displays the payment's status. If the user is
366
-     * sent to an offsite payment provider, this should be called upon returning from that offsite payment
367
-     * provider.
368
-     *
369
-     * @param EE_Transaction|int $transaction
370
-     * @param bool               $update_txn whether or not to call
371
-     *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
372
-     * @throws \EE_Error
373
-     * @return EE_Payment
374
-     * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
375
-     *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
376
-     */
377
-    public function finalize_payment_for($transaction, $update_txn = true)
378
-    {
379
-        /** @var $transaction EE_Transaction */
380
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
381
-        $last_payment_method = $transaction->payment_method();
382
-        if ($last_payment_method instanceof EE_Payment_Method) {
383
-            $payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
384
-            $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
385
-            return $payment;
386
-        } else {
387
-            return null;
388
-        }
389
-    }
390
-
391
-
392
-
393
-    /**
394
-     * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
395
-     *
396
-     * @param EE_Payment_Method $payment_method
397
-     * @param EE_Payment        $payment_to_refund
398
-     * @param array             $refund_info
399
-     * @return EE_Payment
400
-     * @throws \EE_Error
401
-     */
402
-    public function process_refund(
403
-        EE_Payment_Method $payment_method,
404
-        EE_Payment $payment_to_refund,
405
-        $refund_info = array()
406
-    ) {
407
-        if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
408
-            $payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
409
-            $this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
410
-        }
411
-        return $payment_to_refund;
412
-    }
413
-
414
-
415
-
416
-    /**
417
-     * This should be called each time there may have been an update to a
418
-     * payment on a transaction (ie, we asked for a payment to process a
419
-     * payment for a transaction, or we told a payment method about an IPN, or
420
-     * we told a payment method to
421
-     * "finalize_payment_for" (a transaction), or we told a payment method to
422
-     * process a refund. This should handle firing the correct hooks to
423
-     * indicate
424
-     * what exactly happened and updating the transaction appropriately). This
425
-     * could be integrated directly into EE_Transaction upon save, but we want
426
-     * this logic to be separate from 'normal' plain-jane saving and updating
427
-     * of transactions and payments, and to be tied to payment processing.
428
-     * Note: this method DOES NOT save the payment passed into it. It is the responsibility
429
-     * of previous code to decide whether or not to save (because the payment passed into
430
-     * this method might be a temporary, never-to-be-saved payment from an offline gateway,
431
-     * in which case we only want that payment object for some temporary usage during this request,
432
-     * but we don't want it to be saved).
433
-     *
434
-     * @param EE_Transaction|int $transaction
435
-     * @param EE_Payment         $payment
436
-     * @param boolean            $update_txn
437
-     *                        whether or not to call
438
-     *                        EE_Transaction_Processor::
439
-     *                        update_transaction_and_registrations_after_checkout_or_payment()
440
-     *                        (you can save 1 DB query if you know you're going
441
-     *                        to save it later instead)
442
-     * @param bool               $IPN
443
-     *                        if processing IPNs or other similar payment
444
-     *                        related activities that occur in alternate
445
-     *                        requests than the main one that is processing the
446
-     *                        TXN, then set this to true to check whether the
447
-     *                        TXN is locked before updating
448
-     * @throws \EE_Error
449
-     */
450
-    public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
451
-    {
452
-        $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
453
-        /** @type EE_Transaction $transaction */
454
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
455
-        // can we freely update the TXN at this moment?
456
-        if ($IPN && $transaction->is_locked()) {
457
-            // don't update the transaction at this exact moment
458
-            // because the TXN is active in another request
459
-            EE_Cron_Tasks::schedule_update_transaction_with_payment(
460
-                time(),
461
-                $transaction->ID(),
462
-                $payment->ID()
463
-            );
464
-        } else {
465
-            // verify payment and that it has been saved
466
-            if ($payment instanceof EE_Payment && $payment->ID()) {
467
-                if (
468
-                    $payment->payment_method() instanceof EE_Payment_Method
469
-                    && $payment->payment_method()->type_obj() instanceof EE_PMT_Base
470
-                ) {
471
-                    $payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
472
-                    // update TXN registrations with payment info
473
-                    $this->process_registration_payments($transaction, $payment);
474
-                }
475
-                $do_action = $payment->just_approved()
476
-                    ? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
477
-                    : $do_action;
478
-            } else {
479
-                // send out notifications
480
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
481
-                $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
482
-            }
483
-            if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
484
-                /** @type EE_Transaction_Payments $transaction_payments */
485
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
486
-                // set new value for total paid
487
-                $transaction_payments->calculate_total_payments_and_update_status($transaction);
488
-                // call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
489
-                if ($update_txn) {
490
-                    $this->_post_payment_processing($transaction, $payment, $IPN);
491
-                }
492
-            }
493
-            // granular hook for others to use.
494
-            do_action($do_action, $transaction, $payment);
495
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
496
-            //global hook for others to use.
497
-            do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
498
-        }
499
-    }
500
-
501
-
502
-
503
-    /**
504
-     * update registrations REG_paid field after successful payment and link registrations with payment
505
-     *
506
-     * @param EE_Transaction    $transaction
507
-     * @param EE_Payment        $payment
508
-     * @param EE_Registration[] $registrations
509
-     * @throws \EE_Error
510
-     */
511
-    public function process_registration_payments(
512
-        EE_Transaction $transaction,
513
-        EE_Payment $payment,
514
-        $registrations = array()
515
-    ) {
516
-        // only process if payment was successful
517
-        if ($payment->status() !== EEM_Payment::status_id_approved) {
518
-            return;
519
-        }
520
-        //EEM_Registration::instance()->show_next_x_db_queries();
521
-        if (empty($registrations)) {
522
-            // find registrations with monies owing that can receive a payment
523
-            $registrations = $transaction->registrations(
524
-                array(
525
-                    array(
526
-                        // only these reg statuses can receive payments
527
-                        'STS_ID'           => array('IN', EEM_Registration::reg_statuses_that_allow_payment()),
528
-                        'REG_final_price'  => array('!=', 0),
529
-                        'REG_final_price*' => array('!=', 'REG_paid', true),
530
-                    ),
531
-                )
532
-            );
533
-        }
534
-        // still nothing ??!??
535
-        if (empty($registrations)) {
536
-            return;
537
-        }
538
-        // todo: break out the following logic into a separate strategy class
539
-        // todo: named something like "Sequential_Reg_Payment_Strategy"
540
-        // todo: which would apply payments using the capitalist "first come first paid" approach
541
-        // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
542
-        // todo: which would be the socialist "everybody gets a piece of pie" approach,
543
-        // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
544
-        $refund = $payment->is_a_refund();
545
-        // how much is available to apply to registrations?
546
-        $available_payment_amount = abs($payment->amount());
547
-        foreach ($registrations as $registration) {
548
-            if ($registration instanceof EE_Registration) {
549
-                // nothing left?
550
-                if ($available_payment_amount <= 0) {
551
-                    break;
552
-                }
553
-                if ($refund) {
554
-                    $available_payment_amount = $this->process_registration_refund($registration, $payment, $available_payment_amount);
555
-                } else {
556
-                    $available_payment_amount = $this->process_registration_payment($registration, $payment, $available_payment_amount);
557
-                }
558
-            }
559
-        }
560
-        if ($available_payment_amount > 0 && apply_filters('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', false)) {
561
-            EE_Error::add_attention(
562
-                sprintf(
563
-                    __('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).',
564
-                        'event_espresso'),
565
-                    EEH_Template::format_currency($available_payment_amount),
566
-                    implode(', ', array_keys($registrations)),
567
-                    '<br/>',
568
-                    EEH_Template::format_currency($payment->amount())
569
-                ),
570
-                __FILE__, __FUNCTION__, __LINE__
571
-            );
572
-        }
573
-    }
574
-
575
-
576
-
577
-    /**
578
-     * update registration REG_paid field after successful payment and link registration with payment
579
-     *
580
-     * @param EE_Registration $registration
581
-     * @param EE_Payment      $payment
582
-     * @param float           $available_payment_amount
583
-     * @return float
584
-     * @throws \EE_Error
585
-     */
586
-    public function process_registration_payment(
587
-        EE_Registration $registration,
588
-        EE_Payment $payment,
589
-        $available_payment_amount = 0.00
590
-    ) {
591
-        $owing = $registration->final_price() - $registration->paid();
592
-        if ($owing > 0) {
593
-            // don't allow payment amount to exceed the available payment amount, OR the amount owing
594
-            $payment_amount = min($available_payment_amount, $owing);
595
-            // update $available_payment_amount
596
-            $available_payment_amount -= $payment_amount;
597
-            //calculate and set new REG_paid
598
-            $registration->set_paid($registration->paid() + $payment_amount);
599
-            // now save it
600
-            $this->_apply_registration_payment($registration, $payment, $payment_amount);
601
-        }
602
-        return $available_payment_amount;
603
-    }
604
-
605
-
606
-
607
-    /**
608
-     * update registration REG_paid field after successful payment and link registration with payment
609
-     *
610
-     * @param EE_Registration $registration
611
-     * @param EE_Payment      $payment
612
-     * @param float           $payment_amount
613
-     * @return void
614
-     * @throws \EE_Error
615
-     */
616
-    protected function _apply_registration_payment(
617
-        EE_Registration $registration,
618
-        EE_Payment $payment,
619
-        $payment_amount = 0.00
620
-    ) {
621
-        // find any existing reg payment records for this registration and payment
622
-        $existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
623
-            array(array('REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()))
624
-        );
625
-        // if existing registration payment exists
626
-        if ($existing_reg_payment instanceof EE_Registration_Payment) {
627
-            // then update that record
628
-            $existing_reg_payment->set_amount($payment_amount);
629
-            $existing_reg_payment->save();
630
-        } else {
631
-            // or add new relation between registration and payment and set amount
632
-            $registration->_add_relation_to($payment, 'Payment', array('RPY_amount' => $payment_amount));
633
-            // make it stick
634
-            $registration->save();
635
-        }
636
-    }
637
-
638
-
639
-
640
-    /**
641
-     * update registration REG_paid field after refund and link registration with payment
642
-     *
643
-     * @param EE_Registration $registration
644
-     * @param EE_Payment      $payment
645
-     * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
646
-     * @return float
647
-     * @throws \EE_Error
648
-     */
649
-    public function process_registration_refund(
650
-        EE_Registration $registration,
651
-        EE_Payment $payment,
652
-        $available_refund_amount = 0.00
653
-    ) {
654
-        //EEH_Debug_Tools::printr( $payment->amount(), '$payment->amount()', __FILE__, __LINE__ );
655
-        if ($registration->paid() > 0) {
656
-            // ensure $available_refund_amount is NOT negative
657
-            $available_refund_amount = (float)abs($available_refund_amount);
658
-            // don't allow refund amount to exceed the available payment amount, OR the amount paid
659
-            $refund_amount = min($available_refund_amount, (float)$registration->paid());
660
-            // update $available_payment_amount
661
-            $available_refund_amount -= $refund_amount;
662
-            //calculate and set new REG_paid
663
-            $registration->set_paid($registration->paid() - $refund_amount);
664
-            // convert payment amount back to a negative value for storage in the db
665
-            $refund_amount = (float)abs($refund_amount) * -1;
666
-            // now save it
667
-            $this->_apply_registration_payment($registration, $payment, $refund_amount);
668
-        }
669
-        return $available_refund_amount;
670
-    }
671
-
672
-
673
-
674
-    /**
675
-     * Process payments and transaction after payment process completed.
676
-     * ultimately this will send the TXN and payment details off so that notifications can be sent out.
677
-     * if this request happens to be processing an IPN,
678
-     * then we will also set the Payment Options Reg Step to completed,
679
-     * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
680
-     *
681
-     * @param EE_Transaction $transaction
682
-     * @param EE_Payment     $payment
683
-     * @param bool           $IPN
684
-     * @throws \EE_Error
685
-     */
686
-    protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
687
-    {
688
-        /** @type EE_Transaction_Processor $transaction_processor */
689
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
690
-        // is the Payment Options Reg Step completed ?
691
-        $payment_options_step_completed = $transaction->reg_step_completed('payment_options');
692
-        // if the Payment Options Reg Step is completed...
693
-        $revisit = $payment_options_step_completed === true ? true : false;
694
-        // then this is kinda sorta a revisit with regards to payments at least
695
-        $transaction_processor->set_revisit($revisit);
696
-        // if this is an IPN, let's consider the Payment Options Reg Step completed if not already
697
-        if (
698
-            $IPN
699
-            && $payment_options_step_completed !== true
700
-            && ($payment->is_approved() || $payment->is_pending())
701
-        ) {
702
-            $payment_options_step_completed = $transaction->set_reg_step_completed(
703
-                'payment_options'
704
-            );
705
-        }
706
-        // maybe update status, but don't save transaction just yet
707
-        $transaction->update_status_based_on_total_paid(false);
708
-        // check if 'finalize_registration' step has been completed...
709
-        $finalized = $transaction->reg_step_completed('finalize_registration');
710
-        //  if this is an IPN and the final step has not been initiated
711
-        if ($IPN && $payment_options_step_completed && $finalized === false) {
712
-            // and if it hasn't already been set as being started...
713
-            $finalized = $transaction->set_reg_step_initiated('finalize_registration');
714
-        }
715
-        $transaction->save();
716
-        // because the above will return false if the final step was not fully completed, we need to check again...
717
-        if ($IPN && $finalized !== false) {
718
-            // and if we are all good to go, then send out notifications
719
-            add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
720
-            //ok, now process the transaction according to the payment
721
-            $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($transaction, $payment);
722
-        }
723
-        // DEBUG LOG
724
-        $payment_method = $payment->payment_method();
725
-        if ($payment_method instanceof EE_Payment_Method) {
726
-            $payment_method_type_obj = $payment_method->type_obj();
727
-            if ($payment_method_type_obj instanceof EE_PMT_Base) {
728
-                $gateway = $payment_method_type_obj->get_gateway();
729
-                if ($gateway instanceof EE_Gateway) {
730
-                    $gateway->log(
731
-                        array(
732
-                            'message'               => __('Post Payment Transaction Details', 'event_espresso'),
733
-                            'transaction'           => $transaction->model_field_array(),
734
-                            'finalized'             => $finalized,
735
-                            'IPN'                   => $IPN,
736
-                            'deliver_notifications' => has_filter(
737
-                                'FHEE__EED_Messages___maybe_registration__deliver_notifications'
738
-                            ),
739
-                        ),
740
-                        $payment
741
-                    );
742
-                }
743
-            }
744
-        }
745
-    }
746
-
747
-
748
-
749
-    /**
750
-     * Force posts to PayPal to use TLS v1.2. See:
751
-     * https://core.trac.wordpress.org/ticket/36320
752
-     * https://core.trac.wordpress.org/ticket/34924#comment:15
753
-     * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
754
-     * This will affect paypal standard, pro, express, and payflow.
755
-     */
756
-    public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
757
-    {
758
-        if (strstr($url, 'https://') && strstr($url, '.paypal.com')) {
759
-            //Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
760
-            //instead of the constant because it might not be defined
761
-            curl_setopt($handle, CURLOPT_SSLVERSION, 1);
762
-        }
763
-    }
20
+	/**
21
+	 * @var EE_Payment_Processor $_instance
22
+	 * @access    private
23
+	 */
24
+	private static $_instance;
25
+
26
+
27
+
28
+	/**
29
+	 * @singleton method used to instantiate class object
30
+	 * @access    public
31
+	 * @return EE_Payment_Processor instance
32
+	 */
33
+	public static function instance()
34
+	{
35
+		// check if class object is instantiated
36
+		if ( ! self::$_instance instanceof EE_Payment_Processor) {
37
+			self::$_instance = new self();
38
+		}
39
+		return self::$_instance;
40
+	}
41
+
42
+
43
+
44
+	/**
45
+	 * @return EE_Payment_Processor
46
+	 */
47
+	public static function reset()
48
+	{
49
+		self::$_instance = null;
50
+		return self::instance();
51
+	}
52
+
53
+
54
+
55
+	/**
56
+	 *private constructor to prevent direct creation
57
+	 *
58
+	 * @Constructor
59
+	 * @access private
60
+	 */
61
+	private function __construct()
62
+	{
63
+		do_action('AHEE__EE_Payment_Processor__construct');
64
+		add_action('http_api_curl', array($this, '_curl_requests_to_paypal_use_tls'), 10, 3);
65
+	}
66
+
67
+
68
+
69
+	/**
70
+	 * Using the selected gateway, processes the payment for that transaction, and updates the transaction
71
+	 * appropriately. Saves the payment that is generated
72
+	 *
73
+	 * @param EE_Payment_Method    $payment_method
74
+	 * @param EE_Transaction       $transaction
75
+	 * @param float                $amount       if only part of the transaction is to be paid for, how much.
76
+	 *                                           Leave null if payment is for the full amount owing
77
+	 * @param EE_Billing_Info_Form $billing_form (or probably null, if it's an offline or offsite payment method).
78
+	 *                                           Receive_form_submission() should have
79
+	 *                                           already been called on the billing form
80
+	 *                                           (ie, its inputs should have their normalized values set).
81
+	 * @param string               $return_url   string used mostly by offsite gateways to specify
82
+	 *                                           where to go AFTER the offsite gateway
83
+	 * @param string               $method       like 'CART', indicates who the client who called this was
84
+	 * @param bool                 $by_admin     TRUE if payment is being attempted from the admin
85
+	 * @param boolean              $update_txn   whether or not to call
86
+	 *                                           EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
87
+	 * @param string               $cancel_url   URL to return to if off-site payments are cancelled
88
+	 * @return \EE_Payment
89
+	 * @throws \EE_Error
90
+	 */
91
+	public function process_payment(
92
+		EE_Payment_Method $payment_method,
93
+		EE_Transaction $transaction,
94
+		$amount = null,
95
+		$billing_form = null,
96
+		$return_url = null,
97
+		$method = 'CART',
98
+		$by_admin = false,
99
+		$update_txn = true,
100
+		$cancel_url = ''
101
+	) {
102
+		if ((float)$amount < 0) {
103
+			throw new EE_Error(
104
+				sprintf(
105
+					__(
106
+						'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
107
+						'event_espresso'
108
+					),
109
+					$amount,
110
+					$transaction->ID()
111
+				)
112
+			);
113
+		}
114
+		// verify payment method
115
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
116
+		// verify transaction
117
+		EEM_Transaction::instance()->ensure_is_obj($transaction);
118
+		$transaction->set_payment_method_ID($payment_method->ID());
119
+		// verify payment method type
120
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
121
+			$payment = $payment_method->type_obj()->process_payment(
122
+				$transaction,
123
+				min($amount, $transaction->remaining()),//make sure we don't overcharge
124
+				$billing_form,
125
+				$return_url,
126
+				add_query_arg(array('ee_cancel_payment' => true), $cancel_url),
127
+				$method,
128
+				$by_admin
129
+			);
130
+			// check if payment method uses an off-site gateway
131
+			if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
132
+				// don't process payments for off-site gateways yet because no payment has occurred yet
133
+				$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
134
+			}
135
+			return $payment;
136
+		} else {
137
+			EE_Error::add_error(
138
+				sprintf(
139
+					__('A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.', 'event_espresso'),
140
+					'<br/>',
141
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
142
+				), __FILE__, __FUNCTION__, __LINE__
143
+			);
144
+			return null;
145
+		}
146
+	}
147
+
148
+
149
+
150
+	/**
151
+	 * @param EE_Transaction|int $transaction
152
+	 * @param EE_Payment_Method  $payment_method
153
+	 * @throws EE_Error
154
+	 * @return string
155
+	 */
156
+	public function get_ipn_url_for_payment_method($transaction, $payment_method)
157
+	{
158
+		/** @type \EE_Transaction $transaction */
159
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
160
+		$primary_reg = $transaction->primary_registration();
161
+		if ( ! $primary_reg instanceof EE_Registration) {
162
+			throw new EE_Error(
163
+				sprintf(
164
+					__(
165
+						"Cannot get IPN URL for transaction with ID %d because it has no primary registration",
166
+						"event_espresso"
167
+					),
168
+					$transaction->ID()
169
+				)
170
+			);
171
+		}
172
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method, true);
173
+		$url = add_query_arg(
174
+			array(
175
+				'e_reg_url_link'    => $primary_reg->reg_url_link(),
176
+				'ee_payment_method' => $payment_method->slug(),
177
+			),
178
+			EE_Registry::instance()->CFG->core->txn_page_url()
179
+		);
180
+		return $url;
181
+	}
182
+
183
+
184
+
185
+	/**
186
+	 * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
187
+	 * we can easily find what registration the IPN is for and what payment method.
188
+	 * However, if not, we'll give all payment methods a chance to claim it and process it.
189
+	 * If a payment is found for the IPN info, it is saved.
190
+	 *
191
+	 * @param array              $_req_data            eg $_REQUEST
192
+	 * @param EE_Transaction|int $transaction          optional (or a transactions id)
193
+	 * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
194
+	 * @param boolean            $update_txn           whether or not to call
195
+	 *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
196
+	 * @param bool               $separate_IPN_request whether the IPN uses a separate request ( true like PayPal )
197
+	 *                                                 or is processed manually ( false like Mijireh )
198
+	 * @throws EE_Error
199
+	 * @throws Exception
200
+	 * @return EE_Payment
201
+	 */
202
+	public function process_ipn(
203
+		$_req_data,
204
+		$transaction = null,
205
+		$payment_method = null,
206
+		$update_txn = true,
207
+		$separate_IPN_request = true
208
+	) {
209
+		EE_Registry::instance()->load_model('Change_Log');
210
+		$_req_data = $this->_remove_unusable_characters_from_array((array)$_req_data);
211
+		EE_Processor_Base::set_IPN($separate_IPN_request);
212
+		$obj_for_log = null;
213
+		if ($transaction instanceof EE_Transaction) {
214
+			$obj_for_log = $transaction;
215
+			if ($payment_method instanceof EE_Payment_Method) {
216
+				$obj_for_log = EEM_Payment::instance()->get_one(
217
+					array(
218
+						array('TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()),
219
+						'order_by' => array('PAY_timestamp' => 'desc'),
220
+					)
221
+				);
222
+			}
223
+		} else if ($payment_method instanceof EE_Payment) {
224
+			$obj_for_log = $payment_method;
225
+		}
226
+		$log = EEM_Change_Log::instance()->log(
227
+			EEM_Change_Log::type_gateway,
228
+			array('IPN data received' => $_req_data),
229
+			$obj_for_log
230
+		);
231
+		try {
232
+			/**
233
+			 * @var EE_Payment $payment
234
+			 */
235
+			$payment = null;
236
+			if ($transaction && $payment_method) {
237
+				/** @type EE_Transaction $transaction */
238
+				$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
239
+				/** @type EE_Payment_Method $payment_method */
240
+				$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
241
+				if ($payment_method->type_obj() instanceof EE_PMT_Base) {
242
+					try {
243
+						$payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
244
+						$log->set_object($payment);
245
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
246
+						EEM_Change_Log::instance()->log(
247
+							EEM_Change_Log::type_gateway,
248
+							array(
249
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
250
+								'current_url' => EEH_URL::current_url(),
251
+								'payment'     => $e->getPaymentProperties(),
252
+								'IPN_data'    => $e->getIpnData(),
253
+							),
254
+							$obj_for_log
255
+						);
256
+						return $e->getPayment();
257
+					}
258
+				} else {
259
+					// not a payment
260
+					EE_Error::add_error(
261
+						sprintf(
262
+							__('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'),
263
+							'<br/>',
264
+							EE_Registry::instance()->CFG->organization->get_pretty('email')
265
+						),
266
+						__FILE__, __FUNCTION__, __LINE__
267
+					);
268
+				}
269
+			} else {
270
+				//that's actually pretty ok. The IPN just wasn't able
271
+				//to identify which transaction or payment method this was for
272
+				// give all active payment methods a chance to claim it
273
+				$active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
274
+				foreach ($active_payment_methods as $active_payment_method) {
275
+					try {
276
+						$payment = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
277
+						$payment_method = $active_payment_method;
278
+						EEM_Change_Log::instance()->log(
279
+							EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment
280
+						);
281
+						break;
282
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
283
+						EEM_Change_Log::instance()->log(
284
+							EEM_Change_Log::type_gateway,
285
+							array(
286
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
287
+								'current_url' => EEH_URL::current_url(),
288
+								'payment'     => $e->getPaymentProperties(),
289
+								'IPN_data'    => $e->getIpnData(),
290
+							),
291
+							$obj_for_log
292
+						);
293
+						return $e->getPayment();
294
+					} catch (EE_Error $e) {
295
+						//that's fine- it apparently couldn't handle the IPN
296
+					}
297
+				}
298
+			}
299
+			// 			EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
300
+			if ($payment instanceof EE_Payment) {
301
+				$payment->save();
302
+				//  update the TXN
303
+				$this->update_txn_based_on_payment($transaction, $payment, $update_txn, $separate_IPN_request);
304
+			} else {
305
+				//we couldn't find the payment for this IPN... let's try and log at least SOMETHING
306
+				if ($payment_method) {
307
+					EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment_method);
308
+				} elseif ($transaction) {
309
+					EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $transaction);
310
+				}
311
+			}
312
+			return $payment;
313
+		} catch (EE_Error $e) {
314
+			do_action(
315
+				'AHEE__log', __FILE__, __FUNCTION__, sprintf(
316
+					__('Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"', 'event_espresso'),
317
+					print_r($transaction, true),
318
+					print_r($_req_data, true),
319
+					$e->getMessage()
320
+				)
321
+			);
322
+			throw $e;
323
+		}
324
+	}
325
+
326
+
327
+
328
+	/**
329
+	 * Removes any non-printable illegal characters from the input,
330
+	 * which might cause a raucous when trying to insert into the database
331
+	 *
332
+	 * @param  array $request_data
333
+	 * @return array
334
+	 */
335
+	protected function _remove_unusable_characters_from_array(array $request_data)
336
+	{
337
+		$return_data = array();
338
+		foreach ($request_data as $key => $value) {
339
+			$return_data[$this->_remove_unusable_characters($key)] = $this->_remove_unusable_characters($value);
340
+		}
341
+		return $return_data;
342
+	}
343
+
344
+
345
+
346
+	/**
347
+	 * Removes any non-printable illegal characters from the input,
348
+	 * which might cause a raucous when trying to insert into the database
349
+	 *
350
+	 * @param string $request_data
351
+	 * @return string
352
+	 */
353
+	protected function _remove_unusable_characters($request_data)
354
+	{
355
+		return preg_replace('/[^[:print:]]/', '', $request_data);
356
+	}
357
+
358
+
359
+
360
+	/**
361
+	 * Should be called just before displaying the payment attempt results to the user,
362
+	 * when the payment attempt has finished. Some payment methods may have special
363
+	 * logic to perform here. For example, if process_payment() happens on a special request
364
+	 * and then the user is redirected to a page that displays the payment's status, this
365
+	 * should be called while loading the page that displays the payment's status. If the user is
366
+	 * sent to an offsite payment provider, this should be called upon returning from that offsite payment
367
+	 * provider.
368
+	 *
369
+	 * @param EE_Transaction|int $transaction
370
+	 * @param bool               $update_txn whether or not to call
371
+	 *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
372
+	 * @throws \EE_Error
373
+	 * @return EE_Payment
374
+	 * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
375
+	 *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
376
+	 */
377
+	public function finalize_payment_for($transaction, $update_txn = true)
378
+	{
379
+		/** @var $transaction EE_Transaction */
380
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
381
+		$last_payment_method = $transaction->payment_method();
382
+		if ($last_payment_method instanceof EE_Payment_Method) {
383
+			$payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
384
+			$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
385
+			return $payment;
386
+		} else {
387
+			return null;
388
+		}
389
+	}
390
+
391
+
392
+
393
+	/**
394
+	 * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
395
+	 *
396
+	 * @param EE_Payment_Method $payment_method
397
+	 * @param EE_Payment        $payment_to_refund
398
+	 * @param array             $refund_info
399
+	 * @return EE_Payment
400
+	 * @throws \EE_Error
401
+	 */
402
+	public function process_refund(
403
+		EE_Payment_Method $payment_method,
404
+		EE_Payment $payment_to_refund,
405
+		$refund_info = array()
406
+	) {
407
+		if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
408
+			$payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
409
+			$this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
410
+		}
411
+		return $payment_to_refund;
412
+	}
413
+
414
+
415
+
416
+	/**
417
+	 * This should be called each time there may have been an update to a
418
+	 * payment on a transaction (ie, we asked for a payment to process a
419
+	 * payment for a transaction, or we told a payment method about an IPN, or
420
+	 * we told a payment method to
421
+	 * "finalize_payment_for" (a transaction), or we told a payment method to
422
+	 * process a refund. This should handle firing the correct hooks to
423
+	 * indicate
424
+	 * what exactly happened and updating the transaction appropriately). This
425
+	 * could be integrated directly into EE_Transaction upon save, but we want
426
+	 * this logic to be separate from 'normal' plain-jane saving and updating
427
+	 * of transactions and payments, and to be tied to payment processing.
428
+	 * Note: this method DOES NOT save the payment passed into it. It is the responsibility
429
+	 * of previous code to decide whether or not to save (because the payment passed into
430
+	 * this method might be a temporary, never-to-be-saved payment from an offline gateway,
431
+	 * in which case we only want that payment object for some temporary usage during this request,
432
+	 * but we don't want it to be saved).
433
+	 *
434
+	 * @param EE_Transaction|int $transaction
435
+	 * @param EE_Payment         $payment
436
+	 * @param boolean            $update_txn
437
+	 *                        whether or not to call
438
+	 *                        EE_Transaction_Processor::
439
+	 *                        update_transaction_and_registrations_after_checkout_or_payment()
440
+	 *                        (you can save 1 DB query if you know you're going
441
+	 *                        to save it later instead)
442
+	 * @param bool               $IPN
443
+	 *                        if processing IPNs or other similar payment
444
+	 *                        related activities that occur in alternate
445
+	 *                        requests than the main one that is processing the
446
+	 *                        TXN, then set this to true to check whether the
447
+	 *                        TXN is locked before updating
448
+	 * @throws \EE_Error
449
+	 */
450
+	public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
451
+	{
452
+		$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
453
+		/** @type EE_Transaction $transaction */
454
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
455
+		// can we freely update the TXN at this moment?
456
+		if ($IPN && $transaction->is_locked()) {
457
+			// don't update the transaction at this exact moment
458
+			// because the TXN is active in another request
459
+			EE_Cron_Tasks::schedule_update_transaction_with_payment(
460
+				time(),
461
+				$transaction->ID(),
462
+				$payment->ID()
463
+			);
464
+		} else {
465
+			// verify payment and that it has been saved
466
+			if ($payment instanceof EE_Payment && $payment->ID()) {
467
+				if (
468
+					$payment->payment_method() instanceof EE_Payment_Method
469
+					&& $payment->payment_method()->type_obj() instanceof EE_PMT_Base
470
+				) {
471
+					$payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
472
+					// update TXN registrations with payment info
473
+					$this->process_registration_payments($transaction, $payment);
474
+				}
475
+				$do_action = $payment->just_approved()
476
+					? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
477
+					: $do_action;
478
+			} else {
479
+				// send out notifications
480
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
481
+				$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
482
+			}
483
+			if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
484
+				/** @type EE_Transaction_Payments $transaction_payments */
485
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
486
+				// set new value for total paid
487
+				$transaction_payments->calculate_total_payments_and_update_status($transaction);
488
+				// call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
489
+				if ($update_txn) {
490
+					$this->_post_payment_processing($transaction, $payment, $IPN);
491
+				}
492
+			}
493
+			// granular hook for others to use.
494
+			do_action($do_action, $transaction, $payment);
495
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
496
+			//global hook for others to use.
497
+			do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
498
+		}
499
+	}
500
+
501
+
502
+
503
+	/**
504
+	 * update registrations REG_paid field after successful payment and link registrations with payment
505
+	 *
506
+	 * @param EE_Transaction    $transaction
507
+	 * @param EE_Payment        $payment
508
+	 * @param EE_Registration[] $registrations
509
+	 * @throws \EE_Error
510
+	 */
511
+	public function process_registration_payments(
512
+		EE_Transaction $transaction,
513
+		EE_Payment $payment,
514
+		$registrations = array()
515
+	) {
516
+		// only process if payment was successful
517
+		if ($payment->status() !== EEM_Payment::status_id_approved) {
518
+			return;
519
+		}
520
+		//EEM_Registration::instance()->show_next_x_db_queries();
521
+		if (empty($registrations)) {
522
+			// find registrations with monies owing that can receive a payment
523
+			$registrations = $transaction->registrations(
524
+				array(
525
+					array(
526
+						// only these reg statuses can receive payments
527
+						'STS_ID'           => array('IN', EEM_Registration::reg_statuses_that_allow_payment()),
528
+						'REG_final_price'  => array('!=', 0),
529
+						'REG_final_price*' => array('!=', 'REG_paid', true),
530
+					),
531
+				)
532
+			);
533
+		}
534
+		// still nothing ??!??
535
+		if (empty($registrations)) {
536
+			return;
537
+		}
538
+		// todo: break out the following logic into a separate strategy class
539
+		// todo: named something like "Sequential_Reg_Payment_Strategy"
540
+		// todo: which would apply payments using the capitalist "first come first paid" approach
541
+		// todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
542
+		// todo: which would be the socialist "everybody gets a piece of pie" approach,
543
+		// todo: which would be better for deposits, where you want a bit of the payment applied to each registration
544
+		$refund = $payment->is_a_refund();
545
+		// how much is available to apply to registrations?
546
+		$available_payment_amount = abs($payment->amount());
547
+		foreach ($registrations as $registration) {
548
+			if ($registration instanceof EE_Registration) {
549
+				// nothing left?
550
+				if ($available_payment_amount <= 0) {
551
+					break;
552
+				}
553
+				if ($refund) {
554
+					$available_payment_amount = $this->process_registration_refund($registration, $payment, $available_payment_amount);
555
+				} else {
556
+					$available_payment_amount = $this->process_registration_payment($registration, $payment, $available_payment_amount);
557
+				}
558
+			}
559
+		}
560
+		if ($available_payment_amount > 0 && apply_filters('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', false)) {
561
+			EE_Error::add_attention(
562
+				sprintf(
563
+					__('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).',
564
+						'event_espresso'),
565
+					EEH_Template::format_currency($available_payment_amount),
566
+					implode(', ', array_keys($registrations)),
567
+					'<br/>',
568
+					EEH_Template::format_currency($payment->amount())
569
+				),
570
+				__FILE__, __FUNCTION__, __LINE__
571
+			);
572
+		}
573
+	}
574
+
575
+
576
+
577
+	/**
578
+	 * update registration REG_paid field after successful payment and link registration with payment
579
+	 *
580
+	 * @param EE_Registration $registration
581
+	 * @param EE_Payment      $payment
582
+	 * @param float           $available_payment_amount
583
+	 * @return float
584
+	 * @throws \EE_Error
585
+	 */
586
+	public function process_registration_payment(
587
+		EE_Registration $registration,
588
+		EE_Payment $payment,
589
+		$available_payment_amount = 0.00
590
+	) {
591
+		$owing = $registration->final_price() - $registration->paid();
592
+		if ($owing > 0) {
593
+			// don't allow payment amount to exceed the available payment amount, OR the amount owing
594
+			$payment_amount = min($available_payment_amount, $owing);
595
+			// update $available_payment_amount
596
+			$available_payment_amount -= $payment_amount;
597
+			//calculate and set new REG_paid
598
+			$registration->set_paid($registration->paid() + $payment_amount);
599
+			// now save it
600
+			$this->_apply_registration_payment($registration, $payment, $payment_amount);
601
+		}
602
+		return $available_payment_amount;
603
+	}
604
+
605
+
606
+
607
+	/**
608
+	 * update registration REG_paid field after successful payment and link registration with payment
609
+	 *
610
+	 * @param EE_Registration $registration
611
+	 * @param EE_Payment      $payment
612
+	 * @param float           $payment_amount
613
+	 * @return void
614
+	 * @throws \EE_Error
615
+	 */
616
+	protected function _apply_registration_payment(
617
+		EE_Registration $registration,
618
+		EE_Payment $payment,
619
+		$payment_amount = 0.00
620
+	) {
621
+		// find any existing reg payment records for this registration and payment
622
+		$existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
623
+			array(array('REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()))
624
+		);
625
+		// if existing registration payment exists
626
+		if ($existing_reg_payment instanceof EE_Registration_Payment) {
627
+			// then update that record
628
+			$existing_reg_payment->set_amount($payment_amount);
629
+			$existing_reg_payment->save();
630
+		} else {
631
+			// or add new relation between registration and payment and set amount
632
+			$registration->_add_relation_to($payment, 'Payment', array('RPY_amount' => $payment_amount));
633
+			// make it stick
634
+			$registration->save();
635
+		}
636
+	}
637
+
638
+
639
+
640
+	/**
641
+	 * update registration REG_paid field after refund and link registration with payment
642
+	 *
643
+	 * @param EE_Registration $registration
644
+	 * @param EE_Payment      $payment
645
+	 * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
646
+	 * @return float
647
+	 * @throws \EE_Error
648
+	 */
649
+	public function process_registration_refund(
650
+		EE_Registration $registration,
651
+		EE_Payment $payment,
652
+		$available_refund_amount = 0.00
653
+	) {
654
+		//EEH_Debug_Tools::printr( $payment->amount(), '$payment->amount()', __FILE__, __LINE__ );
655
+		if ($registration->paid() > 0) {
656
+			// ensure $available_refund_amount is NOT negative
657
+			$available_refund_amount = (float)abs($available_refund_amount);
658
+			// don't allow refund amount to exceed the available payment amount, OR the amount paid
659
+			$refund_amount = min($available_refund_amount, (float)$registration->paid());
660
+			// update $available_payment_amount
661
+			$available_refund_amount -= $refund_amount;
662
+			//calculate and set new REG_paid
663
+			$registration->set_paid($registration->paid() - $refund_amount);
664
+			// convert payment amount back to a negative value for storage in the db
665
+			$refund_amount = (float)abs($refund_amount) * -1;
666
+			// now save it
667
+			$this->_apply_registration_payment($registration, $payment, $refund_amount);
668
+		}
669
+		return $available_refund_amount;
670
+	}
671
+
672
+
673
+
674
+	/**
675
+	 * Process payments and transaction after payment process completed.
676
+	 * ultimately this will send the TXN and payment details off so that notifications can be sent out.
677
+	 * if this request happens to be processing an IPN,
678
+	 * then we will also set the Payment Options Reg Step to completed,
679
+	 * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
680
+	 *
681
+	 * @param EE_Transaction $transaction
682
+	 * @param EE_Payment     $payment
683
+	 * @param bool           $IPN
684
+	 * @throws \EE_Error
685
+	 */
686
+	protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
687
+	{
688
+		/** @type EE_Transaction_Processor $transaction_processor */
689
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
690
+		// is the Payment Options Reg Step completed ?
691
+		$payment_options_step_completed = $transaction->reg_step_completed('payment_options');
692
+		// if the Payment Options Reg Step is completed...
693
+		$revisit = $payment_options_step_completed === true ? true : false;
694
+		// then this is kinda sorta a revisit with regards to payments at least
695
+		$transaction_processor->set_revisit($revisit);
696
+		// if this is an IPN, let's consider the Payment Options Reg Step completed if not already
697
+		if (
698
+			$IPN
699
+			&& $payment_options_step_completed !== true
700
+			&& ($payment->is_approved() || $payment->is_pending())
701
+		) {
702
+			$payment_options_step_completed = $transaction->set_reg_step_completed(
703
+				'payment_options'
704
+			);
705
+		}
706
+		// maybe update status, but don't save transaction just yet
707
+		$transaction->update_status_based_on_total_paid(false);
708
+		// check if 'finalize_registration' step has been completed...
709
+		$finalized = $transaction->reg_step_completed('finalize_registration');
710
+		//  if this is an IPN and the final step has not been initiated
711
+		if ($IPN && $payment_options_step_completed && $finalized === false) {
712
+			// and if it hasn't already been set as being started...
713
+			$finalized = $transaction->set_reg_step_initiated('finalize_registration');
714
+		}
715
+		$transaction->save();
716
+		// because the above will return false if the final step was not fully completed, we need to check again...
717
+		if ($IPN && $finalized !== false) {
718
+			// and if we are all good to go, then send out notifications
719
+			add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
720
+			//ok, now process the transaction according to the payment
721
+			$transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($transaction, $payment);
722
+		}
723
+		// DEBUG LOG
724
+		$payment_method = $payment->payment_method();
725
+		if ($payment_method instanceof EE_Payment_Method) {
726
+			$payment_method_type_obj = $payment_method->type_obj();
727
+			if ($payment_method_type_obj instanceof EE_PMT_Base) {
728
+				$gateway = $payment_method_type_obj->get_gateway();
729
+				if ($gateway instanceof EE_Gateway) {
730
+					$gateway->log(
731
+						array(
732
+							'message'               => __('Post Payment Transaction Details', 'event_espresso'),
733
+							'transaction'           => $transaction->model_field_array(),
734
+							'finalized'             => $finalized,
735
+							'IPN'                   => $IPN,
736
+							'deliver_notifications' => has_filter(
737
+								'FHEE__EED_Messages___maybe_registration__deliver_notifications'
738
+							),
739
+						),
740
+						$payment
741
+					);
742
+				}
743
+			}
744
+		}
745
+	}
746
+
747
+
748
+
749
+	/**
750
+	 * Force posts to PayPal to use TLS v1.2. See:
751
+	 * https://core.trac.wordpress.org/ticket/36320
752
+	 * https://core.trac.wordpress.org/ticket/34924#comment:15
753
+	 * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
754
+	 * This will affect paypal standard, pro, express, and payflow.
755
+	 */
756
+	public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
757
+	{
758
+		if (strstr($url, 'https://') && strstr($url, '.paypal.com')) {
759
+			//Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
760
+			//instead of the constant because it might not be defined
761
+			curl_setopt($handle, CURLOPT_SSLVERSION, 1);
762
+		}
763
+	}
764 764
 }
Please login to merge, or discard this patch.
core/EE_Psr4AutoloaderInit.core.php 2 patches
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -32,19 +32,19 @@
 block discarded – undo
32 32
 	 * @return \EventEspresso\core\Psr4Autoloader
33 33
 	 */
34 34
 	public function initializeAutoloader() {
35
-        static $initialized = false;
36
-        if ( ! $initialized) {
37
-            // instantiate PSR4 autoloader
35
+		static $initialized = false;
36
+		if ( ! $initialized) {
37
+			// instantiate PSR4 autoloader
38 38
 			espresso_load_required( 'Psr4Autoloader', EE_CORE . 'Psr4Autoloader.php' );
39
-            EE_Psr4AutoloaderInit::$psr4_loader = new Psr4Autoloader();
40
-            // register the autoloader
41
-            EE_Psr4AutoloaderInit::$psr4_loader->register();
42
-            // register the base directories for the namespace prefix
43
-            EE_Psr4AutoloaderInit::$psr4_loader->addNamespace('EventEspresso', EE_PLUGIN_DIR_PATH);
44
-            EE_Psr4AutoloaderInit::$psr4_loader->addNamespace('EventEspressoBatchRequest', EE_LIBRARIES . 'batch');
45
-            $initialized = true;
46
-        }
47
-    }
39
+			EE_Psr4AutoloaderInit::$psr4_loader = new Psr4Autoloader();
40
+			// register the autoloader
41
+			EE_Psr4AutoloaderInit::$psr4_loader->register();
42
+			// register the base directories for the namespace prefix
43
+			EE_Psr4AutoloaderInit::$psr4_loader->addNamespace('EventEspresso', EE_PLUGIN_DIR_PATH);
44
+			EE_Psr4AutoloaderInit::$psr4_loader->addNamespace('EventEspressoBatchRequest', EE_LIBRARIES . 'batch');
45
+			$initialized = true;
46
+		}
47
+	}
48 48
 
49 49
 
50 50
 
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -35,13 +35,13 @@
 block discarded – undo
35 35
         static $initialized = false;
36 36
         if ( ! $initialized) {
37 37
             // instantiate PSR4 autoloader
38
-			espresso_load_required( 'Psr4Autoloader', EE_CORE . 'Psr4Autoloader.php' );
38
+			espresso_load_required('Psr4Autoloader', EE_CORE.'Psr4Autoloader.php');
39 39
             EE_Psr4AutoloaderInit::$psr4_loader = new Psr4Autoloader();
40 40
             // register the autoloader
41 41
             EE_Psr4AutoloaderInit::$psr4_loader->register();
42 42
             // register the base directories for the namespace prefix
43 43
             EE_Psr4AutoloaderInit::$psr4_loader->addNamespace('EventEspresso', EE_PLUGIN_DIR_PATH);
44
-            EE_Psr4AutoloaderInit::$psr4_loader->addNamespace('EventEspressoBatchRequest', EE_LIBRARIES . 'batch');
44
+            EE_Psr4AutoloaderInit::$psr4_loader->addNamespace('EventEspressoBatchRequest', EE_LIBRARIES.'batch');
45 45
             $initialized = true;
46 46
         }
47 47
     }
Please login to merge, or discard this patch.
core/EE_Error.core.php 1 patch
Indentation   +1100 added lines, -1100 removed lines patch added patch discarded remove patch
@@ -5,8 +5,8 @@  discard block
 block discarded – undo
5 5
 // if you're a dev and want to receive all errors via email
6 6
 // add this to your wp-config.php: define( 'EE_ERROR_EMAILS', TRUE );
7 7
 if (defined('WP_DEBUG') && WP_DEBUG === true && defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS === true) {
8
-    set_error_handler(array('EE_Error', 'error_handler'));
9
-    register_shutdown_function(array('EE_Error', 'fatal_error_handler'));
8
+	set_error_handler(array('EE_Error', 'error_handler'));
9
+	register_shutdown_function(array('EE_Error', 'fatal_error_handler'));
10 10
 }
11 11
 
12 12
 
@@ -23,257 +23,257 @@  discard block
 block discarded – undo
23 23
 {
24 24
 
25 25
 
26
-    /**
27
-     *    name of the file to log exceptions to
28
-     *
29
-     * @var string
30
-     */
31
-    private static $_exception_log_file = 'espresso_error_log.txt';
32
-
33
-    /**
34
-     *    stores details for all exception
35
-     *
36
-     * @var array
37
-     */
38
-    private static $_all_exceptions = array();
39
-
40
-    /**
41
-     *    tracks number of errors
42
-     *
43
-     * @var int
44
-     */
45
-    private static $_error_count = 0;
46
-
47
-    /**
48
-     * @var array $_espresso_notices
49
-     */
50
-    private static $_espresso_notices = array('success' => false, 'errors' => false, 'attention' => false);
51
-
52
-
53
-
54
-    /**
55
-     * @override default exception handling
56
-     * @param string         $message
57
-     * @param int            $code
58
-     * @param Exception|null $previous
59
-     */
60
-    public function __construct($message, $code = 0, Exception $previous = null)
61
-    {
62
-        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
63
-            parent::__construct($message, $code);
64
-        } else {
65
-            parent::__construct($message, $code, $previous);
66
-        }
67
-    }
68
-
69
-
70
-
71
-    /**
72
-     *    error_handler
73
-     *
74
-     * @param $code
75
-     * @param $message
76
-     * @param $file
77
-     * @param $line
78
-     * @return void
79
-     */
80
-    public static function error_handler($code, $message, $file, $line)
81
-    {
82
-        $type = EE_Error::error_type($code);
83
-        $site = site_url();
84
-        switch ($site) {
85
-            case 'http://ee4.eventespresso.com/' :
86
-            case 'http://ee4decaf.eventespresso.com/' :
87
-            case 'http://ee4hf.eventespresso.com/' :
88
-            case 'http://ee4a.eventespresso.com/' :
89
-            case 'http://ee4ad.eventespresso.com/' :
90
-            case 'http://ee4b.eventespresso.com/' :
91
-            case 'http://ee4bd.eventespresso.com/' :
92
-            case 'http://ee4d.eventespresso.com/' :
93
-            case 'http://ee4dd.eventespresso.com/' :
94
-                $to = '[email protected]';
95
-                break;
96
-            default :
97
-                $to = get_option('admin_email');
98
-        }
99
-        $subject = $type . ' ' . $message . ' in ' . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
100
-        $msg = EE_Error::_format_error($type, $message, $file, $line);
101
-        if (function_exists('wp_mail')) {
102
-            add_filter('wp_mail_content_type', array('EE_Error', 'set_content_type'));
103
-            wp_mail($to, $subject, $msg);
104
-        }
105
-        echo '<div id="message" class="espresso-notices error"><p>';
106
-        echo $type . ': ' . $message . '<br />' . $file . ' line ' . $line;
107
-        echo '<br /></p></div>';
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * error_type
114
-     * http://www.php.net/manual/en/errorfunc.constants.php#109430
115
-     *
116
-     * @param $code
117
-     * @return string
118
-     */
119
-    public static function error_type($code)
120
-    {
121
-        switch ($code) {
122
-            case E_ERROR: // 1 //
123
-                return 'E_ERROR';
124
-            case E_WARNING: // 2 //
125
-                return 'E_WARNING';
126
-            case E_PARSE: // 4 //
127
-                return 'E_PARSE';
128
-            case E_NOTICE: // 8 //
129
-                return 'E_NOTICE';
130
-            case E_CORE_ERROR: // 16 //
131
-                return 'E_CORE_ERROR';
132
-            case E_CORE_WARNING: // 32 //
133
-                return 'E_CORE_WARNING';
134
-            case E_COMPILE_ERROR: // 64 //
135
-                return 'E_COMPILE_ERROR';
136
-            case E_COMPILE_WARNING: // 128 //
137
-                return 'E_COMPILE_WARNING';
138
-            case E_USER_ERROR: // 256 //
139
-                return 'E_USER_ERROR';
140
-            case E_USER_WARNING: // 512 //
141
-                return 'E_USER_WARNING';
142
-            case E_USER_NOTICE: // 1024 //
143
-                return 'E_USER_NOTICE';
144
-            case E_STRICT: // 2048 //
145
-                return 'E_STRICT';
146
-            case E_RECOVERABLE_ERROR: // 4096 //
147
-                return 'E_RECOVERABLE_ERROR';
148
-            case E_DEPRECATED: // 8192 //
149
-                return 'E_DEPRECATED';
150
-            case E_USER_DEPRECATED: // 16384 //
151
-                return 'E_USER_DEPRECATED';
152
-            case E_ALL: // 16384 //
153
-                return 'E_ALL';
154
-        }
155
-        return '';
156
-    }
157
-
158
-
159
-
160
-    /**
161
-     *    fatal_error_handler
162
-     *
163
-     * @return void
164
-     */
165
-    public static function fatal_error_handler()
166
-    {
167
-        $last_error = error_get_last();
168
-        if ($last_error['type'] === E_ERROR) {
169
-            EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
170
-        }
171
-    }
172
-
173
-
174
-
175
-    /**
176
-     * _format_error
177
-     *
178
-     * @param $code
179
-     * @param $message
180
-     * @param $file
181
-     * @param $line
182
-     * @return string
183
-     */
184
-    private static function _format_error($code, $message, $file, $line)
185
-    {
186
-        $html = "<table cellpadding='5'><thead bgcolor='#f8f8f8'><th>Item</th><th align='left'>Details</th></thead><tbody>";
187
-        $html .= "<tr valign='top'><td><b>Code</b></td><td>$code</td></tr>";
188
-        $html .= "<tr valign='top'><td><b>Error</b></td><td>$message</td></tr>";
189
-        $html .= "<tr valign='top'><td><b>File</b></td><td>$file</td></tr>";
190
-        $html .= "<tr valign='top'><td><b>Line</b></td><td>$line</td></tr>";
191
-        $html .= '</tbody></table>';
192
-        return $html;
193
-    }
194
-
195
-
196
-
197
-    /**
198
-     * set_content_type
199
-     *
200
-     * @param $content_type
201
-     * @return string
202
-     */
203
-    public static function set_content_type($content_type)
204
-    {
205
-        return 'text/html';
206
-    }
207
-
208
-
209
-
210
-    /**
211
-     * @return void
212
-     * @throws EE_Error
213
-     * @throws ReflectionException
214
-     */
215
-    public function get_error()
216
-    {
217
-        if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
218
-            throw $this;
219
-        }
220
-        // get separate user and developer messages if they exist
221
-        $msg = explode('||', $this->getMessage());
222
-        $user_msg = $msg[0];
223
-        $dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
224
-        $msg = WP_DEBUG ? $dev_msg : $user_msg;
225
-        // add details to _all_exceptions array
226
-        $x_time = time();
227
-        self::$_all_exceptions[$x_time]['name'] = get_class($this);
228
-        self::$_all_exceptions[$x_time]['file'] = $this->getFile();
229
-        self::$_all_exceptions[$x_time]['line'] = $this->getLine();
230
-        self::$_all_exceptions[$x_time]['msg'] = $msg;
231
-        self::$_all_exceptions[$x_time]['code'] = $this->getCode();
232
-        self::$_all_exceptions[$x_time]['trace'] = $this->getTrace();
233
-        self::$_all_exceptions[$x_time]['string'] = $this->getTraceAsString();
234
-        self::$_error_count++;
235
-        //add_action( 'shutdown', array( $this, 'display_errors' ));
236
-        $this->display_errors();
237
-    }
238
-
239
-
240
-
241
-    /**
242
-     *    has_error
243
-     *
244
-     * @param bool   $check_stored
245
-     * @param string $type_to_check
246
-     * @return bool
247
-     */
248
-    public static function has_error($check_stored = false, $type_to_check = 'errors')
249
-    {
250
-        $has_error = isset(self::$_espresso_notices[$type_to_check])
251
-                     && ! empty(self::$_espresso_notices[$type_to_check])
252
-            ? true
253
-            : false;
254
-        if ($check_stored && ! $has_error) {
255
-            $notices = (array)get_option('ee_notices', array());
256
-            foreach ($notices as $type => $notice) {
257
-                if ($type === $type_to_check && $notice) {
258
-                    return true;
259
-                }
260
-            }
261
-        }
262
-        return $has_error;
263
-    }
264
-
265
-
266
-
267
-    /**
268
-     *    display_errors
269
-     *
270
-     * @echo   string
271
-     * @throws \ReflectionException
272
-     */
273
-    public function display_errors()
274
-    {
275
-        $trace_details = '';
276
-        $output = '
26
+	/**
27
+	 *    name of the file to log exceptions to
28
+	 *
29
+	 * @var string
30
+	 */
31
+	private static $_exception_log_file = 'espresso_error_log.txt';
32
+
33
+	/**
34
+	 *    stores details for all exception
35
+	 *
36
+	 * @var array
37
+	 */
38
+	private static $_all_exceptions = array();
39
+
40
+	/**
41
+	 *    tracks number of errors
42
+	 *
43
+	 * @var int
44
+	 */
45
+	private static $_error_count = 0;
46
+
47
+	/**
48
+	 * @var array $_espresso_notices
49
+	 */
50
+	private static $_espresso_notices = array('success' => false, 'errors' => false, 'attention' => false);
51
+
52
+
53
+
54
+	/**
55
+	 * @override default exception handling
56
+	 * @param string         $message
57
+	 * @param int            $code
58
+	 * @param Exception|null $previous
59
+	 */
60
+	public function __construct($message, $code = 0, Exception $previous = null)
61
+	{
62
+		if (version_compare(PHP_VERSION, '5.3.0', '<')) {
63
+			parent::__construct($message, $code);
64
+		} else {
65
+			parent::__construct($message, $code, $previous);
66
+		}
67
+	}
68
+
69
+
70
+
71
+	/**
72
+	 *    error_handler
73
+	 *
74
+	 * @param $code
75
+	 * @param $message
76
+	 * @param $file
77
+	 * @param $line
78
+	 * @return void
79
+	 */
80
+	public static function error_handler($code, $message, $file, $line)
81
+	{
82
+		$type = EE_Error::error_type($code);
83
+		$site = site_url();
84
+		switch ($site) {
85
+			case 'http://ee4.eventespresso.com/' :
86
+			case 'http://ee4decaf.eventespresso.com/' :
87
+			case 'http://ee4hf.eventespresso.com/' :
88
+			case 'http://ee4a.eventespresso.com/' :
89
+			case 'http://ee4ad.eventespresso.com/' :
90
+			case 'http://ee4b.eventespresso.com/' :
91
+			case 'http://ee4bd.eventespresso.com/' :
92
+			case 'http://ee4d.eventespresso.com/' :
93
+			case 'http://ee4dd.eventespresso.com/' :
94
+				$to = '[email protected]';
95
+				break;
96
+			default :
97
+				$to = get_option('admin_email');
98
+		}
99
+		$subject = $type . ' ' . $message . ' in ' . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
100
+		$msg = EE_Error::_format_error($type, $message, $file, $line);
101
+		if (function_exists('wp_mail')) {
102
+			add_filter('wp_mail_content_type', array('EE_Error', 'set_content_type'));
103
+			wp_mail($to, $subject, $msg);
104
+		}
105
+		echo '<div id="message" class="espresso-notices error"><p>';
106
+		echo $type . ': ' . $message . '<br />' . $file . ' line ' . $line;
107
+		echo '<br /></p></div>';
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * error_type
114
+	 * http://www.php.net/manual/en/errorfunc.constants.php#109430
115
+	 *
116
+	 * @param $code
117
+	 * @return string
118
+	 */
119
+	public static function error_type($code)
120
+	{
121
+		switch ($code) {
122
+			case E_ERROR: // 1 //
123
+				return 'E_ERROR';
124
+			case E_WARNING: // 2 //
125
+				return 'E_WARNING';
126
+			case E_PARSE: // 4 //
127
+				return 'E_PARSE';
128
+			case E_NOTICE: // 8 //
129
+				return 'E_NOTICE';
130
+			case E_CORE_ERROR: // 16 //
131
+				return 'E_CORE_ERROR';
132
+			case E_CORE_WARNING: // 32 //
133
+				return 'E_CORE_WARNING';
134
+			case E_COMPILE_ERROR: // 64 //
135
+				return 'E_COMPILE_ERROR';
136
+			case E_COMPILE_WARNING: // 128 //
137
+				return 'E_COMPILE_WARNING';
138
+			case E_USER_ERROR: // 256 //
139
+				return 'E_USER_ERROR';
140
+			case E_USER_WARNING: // 512 //
141
+				return 'E_USER_WARNING';
142
+			case E_USER_NOTICE: // 1024 //
143
+				return 'E_USER_NOTICE';
144
+			case E_STRICT: // 2048 //
145
+				return 'E_STRICT';
146
+			case E_RECOVERABLE_ERROR: // 4096 //
147
+				return 'E_RECOVERABLE_ERROR';
148
+			case E_DEPRECATED: // 8192 //
149
+				return 'E_DEPRECATED';
150
+			case E_USER_DEPRECATED: // 16384 //
151
+				return 'E_USER_DEPRECATED';
152
+			case E_ALL: // 16384 //
153
+				return 'E_ALL';
154
+		}
155
+		return '';
156
+	}
157
+
158
+
159
+
160
+	/**
161
+	 *    fatal_error_handler
162
+	 *
163
+	 * @return void
164
+	 */
165
+	public static function fatal_error_handler()
166
+	{
167
+		$last_error = error_get_last();
168
+		if ($last_error['type'] === E_ERROR) {
169
+			EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
170
+		}
171
+	}
172
+
173
+
174
+
175
+	/**
176
+	 * _format_error
177
+	 *
178
+	 * @param $code
179
+	 * @param $message
180
+	 * @param $file
181
+	 * @param $line
182
+	 * @return string
183
+	 */
184
+	private static function _format_error($code, $message, $file, $line)
185
+	{
186
+		$html = "<table cellpadding='5'><thead bgcolor='#f8f8f8'><th>Item</th><th align='left'>Details</th></thead><tbody>";
187
+		$html .= "<tr valign='top'><td><b>Code</b></td><td>$code</td></tr>";
188
+		$html .= "<tr valign='top'><td><b>Error</b></td><td>$message</td></tr>";
189
+		$html .= "<tr valign='top'><td><b>File</b></td><td>$file</td></tr>";
190
+		$html .= "<tr valign='top'><td><b>Line</b></td><td>$line</td></tr>";
191
+		$html .= '</tbody></table>';
192
+		return $html;
193
+	}
194
+
195
+
196
+
197
+	/**
198
+	 * set_content_type
199
+	 *
200
+	 * @param $content_type
201
+	 * @return string
202
+	 */
203
+	public static function set_content_type($content_type)
204
+	{
205
+		return 'text/html';
206
+	}
207
+
208
+
209
+
210
+	/**
211
+	 * @return void
212
+	 * @throws EE_Error
213
+	 * @throws ReflectionException
214
+	 */
215
+	public function get_error()
216
+	{
217
+		if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
218
+			throw $this;
219
+		}
220
+		// get separate user and developer messages if they exist
221
+		$msg = explode('||', $this->getMessage());
222
+		$user_msg = $msg[0];
223
+		$dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
224
+		$msg = WP_DEBUG ? $dev_msg : $user_msg;
225
+		// add details to _all_exceptions array
226
+		$x_time = time();
227
+		self::$_all_exceptions[$x_time]['name'] = get_class($this);
228
+		self::$_all_exceptions[$x_time]['file'] = $this->getFile();
229
+		self::$_all_exceptions[$x_time]['line'] = $this->getLine();
230
+		self::$_all_exceptions[$x_time]['msg'] = $msg;
231
+		self::$_all_exceptions[$x_time]['code'] = $this->getCode();
232
+		self::$_all_exceptions[$x_time]['trace'] = $this->getTrace();
233
+		self::$_all_exceptions[$x_time]['string'] = $this->getTraceAsString();
234
+		self::$_error_count++;
235
+		//add_action( 'shutdown', array( $this, 'display_errors' ));
236
+		$this->display_errors();
237
+	}
238
+
239
+
240
+
241
+	/**
242
+	 *    has_error
243
+	 *
244
+	 * @param bool   $check_stored
245
+	 * @param string $type_to_check
246
+	 * @return bool
247
+	 */
248
+	public static function has_error($check_stored = false, $type_to_check = 'errors')
249
+	{
250
+		$has_error = isset(self::$_espresso_notices[$type_to_check])
251
+					 && ! empty(self::$_espresso_notices[$type_to_check])
252
+			? true
253
+			: false;
254
+		if ($check_stored && ! $has_error) {
255
+			$notices = (array)get_option('ee_notices', array());
256
+			foreach ($notices as $type => $notice) {
257
+				if ($type === $type_to_check && $notice) {
258
+					return true;
259
+				}
260
+			}
261
+		}
262
+		return $has_error;
263
+	}
264
+
265
+
266
+
267
+	/**
268
+	 *    display_errors
269
+	 *
270
+	 * @echo   string
271
+	 * @throws \ReflectionException
272
+	 */
273
+	public function display_errors()
274
+	{
275
+		$trace_details = '';
276
+		$output = '
277 277
 <style type="text/css">
278 278
 	#ee-error-message {
279 279
 		max-width:90% !important;
@@ -329,21 +329,21 @@  discard block
 block discarded – undo
329 329
 	}
330 330
 </style>
331 331
 <div id="ee-error-message" class="error">';
332
-        if (! WP_DEBUG) {
333
-            $output .= '
332
+		if (! WP_DEBUG) {
333
+			$output .= '
334 334
 	<p>';
335
-        }
336
-        // cycle thru errors
337
-        foreach (self::$_all_exceptions as $time => $ex) {
338
-            $error_code = '';
339
-            // process trace info
340
-            if (empty($ex['trace'])) {
341
-                $trace_details .= __(
342
-                    'Sorry, but no trace information was available for this exception.',
343
-                    'event_espresso'
344
-                );
345
-            } else {
346
-                $trace_details .= '
335
+		}
336
+		// cycle thru errors
337
+		foreach (self::$_all_exceptions as $time => $ex) {
338
+			$error_code = '';
339
+			// process trace info
340
+			if (empty($ex['trace'])) {
341
+				$trace_details .= __(
342
+					'Sorry, but no trace information was available for this exception.',
343
+					'event_espresso'
344
+				);
345
+			} else {
346
+				$trace_details .= '
347 347
 			<div id="ee-trace-details">
348 348
 			<table width="100%" border="0" cellpadding="5" cellspacing="0">
349 349
 				<tr>
@@ -353,38 +353,38 @@  discard block
 block discarded – undo
353 353
 					<th scope="col" align="left">Class</th>
354 354
 					<th scope="col" align="left">Method( arguments )</th>
355 355
 				</tr>';
356
-                $last_on_stack = count($ex['trace']) - 1;
357
-                // reverse array so that stack is in proper chronological order
358
-                $sorted_trace = array_reverse($ex['trace']);
359
-                foreach ($sorted_trace as $nmbr => $trace) {
360
-                    $file = isset($trace['file']) ? $trace['file'] : '';
361
-                    $class = isset($trace['class']) ? $trace['class'] : '';
362
-                    $type = isset($trace['type']) ? $trace['type'] : '';
363
-                    $function = isset($trace['function']) ? $trace['function'] : '';
364
-                    $args = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
365
-                    $line = isset($trace['line']) ? $trace['line'] : '';
366
-                    $zebra = ($nmbr % 2) ? ' odd' : '';
367
-                    if (empty($file) && ! empty($class)) {
368
-                        $a = new ReflectionClass($class);
369
-                        $file = $a->getFileName();
370
-                        if (empty($line) && ! empty($function)) {
371
-                            $b = new ReflectionMethod($class, $function);
372
-                            $line = $b->getStartLine();
373
-                        }
374
-                    }
375
-                    if ($nmbr === $last_on_stack) {
376
-                        $file = $ex['file'] !== '' ? $ex['file'] : $file;
377
-                        $line = $ex['line'] !== '' ? $ex['line'] : $line;
378
-                        $error_code = self::generate_error_code($file, $trace['function'], $line);
379
-                    }
380
-                    $nmbr_dsply = ! empty($nmbr) ? $nmbr : '&nbsp;';
381
-                    $line_dsply = ! empty($line) ? $line : '&nbsp;';
382
-                    $file_dsply = ! empty($file) ? $file : '&nbsp;';
383
-                    $class_dsply = ! empty($class) ? $class : '&nbsp;';
384
-                    $type_dsply = ! empty($type) ? $type : '&nbsp;';
385
-                    $function_dsply = ! empty($function) ? $function : '&nbsp;';
386
-                    $args_dsply = ! empty($args) ? '( ' . $args . ' )' : '';
387
-                    $trace_details .= '
356
+				$last_on_stack = count($ex['trace']) - 1;
357
+				// reverse array so that stack is in proper chronological order
358
+				$sorted_trace = array_reverse($ex['trace']);
359
+				foreach ($sorted_trace as $nmbr => $trace) {
360
+					$file = isset($trace['file']) ? $trace['file'] : '';
361
+					$class = isset($trace['class']) ? $trace['class'] : '';
362
+					$type = isset($trace['type']) ? $trace['type'] : '';
363
+					$function = isset($trace['function']) ? $trace['function'] : '';
364
+					$args = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
365
+					$line = isset($trace['line']) ? $trace['line'] : '';
366
+					$zebra = ($nmbr % 2) ? ' odd' : '';
367
+					if (empty($file) && ! empty($class)) {
368
+						$a = new ReflectionClass($class);
369
+						$file = $a->getFileName();
370
+						if (empty($line) && ! empty($function)) {
371
+							$b = new ReflectionMethod($class, $function);
372
+							$line = $b->getStartLine();
373
+						}
374
+					}
375
+					if ($nmbr === $last_on_stack) {
376
+						$file = $ex['file'] !== '' ? $ex['file'] : $file;
377
+						$line = $ex['line'] !== '' ? $ex['line'] : $line;
378
+						$error_code = self::generate_error_code($file, $trace['function'], $line);
379
+					}
380
+					$nmbr_dsply = ! empty($nmbr) ? $nmbr : '&nbsp;';
381
+					$line_dsply = ! empty($line) ? $line : '&nbsp;';
382
+					$file_dsply = ! empty($file) ? $file : '&nbsp;';
383
+					$class_dsply = ! empty($class) ? $class : '&nbsp;';
384
+					$type_dsply = ! empty($type) ? $type : '&nbsp;';
385
+					$function_dsply = ! empty($function) ? $function : '&nbsp;';
386
+					$args_dsply = ! empty($args) ? '( ' . $args . ' )' : '';
387
+					$trace_details .= '
388 388
 					<tr>
389 389
 						<td align="right" class="' . $zebra . '">' . $nmbr_dsply . '</td>
390 390
 						<td align="right" class="' . $zebra . '">' . $line_dsply . '</td>
@@ -392,684 +392,684 @@  discard block
 block discarded – undo
392 392
 						<td align="left" class="' . $zebra . '">' . $class_dsply . '</td>
393 393
 						<td align="left" class="' . $zebra . '">' . $type_dsply . $function_dsply . $args_dsply . '</td>
394 394
 					</tr>';
395
-                }
396
-                $trace_details .= '
395
+				}
396
+				$trace_details .= '
397 397
 			 </table>
398 398
 			</div>';
399
-            }
400
-            $ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
401
-            // add generic non-identifying messages for non-privileged users
402
-            if (! WP_DEBUG) {
403
-                $output .= '<span class="ee-error-user-msg-spn">'
404
-                           . trim($ex['msg'])
405
-                           . '</span> &nbsp; <sup>'
406
-                           . $ex['code']
407
-                           . '</sup><br />';
408
-            } else {
409
-                // or helpful developer messages if debugging is on
410
-                $output .= '
399
+			}
400
+			$ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
401
+			// add generic non-identifying messages for non-privileged users
402
+			if (! WP_DEBUG) {
403
+				$output .= '<span class="ee-error-user-msg-spn">'
404
+						   . trim($ex['msg'])
405
+						   . '</span> &nbsp; <sup>'
406
+						   . $ex['code']
407
+						   . '</sup><br />';
408
+			} else {
409
+				// or helpful developer messages if debugging is on
410
+				$output .= '
411 411
 		<div class="ee-error-dev-msg-dv">
412 412
 			<p class="ee-error-dev-msg-pg">
413 413
 				<strong class="ee-error-dev-msg-str">An '
414
-                           . $ex['name']
415
-                           . ' exception was thrown!</strong>  &nbsp; <span>code: '
416
-                           . $ex['code']
417
-                           . '</span><br />
414
+						   . $ex['name']
415
+						   . ' exception was thrown!</strong>  &nbsp; <span>code: '
416
+						   . $ex['code']
417
+						   . '</span><br />
418 418
 				<span class="big-text">"'
419
-                           . trim($ex['msg'])
420
-                           . '"</span><br/>
419
+						   . trim($ex['msg'])
420
+						   . '"</span><br/>
421 421
 				<a id="display-ee-error-trace-'
422
-                           . self::$_error_count
423
-                           . $time
424
-                           . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
425
-                           . self::$_error_count
426
-                           . $time
427
-                           . '">
422
+						   . self::$_error_count
423
+						   . $time
424
+						   . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
425
+						   . self::$_error_count
426
+						   . $time
427
+						   . '">
428 428
 					'
429
-                           . __('click to view backtrace and class/method details', 'event_espresso')
430
-                           . '
429
+						   . __('click to view backtrace and class/method details', 'event_espresso')
430
+						   . '
431 431
 				</a><br />
432 432
 				<span class="small-text lt-grey-text">'
433
-                           . $ex['file']
434
-                           . ' &nbsp; ( line no: '
435
-                           . $ex['line']
436
-                           . ' )</span>
433
+						   . $ex['file']
434
+						   . ' &nbsp; ( line no: '
435
+						   . $ex['line']
436
+						   . ' )</span>
437 437
 			</p>
438 438
 			<div id="ee-error-trace-'
439
-                           . self::$_error_count
440
-                           . $time
441
-                           . '-dv" class="ee-error-trace-dv" style="display: none;">
439
+						   . self::$_error_count
440
+						   . $time
441
+						   . '-dv" class="ee-error-trace-dv" style="display: none;">
442 442
 				'
443
-                           . $trace_details;
444
-                if (! empty($class)) {
445
-                    $output .= '
443
+						   . $trace_details;
444
+				if (! empty($class)) {
445
+					$output .= '
446 446
 				<div style="padding:3px; margin:0 0 1em; border:1px solid #666; background:#fff; border-radius:3px;">
447 447
 					<div style="padding:1em 2em; border:1px solid #666; background:#f9f9f9;">
448 448
 						<h3>Class Details</h3>';
449
-                    $a = new ReflectionClass($class);
450
-                    $output .= '
449
+					$a = new ReflectionClass($class);
450
+					$output .= '
451 451
 						<pre>' . $a . '</pre>
452 452
 					</div>
453 453
 				</div>';
454
-                }
455
-                $output .= '
454
+				}
455
+				$output .= '
456 456
 			</div>
457 457
 		</div>
458 458
 		<br />';
459
-            }
460
-            $this->write_to_error_log($time, $ex);
461
-        }
462
-        // remove last linebreak
463
-        $output = substr($output, 0, -6);
464
-        if (! WP_DEBUG) {
465
-            $output .= '
459
+			}
460
+			$this->write_to_error_log($time, $ex);
461
+		}
462
+		// remove last linebreak
463
+		$output = substr($output, 0, -6);
464
+		if (! WP_DEBUG) {
465
+			$output .= '
466 466
 	</p>';
467
-        }
468
-        $output .= '
467
+		}
468
+		$output .= '
469 469
 </div>';
470
-        $output .= self::_print_scripts(true);
471
-        if (defined('DOING_AJAX')) {
472
-            echo wp_json_encode(array('error' => $output));
473
-            exit();
474
-        }
475
-        echo $output;
476
-        die();
477
-    }
478
-
479
-
480
-
481
-    /**
482
-     *    generate string from exception trace args
483
-     *
484
-     * @param array $arguments
485
-     * @param bool  $array
486
-     * @return string
487
-     */
488
-    private function _convert_args_to_string($arguments = array(), $array = false)
489
-    {
490
-        $arg_string = '';
491
-        if (! empty($arguments)) {
492
-            $args = array();
493
-            foreach ($arguments as $arg) {
494
-                if (! empty($arg)) {
495
-                    if (is_string($arg)) {
496
-                        $args[] = " '" . $arg . "'";
497
-                    } elseif (is_array($arg)) {
498
-                        $args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
499
-                    } elseif ($arg === null) {
500
-                        $args[] = ' NULL';
501
-                    } elseif (is_bool($arg)) {
502
-                        $args[] = ($arg) ? ' TRUE' : ' FALSE';
503
-                    } elseif (is_object($arg)) {
504
-                        $args[] = ' OBJECT ' . get_class($arg);
505
-                    } elseif (is_resource($arg)) {
506
-                        $args[] = get_resource_type($arg);
507
-                    } else {
508
-                        $args[] = $arg;
509
-                    }
510
-                }
511
-            }
512
-            $arg_string = implode(', ', $args);
513
-        }
514
-        if ($array) {
515
-            $arg_string .= ' )';
516
-        }
517
-        return $arg_string;
518
-    }
519
-
520
-
521
-
522
-    /**
523
-     *    add error message
524
-     *
525
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
526
-     *                            separate messages for user || dev
527
-     * @param        string $file the file that the error occurred in - just use __FILE__
528
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
529
-     * @param        string $line the line number where the error occurred - just use __LINE__
530
-     * @return        void
531
-     */
532
-    public static function add_error($msg = null, $file = null, $func = null, $line = null)
533
-    {
534
-        self::_add_notice('errors', $msg, $file, $func, $line);
535
-        self::$_error_count++;
536
-    }
537
-
538
-
539
-
540
-    /**
541
-     * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
542
-     * adds an error
543
-     *
544
-     * @param string $msg
545
-     * @param string $file
546
-     * @param string $func
547
-     * @param string $line
548
-     * @throws EE_Error
549
-     */
550
-    public static function throw_exception_if_debugging($msg = null, $file = null, $func = null, $line = null)
551
-    {
552
-        if (WP_DEBUG) {
553
-            throw new EE_Error($msg);
554
-        }
555
-        EE_Error::add_error($msg, $file, $func, $line);
556
-    }
557
-
558
-
559
-
560
-    /**
561
-     *    add success message
562
-     *
563
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
564
-     *                            separate messages for user || dev
565
-     * @param        string $file the file that the error occurred in - just use __FILE__
566
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
567
-     * @param        string $line the line number where the error occurred - just use __LINE__
568
-     * @return        void
569
-     */
570
-    public static function add_success($msg = null, $file = null, $func = null, $line = null)
571
-    {
572
-        self::_add_notice('success', $msg, $file, $func, $line);
573
-    }
574
-
575
-
576
-
577
-    /**
578
-     *    add attention message
579
-     *
580
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
581
-     *                            separate messages for user || dev
582
-     * @param        string $file the file that the error occurred in - just use __FILE__
583
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
584
-     * @param        string $line the line number where the error occurred - just use __LINE__
585
-     * @return        void
586
-     */
587
-    public static function add_attention($msg = null, $file = null, $func = null, $line = null)
588
-    {
589
-        self::_add_notice('attention', $msg, $file, $func, $line);
590
-    }
591
-
592
-
593
-
594
-    /**
595
-     *    add success message
596
-     *
597
-     * @param        string $type whether the message is for a success or error notification
598
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
599
-     *                            separate messages for user || dev
600
-     * @param        string $file the file that the error occurred in - just use __FILE__
601
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
602
-     * @param        string $line the line number where the error occurred - just use __LINE__
603
-     * @return        void
604
-     */
605
-    private static function _add_notice($type = 'success', $msg = null, $file = null, $func = null, $line = null)
606
-    {
607
-        if (empty($msg)) {
608
-            EE_Error::doing_it_wrong(
609
-                'EE_Error::add_' . $type . '()',
610
-                sprintf(
611
-                    __('Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
612
-                        'event_espresso'),
613
-                    $type,
614
-                    $file,
615
-                    $line
616
-                ),
617
-                EVENT_ESPRESSO_VERSION
618
-            );
619
-        }
620
-        if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
621
-            EE_Error::doing_it_wrong(
622
-                'EE_Error::add_error()',
623
-                __('You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
624
-                    'event_espresso'),
625
-                EVENT_ESPRESSO_VERSION
626
-            );
627
-        }
628
-        // get separate user and developer messages if they exist
629
-        $msg = explode('||', $msg);
630
-        $user_msg = $msg[0];
631
-        $dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
632
-        /**
633
-         * Do an action so other code can be triggered when a notice is created
634
-         *
635
-         * @param string $type     can be 'errors', 'attention', or 'success'
636
-         * @param string $user_msg message displayed to user when WP_DEBUG is off
637
-         * @param string $user_msg message displayed to user when WP_DEBUG is on
638
-         * @param string $file     file where error was generated
639
-         * @param string $func     function where error was generated
640
-         * @param string $line     line where error was generated
641
-         */
642
-        do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
643
-        $msg = WP_DEBUG ? $dev_msg : $user_msg;
644
-        // add notice if message exists
645
-        if (! empty($msg)) {
646
-            // get error code
647
-            $notice_code = EE_Error::generate_error_code($file, $func, $line);
648
-            if (WP_DEBUG && $type === 'errors') {
649
-                $msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
650
-            }
651
-            // add notice. Index by code if it's not blank
652
-            if ($notice_code) {
653
-                self::$_espresso_notices[$type][$notice_code] = $msg;
654
-            } else {
655
-                self::$_espresso_notices[$type][] = $msg;
656
-            }
657
-            add_action('wp_footer', array('EE_Error', 'enqueue_error_scripts'), 1);
658
-        }
659
-    }
660
-
661
-
662
-
663
-    /**
664
-     *    in some case it may be necessary to overwrite the existing success messages
665
-     *
666
-     * @return        void
667
-     */
668
-    public static function overwrite_success()
669
-    {
670
-        self::$_espresso_notices['success'] = false;
671
-    }
672
-
673
-
674
-
675
-    /**
676
-     *    in some case it may be necessary to overwrite the existing attention messages
677
-     *
678
-     * @return        void
679
-     */
680
-    public static function overwrite_attention()
681
-    {
682
-        self::$_espresso_notices['attention'] = false;
683
-    }
684
-
685
-
686
-
687
-    /**
688
-     *    in some case it may be necessary to overwrite the existing error messages
689
-     *
690
-     * @return        void
691
-     */
692
-    public static function overwrite_errors()
693
-    {
694
-        self::$_espresso_notices['errors'] = false;
695
-    }
696
-
697
-
698
-
699
-    /**
700
-     *    reset_notices
701
-     *
702
-     * @return void
703
-     */
704
-    public static function reset_notices()
705
-    {
706
-        self::$_espresso_notices['success'] = false;
707
-        self::$_espresso_notices['attention'] = false;
708
-        self::$_espresso_notices['errors'] = false;
709
-    }
710
-
711
-
712
-
713
-    /**
714
-     *    has_errors
715
-     *
716
-     * @return int
717
-     */
718
-    public static function has_notices()
719
-    {
720
-        $has_notices = 0;
721
-        // check for success messages
722
-        $has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success']) 
723
-            ? 3
724
-            : $has_notices;
725
-        // check for attention messages
726
-        $has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention']) 
727
-            ? 2
728
-            : $has_notices;
729
-        // check for error messages
730
-        $has_notices = self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors']) 
731
-            ? 1
732
-            : $has_notices;
733
-        return $has_notices;
734
-    }
735
-
736
-
737
-
738
-    /**
739
-     * This simply returns non formatted error notices as they were sent into the EE_Error object.
740
-     *
741
-     * @since 4.9.0
742
-     * @return array
743
-     */
744
-    public static function get_vanilla_notices()
745
-    {
746
-        return array(
747
-            'success'   => isset(self::$_espresso_notices['success'])
748
-                ? self::$_espresso_notices['success']
749
-                : array(),
750
-            'attention' => isset(self::$_espresso_notices['attention'])
751
-                ? self::$_espresso_notices['attention']
752
-                : array(),
753
-            'errors'    => isset(self::$_espresso_notices['errors'])
754
-                ? self::$_espresso_notices['errors']
755
-                : array(),
756
-        );
757
-    }
758
-
759
-
760
-
761
-    /**
762
-     *    compile all error or success messages into one string
763
-     *
764
-     * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
765
-     * @param        boolean $format_output     whether or not to format the messages for display in the WP admin
766
-     * @param        boolean $save_to_transient whether or not to save notices to the db for retrieval on next request
767
-     *                                          - ONLY do this just before redirecting
768
-     * @param        boolean $remove_empty      whether or not to unset empty messages
769
-     * @return        array
770
-     */
771
-    public static function get_notices($format_output = true, $save_to_transient = false, $remove_empty = true)
772
-    {
773
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
774
-        $success_messages = '';
775
-        $attention_messages = '';
776
-        $error_messages = '';
777
-        $print_scripts = false;
778
-        // either save notices to the db
779
-        if ($save_to_transient) {
780
-            update_option('ee_notices', self::$_espresso_notices);
781
-            return array();
782
-        }
783
-        // grab any notices that have been previously saved
784
-        if ($notices = get_option('ee_notices', false)) {
785
-            foreach ($notices as $type => $notice) {
786
-                if (is_array($notice) && ! empty($notice)) {
787
-                    // make sure that existing notice type is an array
788
-                    self::$_espresso_notices[$type] = is_array(self::$_espresso_notices[$type])
789
-                                                      && ! empty(self::$_espresso_notices[$type])
790
-                        ? self::$_espresso_notices[$type] : array();
791
-                    // merge stored notices with any newly created ones
792
-                    self::$_espresso_notices[$type] = array_merge(self::$_espresso_notices[$type], $notice);
793
-                    $print_scripts = true;
794
-                }
795
-            }
796
-            // now clear any stored notices
797
-            update_option('ee_notices', false);
798
-        }
799
-        // check for success messages
800
-        if (self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])) {
801
-            // combine messages
802
-            $success_messages .= implode(self::$_espresso_notices['success'], '<br /><br />');
803
-            $print_scripts = true;
804
-        }
805
-        // check for attention messages
806
-        if (self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])) {
807
-            // combine messages
808
-            $attention_messages .= implode(self::$_espresso_notices['attention'], '<br /><br />');
809
-            $print_scripts = true;
810
-        }
811
-        // check for error messages
812
-        if (self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])) {
813
-            $error_messages .= count(self::$_espresso_notices['errors']) > 1
814
-                ? __('The following errors have occurred:<br />', 'event_espresso')
815
-                : __('An error has occurred:<br />', 'event_espresso');
816
-            // combine messages
817
-            $error_messages .= implode(self::$_espresso_notices['errors'], '<br /><br />');
818
-            $print_scripts = true;
819
-        }
820
-        if ($format_output) {
821
-            $notices = '<div id="espresso-notices">';
822
-            $close = is_admin() ? ''
823
-                : '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"></span></a>';
824
-            if ($success_messages !== '') {
825
-                $css_id = is_admin() ? 'message' : 'espresso-notices-success';
826
-                $css_class = is_admin() ? 'updated fade' : 'success fade-away';
827
-                //showMessage( $success_messages );
828
-                $notices .= '<div id="'
829
-                            . $css_id
830
-                            . '" class="espresso-notices '
831
-                            . $css_class
832
-                            . '" style="display:none;"><p>'
833
-                            . $success_messages
834
-                            . '</p>'
835
-                            . $close
836
-                            . '</div>';
837
-            }
838
-            if ($attention_messages !== '') {
839
-                $css_id = is_admin() ? 'message' : 'espresso-notices-attention';
840
-                $css_class = is_admin() ? 'updated ee-notices-attention' : 'attention fade-away';
841
-                //showMessage( $error_messages, TRUE );
842
-                $notices .= '<div id="'
843
-                            . $css_id
844
-                            . '" class="espresso-notices '
845
-                            . $css_class
846
-                            . '" style="display:none;"><p>'
847
-                            . $attention_messages
848
-                            . '</p>'
849
-                            . $close
850
-                            . '</div>';
851
-            }
852
-            if ($error_messages !== '') {
853
-                $css_id = is_admin() ? 'message' : 'espresso-notices-error';
854
-                $css_class = is_admin() ? 'error' : 'error fade-away';
855
-                //showMessage( $error_messages, TRUE );
856
-                $notices .= '<div id="'
857
-                            . $css_id
858
-                            . '" class="espresso-notices '
859
-                            . $css_class
860
-                            . '" style="display:none;"><p>'
861
-                            . $error_messages
862
-                            . '</p>'
863
-                            . $close
864
-                            . '</div>';
865
-            }
866
-            $notices .= '</div>';
867
-        } else {
868
-            $notices = array(
869
-                'success'   => $success_messages,
870
-                'attention' => $attention_messages,
871
-                'errors'    => $error_messages,
872
-            );
873
-            if ($remove_empty) {
874
-                // remove empty notices
875
-                foreach ($notices as $type => $notice) {
876
-                    if (empty($notice)) {
877
-                        unset($notices[$type]);
878
-                    }
879
-                }
880
-            }
881
-        }
882
-        if ($print_scripts) {
883
-            self::_print_scripts();
884
-        }
885
-        return $notices;
886
-    }
887
-
888
-
889
-
890
-    /**
891
-     *    add_persistent_admin_notice
892
-     *
893
-     * @param        string $pan_name     the name, or key of the Persistent Admin Notice to be stored
894
-     * @param        string $pan_message  the message to be stored persistently until dismissed
895
-     * @param bool          $force_update allows one to enforce the reappearance of a persistent message.
896
-     * @return        void
897
-     */
898
-    public static function add_persistent_admin_notice($pan_name = '', $pan_message, $force_update = false)
899
-    {
900
-        if (! empty($pan_name) && ! empty($pan_message)) {
901
-            $persistent_admin_notices = get_option('ee_pers_admin_notices', array());
902
-            //maybe initialize persistent_admin_notices
903
-            if (empty($persistent_admin_notices)) {
904
-                add_option('ee_pers_admin_notices', array(), '', 'no');
905
-            }
906
-            $pan_name = sanitize_key($pan_name);
907
-            if (! array_key_exists($pan_name, $persistent_admin_notices) || $force_update) {
908
-                $persistent_admin_notices[$pan_name] = $pan_message;
909
-                update_option('ee_pers_admin_notices', $persistent_admin_notices);
910
-            }
911
-        }
912
-    }
913
-
914
-
915
-
916
-    /**
917
-     *    dismiss_persistent_admin_notice
918
-     *
919
-     * @param        string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
920
-     * @param bool          $purge
921
-     * @param bool          $return_immediately
922
-     * @return        void
923
-     */
924
-    public static function dismiss_persistent_admin_notice($pan_name = '', $purge = false, $return_immediately = false)
925
-    {
926
-        $pan_name = EE_Registry::instance()->REQ->is_set('ee_nag_notice')
927
-            ? EE_Registry::instance()->REQ->get('ee_nag_notice') 
928
-            : $pan_name;
929
-        if (! empty($pan_name)) {
930
-            $persistent_admin_notices = get_option('ee_pers_admin_notices', array());
931
-            // check if notice we wish to dismiss is actually in the $persistent_admin_notices array
932
-            if (is_array($persistent_admin_notices) && isset($persistent_admin_notices[$pan_name])) {
933
-                // completely delete nag notice, or just NULL message so that it can NOT be added again ?
934
-                if ($purge) {
935
-                    unset($persistent_admin_notices[$pan_name]);
936
-                } else {
937
-                    $persistent_admin_notices[$pan_name] = null;
938
-                }
939
-                if (update_option('ee_pers_admin_notices', $persistent_admin_notices) === false) {
940
-                    EE_Error::add_error(sprintf(__('The persistent admin notice for "%s" could not be deleted.',
941
-                        'event_espresso'), $pan_name), __FILE__, __FUNCTION__, __LINE__);
942
-                }
943
-            }
944
-        }
945
-        if ($return_immediately) {
946
-            return;
947
-        }
948
-        if (EE_Registry::instance()->REQ->ajax) {
949
-            // grab any notices and concatenate into string
950
-            echo wp_json_encode(array('errors' => implode('<br />', EE_Error::get_notices(false))));
951
-            exit();
952
-        }
953
-        // save errors to a transient to be displayed on next request (after redirect)
954
-        EE_Error::get_notices(false, true);
955
-        $return_url = EE_Registry::instance()->REQ->is_set('return_url')
956
-            ? EE_Registry::instance()->REQ->get('return_url') 
957
-            : '';
958
-        wp_safe_redirect(urldecode($return_url));
959
-    }
960
-
961
-
962
-
963
-    /**
964
-     * display_persistent_admin_notices
965
-     *
966
-     * @param  string $pan_name    the name, or key of the Persistent Admin Notice to be stored
967
-     * @param  string $pan_message the message to be stored persistently until dismissed
968
-     * @param  string $return_url  URL to go back to after nag notice is dismissed
969
-     * @return string
970
-     */
971
-    public static function display_persistent_admin_notices($pan_name = '', $pan_message = '', $return_url = '')
972
-    {
973
-        if (! empty($pan_name) && ! empty($pan_message) && ! is_array( $pan_message )) {
974
-            $args = array(
975
-                'nag_notice'    => $pan_name,
976
-                'return_url'    => urlencode($return_url),
977
-                'ajax_url'      => WP_AJAX_URL,
978
-                'unknown_error' => esc_html__(
979
-                    'An unknown error has occurred on the server while attempting to dismiss this notice.',
980
-                    'event_espresso'
981
-                ),
982
-            );
983
-            EE_Registry::$i18n_js_strings = array_merge(
984
-                EE_Registry::$i18n_js_strings,
985
-                array('ee_dismiss' => $args)
986
-            );
987
-            return '
470
+		$output .= self::_print_scripts(true);
471
+		if (defined('DOING_AJAX')) {
472
+			echo wp_json_encode(array('error' => $output));
473
+			exit();
474
+		}
475
+		echo $output;
476
+		die();
477
+	}
478
+
479
+
480
+
481
+	/**
482
+	 *    generate string from exception trace args
483
+	 *
484
+	 * @param array $arguments
485
+	 * @param bool  $array
486
+	 * @return string
487
+	 */
488
+	private function _convert_args_to_string($arguments = array(), $array = false)
489
+	{
490
+		$arg_string = '';
491
+		if (! empty($arguments)) {
492
+			$args = array();
493
+			foreach ($arguments as $arg) {
494
+				if (! empty($arg)) {
495
+					if (is_string($arg)) {
496
+						$args[] = " '" . $arg . "'";
497
+					} elseif (is_array($arg)) {
498
+						$args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
499
+					} elseif ($arg === null) {
500
+						$args[] = ' NULL';
501
+					} elseif (is_bool($arg)) {
502
+						$args[] = ($arg) ? ' TRUE' : ' FALSE';
503
+					} elseif (is_object($arg)) {
504
+						$args[] = ' OBJECT ' . get_class($arg);
505
+					} elseif (is_resource($arg)) {
506
+						$args[] = get_resource_type($arg);
507
+					} else {
508
+						$args[] = $arg;
509
+					}
510
+				}
511
+			}
512
+			$arg_string = implode(', ', $args);
513
+		}
514
+		if ($array) {
515
+			$arg_string .= ' )';
516
+		}
517
+		return $arg_string;
518
+	}
519
+
520
+
521
+
522
+	/**
523
+	 *    add error message
524
+	 *
525
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
526
+	 *                            separate messages for user || dev
527
+	 * @param        string $file the file that the error occurred in - just use __FILE__
528
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
529
+	 * @param        string $line the line number where the error occurred - just use __LINE__
530
+	 * @return        void
531
+	 */
532
+	public static function add_error($msg = null, $file = null, $func = null, $line = null)
533
+	{
534
+		self::_add_notice('errors', $msg, $file, $func, $line);
535
+		self::$_error_count++;
536
+	}
537
+
538
+
539
+
540
+	/**
541
+	 * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
542
+	 * adds an error
543
+	 *
544
+	 * @param string $msg
545
+	 * @param string $file
546
+	 * @param string $func
547
+	 * @param string $line
548
+	 * @throws EE_Error
549
+	 */
550
+	public static function throw_exception_if_debugging($msg = null, $file = null, $func = null, $line = null)
551
+	{
552
+		if (WP_DEBUG) {
553
+			throw new EE_Error($msg);
554
+		}
555
+		EE_Error::add_error($msg, $file, $func, $line);
556
+	}
557
+
558
+
559
+
560
+	/**
561
+	 *    add success message
562
+	 *
563
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
564
+	 *                            separate messages for user || dev
565
+	 * @param        string $file the file that the error occurred in - just use __FILE__
566
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
567
+	 * @param        string $line the line number where the error occurred - just use __LINE__
568
+	 * @return        void
569
+	 */
570
+	public static function add_success($msg = null, $file = null, $func = null, $line = null)
571
+	{
572
+		self::_add_notice('success', $msg, $file, $func, $line);
573
+	}
574
+
575
+
576
+
577
+	/**
578
+	 *    add attention message
579
+	 *
580
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
581
+	 *                            separate messages for user || dev
582
+	 * @param        string $file the file that the error occurred in - just use __FILE__
583
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
584
+	 * @param        string $line the line number where the error occurred - just use __LINE__
585
+	 * @return        void
586
+	 */
587
+	public static function add_attention($msg = null, $file = null, $func = null, $line = null)
588
+	{
589
+		self::_add_notice('attention', $msg, $file, $func, $line);
590
+	}
591
+
592
+
593
+
594
+	/**
595
+	 *    add success message
596
+	 *
597
+	 * @param        string $type whether the message is for a success or error notification
598
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
599
+	 *                            separate messages for user || dev
600
+	 * @param        string $file the file that the error occurred in - just use __FILE__
601
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
602
+	 * @param        string $line the line number where the error occurred - just use __LINE__
603
+	 * @return        void
604
+	 */
605
+	private static function _add_notice($type = 'success', $msg = null, $file = null, $func = null, $line = null)
606
+	{
607
+		if (empty($msg)) {
608
+			EE_Error::doing_it_wrong(
609
+				'EE_Error::add_' . $type . '()',
610
+				sprintf(
611
+					__('Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
612
+						'event_espresso'),
613
+					$type,
614
+					$file,
615
+					$line
616
+				),
617
+				EVENT_ESPRESSO_VERSION
618
+			);
619
+		}
620
+		if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
621
+			EE_Error::doing_it_wrong(
622
+				'EE_Error::add_error()',
623
+				__('You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
624
+					'event_espresso'),
625
+				EVENT_ESPRESSO_VERSION
626
+			);
627
+		}
628
+		// get separate user and developer messages if they exist
629
+		$msg = explode('||', $msg);
630
+		$user_msg = $msg[0];
631
+		$dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
632
+		/**
633
+		 * Do an action so other code can be triggered when a notice is created
634
+		 *
635
+		 * @param string $type     can be 'errors', 'attention', or 'success'
636
+		 * @param string $user_msg message displayed to user when WP_DEBUG is off
637
+		 * @param string $user_msg message displayed to user when WP_DEBUG is on
638
+		 * @param string $file     file where error was generated
639
+		 * @param string $func     function where error was generated
640
+		 * @param string $line     line where error was generated
641
+		 */
642
+		do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
643
+		$msg = WP_DEBUG ? $dev_msg : $user_msg;
644
+		// add notice if message exists
645
+		if (! empty($msg)) {
646
+			// get error code
647
+			$notice_code = EE_Error::generate_error_code($file, $func, $line);
648
+			if (WP_DEBUG && $type === 'errors') {
649
+				$msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
650
+			}
651
+			// add notice. Index by code if it's not blank
652
+			if ($notice_code) {
653
+				self::$_espresso_notices[$type][$notice_code] = $msg;
654
+			} else {
655
+				self::$_espresso_notices[$type][] = $msg;
656
+			}
657
+			add_action('wp_footer', array('EE_Error', 'enqueue_error_scripts'), 1);
658
+		}
659
+	}
660
+
661
+
662
+
663
+	/**
664
+	 *    in some case it may be necessary to overwrite the existing success messages
665
+	 *
666
+	 * @return        void
667
+	 */
668
+	public static function overwrite_success()
669
+	{
670
+		self::$_espresso_notices['success'] = false;
671
+	}
672
+
673
+
674
+
675
+	/**
676
+	 *    in some case it may be necessary to overwrite the existing attention messages
677
+	 *
678
+	 * @return        void
679
+	 */
680
+	public static function overwrite_attention()
681
+	{
682
+		self::$_espresso_notices['attention'] = false;
683
+	}
684
+
685
+
686
+
687
+	/**
688
+	 *    in some case it may be necessary to overwrite the existing error messages
689
+	 *
690
+	 * @return        void
691
+	 */
692
+	public static function overwrite_errors()
693
+	{
694
+		self::$_espresso_notices['errors'] = false;
695
+	}
696
+
697
+
698
+
699
+	/**
700
+	 *    reset_notices
701
+	 *
702
+	 * @return void
703
+	 */
704
+	public static function reset_notices()
705
+	{
706
+		self::$_espresso_notices['success'] = false;
707
+		self::$_espresso_notices['attention'] = false;
708
+		self::$_espresso_notices['errors'] = false;
709
+	}
710
+
711
+
712
+
713
+	/**
714
+	 *    has_errors
715
+	 *
716
+	 * @return int
717
+	 */
718
+	public static function has_notices()
719
+	{
720
+		$has_notices = 0;
721
+		// check for success messages
722
+		$has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success']) 
723
+			? 3
724
+			: $has_notices;
725
+		// check for attention messages
726
+		$has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention']) 
727
+			? 2
728
+			: $has_notices;
729
+		// check for error messages
730
+		$has_notices = self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors']) 
731
+			? 1
732
+			: $has_notices;
733
+		return $has_notices;
734
+	}
735
+
736
+
737
+
738
+	/**
739
+	 * This simply returns non formatted error notices as they were sent into the EE_Error object.
740
+	 *
741
+	 * @since 4.9.0
742
+	 * @return array
743
+	 */
744
+	public static function get_vanilla_notices()
745
+	{
746
+		return array(
747
+			'success'   => isset(self::$_espresso_notices['success'])
748
+				? self::$_espresso_notices['success']
749
+				: array(),
750
+			'attention' => isset(self::$_espresso_notices['attention'])
751
+				? self::$_espresso_notices['attention']
752
+				: array(),
753
+			'errors'    => isset(self::$_espresso_notices['errors'])
754
+				? self::$_espresso_notices['errors']
755
+				: array(),
756
+		);
757
+	}
758
+
759
+
760
+
761
+	/**
762
+	 *    compile all error or success messages into one string
763
+	 *
764
+	 * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
765
+	 * @param        boolean $format_output     whether or not to format the messages for display in the WP admin
766
+	 * @param        boolean $save_to_transient whether or not to save notices to the db for retrieval on next request
767
+	 *                                          - ONLY do this just before redirecting
768
+	 * @param        boolean $remove_empty      whether or not to unset empty messages
769
+	 * @return        array
770
+	 */
771
+	public static function get_notices($format_output = true, $save_to_transient = false, $remove_empty = true)
772
+	{
773
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
774
+		$success_messages = '';
775
+		$attention_messages = '';
776
+		$error_messages = '';
777
+		$print_scripts = false;
778
+		// either save notices to the db
779
+		if ($save_to_transient) {
780
+			update_option('ee_notices', self::$_espresso_notices);
781
+			return array();
782
+		}
783
+		// grab any notices that have been previously saved
784
+		if ($notices = get_option('ee_notices', false)) {
785
+			foreach ($notices as $type => $notice) {
786
+				if (is_array($notice) && ! empty($notice)) {
787
+					// make sure that existing notice type is an array
788
+					self::$_espresso_notices[$type] = is_array(self::$_espresso_notices[$type])
789
+													  && ! empty(self::$_espresso_notices[$type])
790
+						? self::$_espresso_notices[$type] : array();
791
+					// merge stored notices with any newly created ones
792
+					self::$_espresso_notices[$type] = array_merge(self::$_espresso_notices[$type], $notice);
793
+					$print_scripts = true;
794
+				}
795
+			}
796
+			// now clear any stored notices
797
+			update_option('ee_notices', false);
798
+		}
799
+		// check for success messages
800
+		if (self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])) {
801
+			// combine messages
802
+			$success_messages .= implode(self::$_espresso_notices['success'], '<br /><br />');
803
+			$print_scripts = true;
804
+		}
805
+		// check for attention messages
806
+		if (self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])) {
807
+			// combine messages
808
+			$attention_messages .= implode(self::$_espresso_notices['attention'], '<br /><br />');
809
+			$print_scripts = true;
810
+		}
811
+		// check for error messages
812
+		if (self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])) {
813
+			$error_messages .= count(self::$_espresso_notices['errors']) > 1
814
+				? __('The following errors have occurred:<br />', 'event_espresso')
815
+				: __('An error has occurred:<br />', 'event_espresso');
816
+			// combine messages
817
+			$error_messages .= implode(self::$_espresso_notices['errors'], '<br /><br />');
818
+			$print_scripts = true;
819
+		}
820
+		if ($format_output) {
821
+			$notices = '<div id="espresso-notices">';
822
+			$close = is_admin() ? ''
823
+				: '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"></span></a>';
824
+			if ($success_messages !== '') {
825
+				$css_id = is_admin() ? 'message' : 'espresso-notices-success';
826
+				$css_class = is_admin() ? 'updated fade' : 'success fade-away';
827
+				//showMessage( $success_messages );
828
+				$notices .= '<div id="'
829
+							. $css_id
830
+							. '" class="espresso-notices '
831
+							. $css_class
832
+							. '" style="display:none;"><p>'
833
+							. $success_messages
834
+							. '</p>'
835
+							. $close
836
+							. '</div>';
837
+			}
838
+			if ($attention_messages !== '') {
839
+				$css_id = is_admin() ? 'message' : 'espresso-notices-attention';
840
+				$css_class = is_admin() ? 'updated ee-notices-attention' : 'attention fade-away';
841
+				//showMessage( $error_messages, TRUE );
842
+				$notices .= '<div id="'
843
+							. $css_id
844
+							. '" class="espresso-notices '
845
+							. $css_class
846
+							. '" style="display:none;"><p>'
847
+							. $attention_messages
848
+							. '</p>'
849
+							. $close
850
+							. '</div>';
851
+			}
852
+			if ($error_messages !== '') {
853
+				$css_id = is_admin() ? 'message' : 'espresso-notices-error';
854
+				$css_class = is_admin() ? 'error' : 'error fade-away';
855
+				//showMessage( $error_messages, TRUE );
856
+				$notices .= '<div id="'
857
+							. $css_id
858
+							. '" class="espresso-notices '
859
+							. $css_class
860
+							. '" style="display:none;"><p>'
861
+							. $error_messages
862
+							. '</p>'
863
+							. $close
864
+							. '</div>';
865
+			}
866
+			$notices .= '</div>';
867
+		} else {
868
+			$notices = array(
869
+				'success'   => $success_messages,
870
+				'attention' => $attention_messages,
871
+				'errors'    => $error_messages,
872
+			);
873
+			if ($remove_empty) {
874
+				// remove empty notices
875
+				foreach ($notices as $type => $notice) {
876
+					if (empty($notice)) {
877
+						unset($notices[$type]);
878
+					}
879
+				}
880
+			}
881
+		}
882
+		if ($print_scripts) {
883
+			self::_print_scripts();
884
+		}
885
+		return $notices;
886
+	}
887
+
888
+
889
+
890
+	/**
891
+	 *    add_persistent_admin_notice
892
+	 *
893
+	 * @param        string $pan_name     the name, or key of the Persistent Admin Notice to be stored
894
+	 * @param        string $pan_message  the message to be stored persistently until dismissed
895
+	 * @param bool          $force_update allows one to enforce the reappearance of a persistent message.
896
+	 * @return        void
897
+	 */
898
+	public static function add_persistent_admin_notice($pan_name = '', $pan_message, $force_update = false)
899
+	{
900
+		if (! empty($pan_name) && ! empty($pan_message)) {
901
+			$persistent_admin_notices = get_option('ee_pers_admin_notices', array());
902
+			//maybe initialize persistent_admin_notices
903
+			if (empty($persistent_admin_notices)) {
904
+				add_option('ee_pers_admin_notices', array(), '', 'no');
905
+			}
906
+			$pan_name = sanitize_key($pan_name);
907
+			if (! array_key_exists($pan_name, $persistent_admin_notices) || $force_update) {
908
+				$persistent_admin_notices[$pan_name] = $pan_message;
909
+				update_option('ee_pers_admin_notices', $persistent_admin_notices);
910
+			}
911
+		}
912
+	}
913
+
914
+
915
+
916
+	/**
917
+	 *    dismiss_persistent_admin_notice
918
+	 *
919
+	 * @param        string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
920
+	 * @param bool          $purge
921
+	 * @param bool          $return_immediately
922
+	 * @return        void
923
+	 */
924
+	public static function dismiss_persistent_admin_notice($pan_name = '', $purge = false, $return_immediately = false)
925
+	{
926
+		$pan_name = EE_Registry::instance()->REQ->is_set('ee_nag_notice')
927
+			? EE_Registry::instance()->REQ->get('ee_nag_notice') 
928
+			: $pan_name;
929
+		if (! empty($pan_name)) {
930
+			$persistent_admin_notices = get_option('ee_pers_admin_notices', array());
931
+			// check if notice we wish to dismiss is actually in the $persistent_admin_notices array
932
+			if (is_array($persistent_admin_notices) && isset($persistent_admin_notices[$pan_name])) {
933
+				// completely delete nag notice, or just NULL message so that it can NOT be added again ?
934
+				if ($purge) {
935
+					unset($persistent_admin_notices[$pan_name]);
936
+				} else {
937
+					$persistent_admin_notices[$pan_name] = null;
938
+				}
939
+				if (update_option('ee_pers_admin_notices', $persistent_admin_notices) === false) {
940
+					EE_Error::add_error(sprintf(__('The persistent admin notice for "%s" could not be deleted.',
941
+						'event_espresso'), $pan_name), __FILE__, __FUNCTION__, __LINE__);
942
+				}
943
+			}
944
+		}
945
+		if ($return_immediately) {
946
+			return;
947
+		}
948
+		if (EE_Registry::instance()->REQ->ajax) {
949
+			// grab any notices and concatenate into string
950
+			echo wp_json_encode(array('errors' => implode('<br />', EE_Error::get_notices(false))));
951
+			exit();
952
+		}
953
+		// save errors to a transient to be displayed on next request (after redirect)
954
+		EE_Error::get_notices(false, true);
955
+		$return_url = EE_Registry::instance()->REQ->is_set('return_url')
956
+			? EE_Registry::instance()->REQ->get('return_url') 
957
+			: '';
958
+		wp_safe_redirect(urldecode($return_url));
959
+	}
960
+
961
+
962
+
963
+	/**
964
+	 * display_persistent_admin_notices
965
+	 *
966
+	 * @param  string $pan_name    the name, or key of the Persistent Admin Notice to be stored
967
+	 * @param  string $pan_message the message to be stored persistently until dismissed
968
+	 * @param  string $return_url  URL to go back to after nag notice is dismissed
969
+	 * @return string
970
+	 */
971
+	public static function display_persistent_admin_notices($pan_name = '', $pan_message = '', $return_url = '')
972
+	{
973
+		if (! empty($pan_name) && ! empty($pan_message) && ! is_array( $pan_message )) {
974
+			$args = array(
975
+				'nag_notice'    => $pan_name,
976
+				'return_url'    => urlencode($return_url),
977
+				'ajax_url'      => WP_AJAX_URL,
978
+				'unknown_error' => esc_html__(
979
+					'An unknown error has occurred on the server while attempting to dismiss this notice.',
980
+					'event_espresso'
981
+				),
982
+			);
983
+			EE_Registry::$i18n_js_strings = array_merge(
984
+				EE_Registry::$i18n_js_strings,
985
+				array('ee_dismiss' => $args)
986
+			);
987
+			return '
988 988
 			<div id="'
989
-                   . $pan_name
990
-                   . '" class="espresso-notices updated ee-nag-notice clearfix" style="border-left: 4px solid #fcb93c;">
989
+				   . $pan_name
990
+				   . '" class="espresso-notices updated ee-nag-notice clearfix" style="border-left: 4px solid #fcb93c;">
991 991
 				<p>'
992
-                   . $pan_message
993
-                   . '</p>
992
+				   . $pan_message
993
+				   . '</p>
994 994
 				<a class="dismiss-ee-nag-notice hide-if-no-js" style="float: right; cursor: pointer; text-decoration:none;" rel="'
995
-                   . $pan_name
996
-                   . '">
995
+				   . $pan_name
996
+				   . '">
997 997
 					<span class="dashicons dashicons-dismiss" style="position:relative; top:-1px; margin-right:.25em;"></span>'
998
-                   . __('Dismiss', 'event_espresso')
999
-                   . '
998
+				   . __('Dismiss', 'event_espresso')
999
+				   . '
1000 1000
 				</a>
1001 1001
 				<div style="clear:both;"></div>
1002 1002
 			</div>';
1003
-        }
1004
-        return '';
1005
-    }
1006
-
1007
-
1008
-
1009
-    /**
1010
-     *    get_persistent_admin_notices
1011
-     *
1012
-     * @param string $return_url
1013
-     * @return string
1014
-     */
1015
-    public static function get_persistent_admin_notices($return_url = '')
1016
-    {
1017
-        $notices = '';
1018
-        // check for persistent admin notices
1019
-        //filter the list though so plugins can notify the admin in a different way if they want
1020
-        $persistent_admin_notices = apply_filters(
1021
-            'FHEE__EE_Error__get_persistent_admin_notices',
1022
-            get_option('ee_pers_admin_notices', false),
1023
-            'ee_pers_admin_notices',
1024
-            $return_url
1025
-        );
1026
-        if ($persistent_admin_notices) {
1027
-            // load scripts
1028
-            wp_register_script(
1029
-                'espresso_core',
1030
-                EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1031
-                array('jquery'),
1032
-                EVENT_ESPRESSO_VERSION,
1033
-                true
1034
-            );
1035
-            wp_register_script(
1036
-                'ee_error_js',
1037
-                EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1038
-                array('espresso_core'),
1039
-                EVENT_ESPRESSO_VERSION,
1040
-                true
1041
-            );
1042
-            wp_enqueue_script('ee_error_js');
1043
-            // and display notices
1044
-            foreach ($persistent_admin_notices as $pan_name => $pan_message) {
1045
-                $notices .= self::display_persistent_admin_notices($pan_name, $pan_message, $return_url);
1046
-            }
1047
-        }
1048
-        return $notices;
1049
-    }
1050
-
1051
-
1052
-
1053
-    /**
1054
-     * _print_scripts
1055
-     *
1056
-     * @param    bool $force_print
1057
-     * @return    string
1058
-     */
1059
-    private static function _print_scripts($force_print = false)
1060
-    {
1061
-        if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1062
-            if (wp_script_is('ee_error_js', 'enqueued')) {
1063
-                return '';
1064
-            }
1065
-            if (wp_script_is('ee_error_js', 'registered')) {
1066
-                wp_enqueue_style('espresso_default');
1067
-                wp_enqueue_style('espresso_custom_css');
1068
-                wp_enqueue_script('ee_error_js');
1069
-                wp_localize_script('ee_error_js', 'ee_settings', array('wp_debug' => WP_DEBUG));
1070
-            }
1071
-        } else {
1072
-            return '
1003
+		}
1004
+		return '';
1005
+	}
1006
+
1007
+
1008
+
1009
+	/**
1010
+	 *    get_persistent_admin_notices
1011
+	 *
1012
+	 * @param string $return_url
1013
+	 * @return string
1014
+	 */
1015
+	public static function get_persistent_admin_notices($return_url = '')
1016
+	{
1017
+		$notices = '';
1018
+		// check for persistent admin notices
1019
+		//filter the list though so plugins can notify the admin in a different way if they want
1020
+		$persistent_admin_notices = apply_filters(
1021
+			'FHEE__EE_Error__get_persistent_admin_notices',
1022
+			get_option('ee_pers_admin_notices', false),
1023
+			'ee_pers_admin_notices',
1024
+			$return_url
1025
+		);
1026
+		if ($persistent_admin_notices) {
1027
+			// load scripts
1028
+			wp_register_script(
1029
+				'espresso_core',
1030
+				EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1031
+				array('jquery'),
1032
+				EVENT_ESPRESSO_VERSION,
1033
+				true
1034
+			);
1035
+			wp_register_script(
1036
+				'ee_error_js',
1037
+				EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1038
+				array('espresso_core'),
1039
+				EVENT_ESPRESSO_VERSION,
1040
+				true
1041
+			);
1042
+			wp_enqueue_script('ee_error_js');
1043
+			// and display notices
1044
+			foreach ($persistent_admin_notices as $pan_name => $pan_message) {
1045
+				$notices .= self::display_persistent_admin_notices($pan_name, $pan_message, $return_url);
1046
+			}
1047
+		}
1048
+		return $notices;
1049
+	}
1050
+
1051
+
1052
+
1053
+	/**
1054
+	 * _print_scripts
1055
+	 *
1056
+	 * @param    bool $force_print
1057
+	 * @return    string
1058
+	 */
1059
+	private static function _print_scripts($force_print = false)
1060
+	{
1061
+		if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1062
+			if (wp_script_is('ee_error_js', 'enqueued')) {
1063
+				return '';
1064
+			}
1065
+			if (wp_script_is('ee_error_js', 'registered')) {
1066
+				wp_enqueue_style('espresso_default');
1067
+				wp_enqueue_style('espresso_custom_css');
1068
+				wp_enqueue_script('ee_error_js');
1069
+				wp_localize_script('ee_error_js', 'ee_settings', array('wp_debug' => WP_DEBUG));
1070
+			}
1071
+		} else {
1072
+			return '
1073 1073
 <script>
1074 1074
 /* <![CDATA[ */
1075 1075
 var ee_settings = {"wp_debug":"' . WP_DEBUG . '"};
@@ -1079,143 +1079,143 @@  discard block
 block discarded – undo
1079 1079
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1080 1080
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1081 1081
 ';
1082
-        }
1083
-        return '';
1084
-    }
1085
-
1086
-
1087
-
1088
-    /**
1089
-     *    enqueue_error_scripts
1090
-     *
1091
-     * @return        void
1092
-     */
1093
-    public static function enqueue_error_scripts()
1094
-    {
1095
-        self::_print_scripts();
1096
-    }
1097
-
1098
-
1099
-
1100
-    /**
1101
-     *    create error code from filepath, function name,
1102
-     *    and line number where exception or error was thrown
1103
-     *
1104
-     * @param string $file
1105
-     * @param string $func
1106
-     * @param string $line
1107
-     * @return string
1108
-     */
1109
-    public static function generate_error_code($file = '', $func = '', $line = '')
1110
-    {
1111
-        $file = explode('.', basename($file));
1112
-        $error_code = ! empty($file[0]) ? $file[0] : '';
1113
-        $error_code .= ! empty($func) ? ' - ' . $func : '';
1114
-        $error_code .= ! empty($line) ? ' - ' . $line : '';
1115
-        return $error_code;
1116
-    }
1117
-
1118
-
1119
-
1120
-    /**
1121
-     *    write exception details to log file
1122
-     *
1123
-     * @param int   $time
1124
-     * @param array $ex
1125
-     * @param bool  $clear
1126
-     * @return void
1127
-     */
1128
-    public function write_to_error_log($time = 0, $ex = array(), $clear = false)
1129
-    {
1130
-        if (empty($ex)) {
1131
-            return;
1132
-        }
1133
-        if (! $time) {
1134
-            $time = time();
1135
-        }
1136
-        $exception_log = '----------------------------------------------------------------------------------------'
1137
-                         . PHP_EOL;
1138
-        $exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1139
-        $exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1140
-        $exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1141
-        $exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1142
-        $exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1143
-        $exception_log .= 'Stack trace: ' . PHP_EOL;
1144
-        $exception_log .= $ex['string'] . PHP_EOL;
1145
-        $exception_log .= '----------------------------------------------------------------------------------------'
1146
-                          . PHP_EOL;
1147
-        try {
1148
-            EEH_File::ensure_file_exists_and_is_writable(
1149
-                EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . self::$_exception_log_file
1150
-            );
1151
-            EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs');
1152
-            if (! $clear) {
1153
-                //get existing log file and append new log info
1154
-                $exception_log = EEH_File::get_file_contents(
1155
-                    EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . self::$_exception_log_file
1156
-                ) . $exception_log;
1157
-            }
1158
-            EEH_File::write_to_file(
1159
-                EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . self::$_exception_log_file,
1160
-                $exception_log
1161
-            );
1162
-        } catch (EE_Error $e) {
1163
-            EE_Error::add_error(sprintf(__('Event Espresso error logging could not be setup because: %s',
1164
-                'event_espresso'), $e->getMessage()));
1165
-            return;
1166
-        }
1167
-    }
1168
-
1169
-
1170
-
1171
-    /**
1172
-     * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1173
-     * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1174
-     * but the code execution is done in a manner that could lead to unexpected results
1175
-     * (i.e. running to early, or too late in WP or EE loading process).
1176
-     * A good test for knowing whether to use this method is:
1177
-     * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1178
-     * Yes -> use EE_Error::add_error() or throw new EE_Error()
1179
-     * 2. If this is loaded before something else, it won't break anything,
1180
-     * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1181
-     *
1182
-     * @uses   constant WP_DEBUG test if wp_debug is on or not
1183
-     * @param string $function      The function that was called
1184
-     * @param string $message       A message explaining what has been done incorrectly
1185
-     * @param string $version       The version of Event Espresso where the error was added
1186
-     * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
1187
-     *                              for a deprecated function. This allows deprecation to occur during one version,
1188
-     *                              but not have any notices appear until a later version. This allows developers
1189
-     *                              extra time to update their code before notices appear.
1190
-     * @param int    $error_type
1191
-     */
1192
-    public static function doing_it_wrong(
1193
-        $function,
1194
-        $message,
1195
-        $version,
1196
-        $applies_when = '',
1197
-        $error_type = null
1198
-    ) {
1199
-        if (defined('WP_DEBUG') && WP_DEBUG) {
1200
-            EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1201
-        }
1202
-    }
1203
-
1204
-
1205
-
1206
-    /**
1207
-     * Like get_notices, but returns an array of all the notices of the given type.
1208
-     *
1209
-     * @return array {
1210
-     * @type array $success   all the success messages
1211
-     * @type array $errors    all the error messages
1212
-     * @type array $attention all the attention messages
1213
-     * }
1214
-     */
1215
-    public static function get_raw_notices()
1216
-    {
1217
-        return self::$_espresso_notices;
1218
-    }
1082
+		}
1083
+		return '';
1084
+	}
1085
+
1086
+
1087
+
1088
+	/**
1089
+	 *    enqueue_error_scripts
1090
+	 *
1091
+	 * @return        void
1092
+	 */
1093
+	public static function enqueue_error_scripts()
1094
+	{
1095
+		self::_print_scripts();
1096
+	}
1097
+
1098
+
1099
+
1100
+	/**
1101
+	 *    create error code from filepath, function name,
1102
+	 *    and line number where exception or error was thrown
1103
+	 *
1104
+	 * @param string $file
1105
+	 * @param string $func
1106
+	 * @param string $line
1107
+	 * @return string
1108
+	 */
1109
+	public static function generate_error_code($file = '', $func = '', $line = '')
1110
+	{
1111
+		$file = explode('.', basename($file));
1112
+		$error_code = ! empty($file[0]) ? $file[0] : '';
1113
+		$error_code .= ! empty($func) ? ' - ' . $func : '';
1114
+		$error_code .= ! empty($line) ? ' - ' . $line : '';
1115
+		return $error_code;
1116
+	}
1117
+
1118
+
1119
+
1120
+	/**
1121
+	 *    write exception details to log file
1122
+	 *
1123
+	 * @param int   $time
1124
+	 * @param array $ex
1125
+	 * @param bool  $clear
1126
+	 * @return void
1127
+	 */
1128
+	public function write_to_error_log($time = 0, $ex = array(), $clear = false)
1129
+	{
1130
+		if (empty($ex)) {
1131
+			return;
1132
+		}
1133
+		if (! $time) {
1134
+			$time = time();
1135
+		}
1136
+		$exception_log = '----------------------------------------------------------------------------------------'
1137
+						 . PHP_EOL;
1138
+		$exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1139
+		$exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1140
+		$exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1141
+		$exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1142
+		$exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1143
+		$exception_log .= 'Stack trace: ' . PHP_EOL;
1144
+		$exception_log .= $ex['string'] . PHP_EOL;
1145
+		$exception_log .= '----------------------------------------------------------------------------------------'
1146
+						  . PHP_EOL;
1147
+		try {
1148
+			EEH_File::ensure_file_exists_and_is_writable(
1149
+				EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . self::$_exception_log_file
1150
+			);
1151
+			EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs');
1152
+			if (! $clear) {
1153
+				//get existing log file and append new log info
1154
+				$exception_log = EEH_File::get_file_contents(
1155
+					EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . self::$_exception_log_file
1156
+				) . $exception_log;
1157
+			}
1158
+			EEH_File::write_to_file(
1159
+				EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . self::$_exception_log_file,
1160
+				$exception_log
1161
+			);
1162
+		} catch (EE_Error $e) {
1163
+			EE_Error::add_error(sprintf(__('Event Espresso error logging could not be setup because: %s',
1164
+				'event_espresso'), $e->getMessage()));
1165
+			return;
1166
+		}
1167
+	}
1168
+
1169
+
1170
+
1171
+	/**
1172
+	 * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1173
+	 * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1174
+	 * but the code execution is done in a manner that could lead to unexpected results
1175
+	 * (i.e. running to early, or too late in WP or EE loading process).
1176
+	 * A good test for knowing whether to use this method is:
1177
+	 * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1178
+	 * Yes -> use EE_Error::add_error() or throw new EE_Error()
1179
+	 * 2. If this is loaded before something else, it won't break anything,
1180
+	 * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1181
+	 *
1182
+	 * @uses   constant WP_DEBUG test if wp_debug is on or not
1183
+	 * @param string $function      The function that was called
1184
+	 * @param string $message       A message explaining what has been done incorrectly
1185
+	 * @param string $version       The version of Event Espresso where the error was added
1186
+	 * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
1187
+	 *                              for a deprecated function. This allows deprecation to occur during one version,
1188
+	 *                              but not have any notices appear until a later version. This allows developers
1189
+	 *                              extra time to update their code before notices appear.
1190
+	 * @param int    $error_type
1191
+	 */
1192
+	public static function doing_it_wrong(
1193
+		$function,
1194
+		$message,
1195
+		$version,
1196
+		$applies_when = '',
1197
+		$error_type = null
1198
+	) {
1199
+		if (defined('WP_DEBUG') && WP_DEBUG) {
1200
+			EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1201
+		}
1202
+	}
1203
+
1204
+
1205
+
1206
+	/**
1207
+	 * Like get_notices, but returns an array of all the notices of the given type.
1208
+	 *
1209
+	 * @return array {
1210
+	 * @type array $success   all the success messages
1211
+	 * @type array $errors    all the error messages
1212
+	 * @type array $attention all the attention messages
1213
+	 * }
1214
+	 */
1215
+	public static function get_raw_notices()
1216
+	{
1217
+		return self::$_espresso_notices;
1218
+	}
1219 1219
 
1220 1220
 
1221 1221
 
@@ -1231,27 +1231,27 @@  discard block
 block discarded – undo
1231 1231
  */
1232 1232
 function espresso_error_enqueue_scripts()
1233 1233
 {
1234
-    // js for error handling
1235
-    wp_register_script(
1236
-        'espresso_core',
1237
-        EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1238
-        array('jquery'),
1239
-        EVENT_ESPRESSO_VERSION,
1240
-        false
1241
-    );
1242
-    wp_register_script(
1243
-        'ee_error_js',
1244
-        EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1245
-        array('espresso_core'),
1246
-        EVENT_ESPRESSO_VERSION,
1247
-        false
1248
-    );
1234
+	// js for error handling
1235
+	wp_register_script(
1236
+		'espresso_core',
1237
+		EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1238
+		array('jquery'),
1239
+		EVENT_ESPRESSO_VERSION,
1240
+		false
1241
+	);
1242
+	wp_register_script(
1243
+		'ee_error_js',
1244
+		EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1245
+		array('espresso_core'),
1246
+		EVENT_ESPRESSO_VERSION,
1247
+		false
1248
+	);
1249 1249
 }
1250 1250
 
1251 1251
 if (is_admin()) {
1252
-    add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1252
+	add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1253 1253
 } else {
1254
-    add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1254
+	add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1255 1255
 }
1256 1256
 
1257 1257
 
Please login to merge, or discard this patch.
core/EE_Registry.core.php 2 patches
Indentation   +1452 added lines, -1452 removed lines patch added patch discarded remove patch
@@ -19,1488 +19,1488 @@
 block discarded – undo
19 19
 class EE_Registry implements ResettableInterface
20 20
 {
21 21
 
22
-    /**
23
-     *    EE_Registry Object
24
-     *
25
-     * @var EE_Registry $_instance
26
-     * @access    private
27
-     */
28
-    private static $_instance = null;
29
-
30
-    /**
31
-     * @var EE_Dependency_Map $_dependency_map
32
-     * @access    protected
33
-     */
34
-    protected $_dependency_map = null;
35
-
36
-    /**
37
-     * @var array $_class_abbreviations
38
-     * @access    protected
39
-     */
40
-    protected $_class_abbreviations = array();
41
-
42
-    /**
43
-     * @access public
44
-     * @var \EventEspresso\core\services\commands\CommandBusInterface $BUS
45
-     */
46
-    public $BUS;
47
-
48
-    /**
49
-     *    EE_Cart Object
50
-     *
51
-     * @access    public
52
-     * @var    EE_Cart $CART
53
-     */
54
-    public $CART = null;
55
-
56
-    /**
57
-     *    EE_Config Object
58
-     *
59
-     * @access    public
60
-     * @var    EE_Config $CFG
61
-     */
62
-    public $CFG = null;
63
-
64
-    /**
65
-     * EE_Network_Config Object
66
-     *
67
-     * @access public
68
-     * @var EE_Network_Config $NET_CFG
69
-     */
70
-    public $NET_CFG = null;
71
-
72
-    /**
73
-     *    StdClass object for storing library classes in
74
-     *
75
-     * @public LIB
76
-     * @var StdClass $LIB
77
-     */
78
-    public $LIB = null;
79
-
80
-    /**
81
-     *    EE_Request_Handler Object
82
-     *
83
-     * @access    public
84
-     * @var    EE_Request_Handler $REQ
85
-     */
86
-    public $REQ = null;
87
-
88
-    /**
89
-     *    EE_Session Object
90
-     *
91
-     * @access    public
92
-     * @var    EE_Session $SSN
93
-     */
94
-    public $SSN = null;
95
-
96
-    /**
97
-     * holds the ee capabilities object.
98
-     *
99
-     * @since 4.5.0
100
-     * @var EE_Capabilities
101
-     */
102
-    public $CAP = null;
103
-
104
-    /**
105
-     * holds the EE_Message_Resource_Manager object.
106
-     *
107
-     * @since 4.9.0
108
-     * @var EE_Message_Resource_Manager
109
-     */
110
-    public $MRM = null;
111
-
112
-
113
-    /**
114
-     * Holds the Assets Registry instance
115
-     * @var Registry
116
-     */
117
-    public $AssetsRegistry = null;
118
-
119
-    /**
120
-     *    $addons - StdClass object for holding addons which have registered themselves to work with EE core
121
-     *
122
-     * @access    public
123
-     * @var    EE_Addon[]
124
-     */
125
-    public $addons = null;
126
-
127
-    /**
128
-     *    $models
129
-     * @access    public
130
-     * @var    EEM_Base[] $models keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
131
-     */
132
-    public $models = array();
133
-
134
-    /**
135
-     *    $modules
136
-     * @access    public
137
-     * @var    EED_Module[] $modules
138
-     */
139
-    public $modules = null;
140
-
141
-    /**
142
-     *    $shortcodes
143
-     * @access    public
144
-     * @var    EES_Shortcode[] $shortcodes
145
-     */
146
-    public $shortcodes = null;
147
-
148
-    /**
149
-     *    $widgets
150
-     * @access    public
151
-     * @var    WP_Widget[] $widgets
152
-     */
153
-    public $widgets = null;
154
-
155
-    /**
156
-     * $non_abstract_db_models
157
-     * @access public
158
-     * @var array this is an array of all implemented model names (i.e. not the parent abstract models, or models
159
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
160
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
161
-     * classnames (eg "EEM_Event")
162
-     */
163
-    public $non_abstract_db_models = array();
164
-
165
-
166
-    /**
167
-     *    $i18n_js_strings - internationalization for JS strings
168
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = __( 'string to translate.', 'event_espresso' );
169
-     *    in js file:  var translatedString = eei18n.string_key;
170
-     *
171
-     * @access    public
172
-     * @var    array
173
-     */
174
-    public static $i18n_js_strings = array();
175
-
176
-
177
-    /**
178
-     *    $main_file - path to espresso.php
179
-     *
180
-     * @access    public
181
-     * @var    array
182
-     */
183
-    public $main_file;
184
-
185
-    /**
186
-     * array of ReflectionClass objects where the key is the class name
187
-     *
188
-     * @access    public
189
-     * @var ReflectionClass[]
190
-     */
191
-    public $_reflectors;
192
-
193
-    /**
194
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
195
-     *
196
-     * @access    protected
197
-     * @var boolean $_cache_on
198
-     */
199
-    protected $_cache_on = true;
200
-
201
-
202
-
203
-    /**
204
-     * @singleton method used to instantiate class object
205
-     * @access    public
206
-     * @param  \EE_Dependency_Map $dependency_map
207
-     * @return \EE_Registry instance
208
-     */
209
-    public static function instance(\EE_Dependency_Map $dependency_map = null)
210
-    {
211
-        // check if class object is instantiated
212
-        if ( ! self::$_instance instanceof EE_Registry) {
213
-            self::$_instance = new EE_Registry($dependency_map);
214
-        }
215
-        return self::$_instance;
216
-    }
217
-
218
-
219
-
220
-    /**
221
-     *protected constructor to prevent direct creation
222
-     *
223
-     * @Constructor
224
-     * @access protected
225
-     * @param  \EE_Dependency_Map $dependency_map
226
-     */
227
-    protected function __construct(\EE_Dependency_Map $dependency_map)
228
-    {
229
-        $this->_dependency_map = $dependency_map;
230
-        $this->LIB = new stdClass();
231
-        $this->addons = new stdClass();
232
-        $this->modules = new stdClass();
233
-        $this->shortcodes = new stdClass();
234
-        $this->widgets = new stdClass();
235
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     * initialize
242
-     */
243
-    public function initialize()
244
-    {
245
-        $this->_class_abbreviations = apply_filters(
246
-            'FHEE__EE_Registry____construct___class_abbreviations',
247
-            array(
248
-                'EE_Config'                                       => 'CFG',
249
-                'EE_Session'                                      => 'SSN',
250
-                'EE_Capabilities'                                 => 'CAP',
251
-                'EE_Cart'                                         => 'CART',
252
-                'EE_Network_Config'                               => 'NET_CFG',
253
-                'EE_Request_Handler'                              => 'REQ',
254
-                'EE_Message_Resource_Manager'                     => 'MRM',
255
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
256
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
257
-            )
258
-        );
259
-        $this->load_core('Base', array(), true);
260
-        // add our request and response objects to the cache
261
-        $request_loader = $this->_dependency_map->class_loader('EE_Request');
262
-        $this->_set_cached_class(
263
-            $request_loader(),
264
-            'EE_Request'
265
-        );
266
-        $response_loader = $this->_dependency_map->class_loader('EE_Response');
267
-        $this->_set_cached_class(
268
-            $response_loader(),
269
-            'EE_Response'
270
-        );
271
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
272
-    }
273
-
274
-
275
-
276
-    /**
277
-     *    init
278
-     *
279
-     * @access    public
280
-     * @return    void
281
-     */
282
-    public function init()
283
-    {
284
-        // Get current page protocol
285
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
286
-        // Output admin-ajax.php URL with same protocol as current page
287
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
288
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
289
-    }
290
-
291
-
292
-
293
-    /**
294
-     * localize_i18n_js_strings
295
-     *
296
-     * @return string
297
-     */
298
-    public static function localize_i18n_js_strings()
299
-    {
300
-        $i18n_js_strings = (array)EE_Registry::$i18n_js_strings;
301
-        foreach ($i18n_js_strings as $key => $value) {
302
-            if (is_scalar($value)) {
303
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
304
-            }
305
-        }
306
-        return "/* <![CDATA[ */ var eei18n = " . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     * @param mixed string | EED_Module $module
313
-     */
314
-    public function add_module($module)
315
-    {
316
-        if ($module instanceof EED_Module) {
317
-            $module_class = get_class($module);
318
-            $this->modules->{$module_class} = $module;
319
-        } else {
320
-            if ( ! class_exists('EE_Module_Request_Router', false)) {
321
-                $this->load_core('Module_Request_Router');
322
-            }
323
-            $this->modules->{$module} = EE_Module_Request_Router::module_factory($module);
324
-        }
325
-    }
326
-
327
-
328
-
329
-    /**
330
-     * @param string $module_name
331
-     * @return mixed EED_Module | NULL
332
-     */
333
-    public function get_module($module_name = '')
334
-    {
335
-        return isset($this->modules->{$module_name}) ? $this->modules->{$module_name} : null;
336
-    }
337
-
338
-
339
-
340
-    /**
341
-     *    loads core classes - must be singletons
342
-     *
343
-     * @access    public
344
-     * @param string $class_name - simple class name ie: session
345
-     * @param mixed  $arguments
346
-     * @param bool   $load_only
347
-     * @return mixed
348
-     */
349
-    public function load_core($class_name, $arguments = array(), $load_only = false)
350
-    {
351
-        $core_paths = apply_filters(
352
-            'FHEE__EE_Registry__load_core__core_paths',
353
-            array(
354
-                EE_CORE,
355
-                EE_ADMIN,
356
-                EE_CPTS,
357
-                EE_CORE . 'data_migration_scripts' . DS,
358
-                EE_CORE . 'request_stack' . DS,
359
-                EE_CORE . 'middleware' . DS,
360
-            )
361
-        );
362
-        // retrieve instantiated class
363
-        return $this->_load($core_paths, 'EE_', $class_name, 'core', $arguments, false, true, $load_only);
364
-    }
365
-
366
-
367
-
368
-    /**
369
-     *    loads service classes
370
-     *
371
-     * @access    public
372
-     * @param string $class_name - simple class name ie: session
373
-     * @param mixed  $arguments
374
-     * @param bool   $load_only
375
-     * @return mixed
376
-     */
377
-    public function load_service($class_name, $arguments = array(), $load_only = false)
378
-    {
379
-        $service_paths = apply_filters(
380
-            'FHEE__EE_Registry__load_service__service_paths',
381
-            array(
382
-                EE_CORE . 'services' . DS,
383
-            )
384
-        );
385
-        // retrieve instantiated class
386
-        return $this->_load($service_paths, 'EE_', $class_name, 'class', $arguments, false, true, $load_only);
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     *    loads data_migration_scripts
393
-     *
394
-     * @access    public
395
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
396
-     * @param mixed  $arguments
397
-     * @return EE_Data_Migration_Script_Base|mixed
398
-     */
399
-    public function load_dms($class_name, $arguments = array())
400
-    {
401
-        // retrieve instantiated class
402
-        return $this->_load(EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(), 'EE_DMS_', $class_name, 'dms', $arguments, false, false, false);
403
-    }
404
-
405
-
406
-
407
-    /**
408
-     *    loads object creating classes - must be singletons
409
-     *
410
-     * @param string $class_name - simple class name ie: attendee
411
-     * @param mixed  $arguments  - an array of arguments to pass to the class
412
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to instantiate
413
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then set this to FALSE (ie. when instantiating model objects from client in a loop)
414
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate (default)
415
-     * @return EE_Base_Class | bool
416
-     */
417
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
418
-    {
419
-        $paths = apply_filters('FHEE__EE_Registry__load_class__paths', array(
420
-            EE_CORE,
421
-            EE_CLASSES,
422
-            EE_BUSINESS,
423
-        ));
424
-        // retrieve instantiated class
425
-        return $this->_load($paths, 'EE_', $class_name, 'class', $arguments, $from_db, $cache, $load_only);
426
-    }
427
-
428
-
429
-
430
-    /**
431
-     *    loads helper classes - must be singletons
432
-     *
433
-     * @param string $class_name - simple class name ie: price
434
-     * @param mixed  $arguments
435
-     * @param bool   $load_only
436
-     * @return EEH_Base | bool
437
-     */
438
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
439
-    {
440
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
441
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
442
-        // retrieve instantiated class
443
-        return $this->_load($helper_paths, 'EEH_', $class_name, 'helper', $arguments, false, true, $load_only);
444
-    }
445
-
446
-
447
-
448
-    /**
449
-     *    loads core classes - must be singletons
450
-     *
451
-     * @access    public
452
-     * @param string $class_name - simple class name ie: session
453
-     * @param mixed  $arguments
454
-     * @param bool   $load_only
455
-     * @param bool   $cache      whether to cache the object or not.
456
-     * @return mixed
457
-     */
458
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
459
-    {
460
-        $paths = array(
461
-            EE_LIBRARIES,
462
-            EE_LIBRARIES . 'messages' . DS,
463
-            EE_LIBRARIES . 'shortcodes' . DS,
464
-            EE_LIBRARIES . 'qtips' . DS,
465
-            EE_LIBRARIES . 'payment_methods' . DS,
466
-            EE_LIBRARIES . 'messages' . DS . 'defaults' . DS,
467
-        );
468
-        // retrieve instantiated class
469
-        return $this->_load($paths, 'EE_', $class_name, 'lib', $arguments, false, $cache, $load_only);
470
-    }
471
-
472
-
473
-
474
-    /**
475
-     *    loads model classes - must be singletons
476
-     *
477
-     * @param string $class_name - simple class name ie: price
478
-     * @param mixed  $arguments
479
-     * @param bool   $load_only
480
-     * @return EEM_Base | bool
481
-     */
482
-    public function load_model($class_name, $arguments = array(), $load_only = false)
483
-    {
484
-        $paths = apply_filters('FHEE__EE_Registry__load_model__paths', array(
485
-            EE_MODELS,
486
-            EE_CORE,
487
-        ));
488
-        // retrieve instantiated class
489
-        return $this->_load($paths, 'EEM_', $class_name, 'model', $arguments, false, true, $load_only);
490
-    }
491
-
492
-
493
-
494
-    /**
495
-     *    loads model classes - must be singletons
496
-     *
497
-     * @param string $class_name - simple class name ie: price
498
-     * @param mixed  $arguments
499
-     * @param bool   $load_only
500
-     * @return mixed | bool
501
-     */
502
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
503
-    {
504
-        $paths = array(
505
-            EE_MODELS . 'fields' . DS,
506
-            EE_MODELS . 'helpers' . DS,
507
-            EE_MODELS . 'relations' . DS,
508
-            EE_MODELS . 'strategies' . DS,
509
-        );
510
-        // retrieve instantiated class
511
-        return $this->_load($paths, 'EE_', $class_name, '', $arguments, false, true, $load_only);
512
-    }
513
-
514
-
515
-
516
-    /**
517
-     * Determines if $model_name is the name of an actual EE model.
518
-     *
519
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
520
-     * @return boolean
521
-     */
522
-    public function is_model_name($model_name)
523
-    {
524
-        return isset($this->models[$model_name]) ? true : false;
525
-    }
526
-
527
-
528
-
529
-    /**
530
-     *    generic class loader
531
-     *
532
-     * @param string $path_to_file - directory path to file location, not including filename
533
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
534
-     * @param string $type         - file type - core? class? helper? model?
535
-     * @param mixed  $arguments
536
-     * @param bool   $load_only
537
-     * @return mixed
538
-     */
539
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
540
-    {
541
-        // retrieve instantiated class
542
-        return $this->_load($path_to_file, '', $file_name, $type, $arguments, false, true, $load_only);
543
-    }
544
-
545
-
546
-
547
-    /**
548
-     *    load_addon
549
-     *
550
-     * @param string $path_to_file - directory path to file location, not including filename
551
-     * @param string $class_name   - full class name  ie:  My_Class
552
-     * @param string $type         - file type - core? class? helper? model?
553
-     * @param mixed  $arguments
554
-     * @param bool   $load_only
555
-     * @return EE_Addon
556
-     */
557
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
558
-    {
559
-        // retrieve instantiated class
560
-        return $this->_load($path_to_file, 'addon', $class_name, $type, $arguments, false, true, $load_only);
561
-    }
562
-
563
-
564
-
565
-    /**
566
-     * instantiates, caches, and automatically resolves dependencies
567
-     * for classes that use a Fully Qualified Class Name.
568
-     * if the class is not capable of being loaded using PSR-4 autoloading,
569
-     * then you need to use one of the existing load_*() methods
570
-     * which can resolve the classname and filepath from the passed arguments
571
-     *
572
-     * @param bool|string $class_name   Fully Qualified Class Name
573
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
574
-     * @param bool        $cache        whether to cache the instantiated object for reuse
575
-     * @param bool        $from_db      some classes are instantiated from the db
576
-     *                                  and thus call a different method to instantiate
577
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
578
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
579
-     * @return mixed                    null = failure to load or instantiate class object.
580
-     *                                  object = class loaded and instantiated successfully.
581
-     *                                  bool = fail or success when $load_only is true
582
-     */
583
-    public function create(
584
-        $class_name = false,
585
-        $arguments = array(),
586
-        $cache = false,
587
-        $from_db = false,
588
-        $load_only = false,
589
-        $addon = false
590
-    ) {
591
-        $class_name = ltrim($class_name, '\\');
592
-        $class_name = $this->_dependency_map->get_alias($class_name);
593
-        if ( ! class_exists($class_name)) {
594
-            // maybe the class is registered with a preceding \
595
-            $class_name = strpos($class_name, '\\') !== 0 ? '\\' . $class_name : $class_name;
596
-            // still doesn't exist ?
597
-            if ( ! class_exists($class_name)) {
598
-                return null;
599
-            }
600
-        }
601
-        // if we're only loading the class and it already exists, then let's just return true immediately
602
-        if ($load_only) {
603
-            return true;
604
-        }
605
-        $addon = $addon ? 'addon' : '';
606
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
607
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
608
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
609
-        if ($this->_cache_on && $cache && ! $load_only) {
610
-            // return object if it's already cached
611
-            $cached_class = $this->_get_cached_class($class_name, $addon);
612
-            if ($cached_class !== null) {
613
-                return $cached_class;
614
-            }
615
-        }
616
-        // instantiate the requested object
617
-        $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
618
-        if ($this->_cache_on && $cache) {
619
-            // save it for later... kinda like gum  { : $
620
-            $this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
621
-        }
622
-        $this->_cache_on = true;
623
-        return $class_obj;
624
-    }
625
-
626
-
627
-
628
-    /**
629
-     * instantiates, caches, and injects dependencies for classes
630
-     *
631
-     * @param array       $file_paths   an array of paths to folders to look in
632
-     * @param string      $class_prefix EE  or EEM or... ???
633
-     * @param bool|string $class_name   $class name
634
-     * @param string      $type         file type - core? class? helper? model?
635
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
636
-     * @param bool        $from_db      some classes are instantiated from the db
637
-     *                                  and thus call a different method to instantiate
638
-     * @param bool        $cache        whether to cache the instantiated object for reuse
639
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
640
-     * @return null|object|bool         null = failure to load or instantiate class object.
641
-     *                                  object = class loaded and instantiated successfully.
642
-     *                                  bool = fail or success when $load_only is true
643
-     */
644
-    protected function _load(
645
-        $file_paths = array(),
646
-        $class_prefix = 'EE_',
647
-        $class_name = false,
648
-        $type = 'class',
649
-        $arguments = array(),
650
-        $from_db = false,
651
-        $cache = true,
652
-        $load_only = false
653
-    ) {
654
-        $class_name = ltrim($class_name, '\\');
655
-        // strip php file extension
656
-        $class_name = str_replace('.php', '', trim($class_name));
657
-        // does the class have a prefix ?
658
-        if ( ! empty($class_prefix) && $class_prefix != 'addon') {
659
-            // make sure $class_prefix is uppercase
660
-            $class_prefix = strtoupper(trim($class_prefix));
661
-            // add class prefix ONCE!!!
662
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
663
-        }
664
-        $class_name = $this->_dependency_map->get_alias($class_name);
665
-        $class_exists = class_exists($class_name, false);
666
-        // if we're only loading the class and it already exists, then let's just return true immediately
667
-        if ($load_only && $class_exists) {
668
-            return true;
669
-        }
670
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
671
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
672
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
673
-        if ($this->_cache_on && $cache && ! $load_only) {
674
-            // return object if it's already cached
675
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix);
676
-            if ($cached_class !== null) {
677
-                return $cached_class;
678
-            }
679
-        }
680
-        // if the class doesn't already exist.. then we need to try and find the file and load it
681
-        if ( ! $class_exists) {
682
-            // get full path to file
683
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
684
-            // load the file
685
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
686
-            // if loading failed, or we are only loading a file but NOT instantiating an object
687
-            if ( ! $loaded || $load_only) {
688
-                // return boolean if only loading, or null if an object was expected
689
-                return $load_only ? $loaded : null;
690
-            }
691
-        }
692
-        // instantiate the requested object
693
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
694
-        if ($this->_cache_on && $cache) {
695
-            // save it for later... kinda like gum  { : $
696
-            $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
697
-        }
698
-        $this->_cache_on = true;
699
-        return $class_obj;
700
-    }
701
-
702
-
703
-
704
-
705
-    /**
706
-     * _get_cached_class
707
-     * attempts to find a cached version of the requested class
708
-     * by looking in the following places:
709
-     *        $this->{$class_abbreviation}            ie:    $this->CART
710
-     *        $this->{$class_name}                        ie:    $this->Some_Class
711
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
712
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
713
-     *
714
-     * @access protected
715
-     * @param string $class_name
716
-     * @param string $class_prefix
717
-     * @return mixed
718
-     */
719
-    protected function _get_cached_class($class_name, $class_prefix = '')
720
-    {
721
-        if ($class_name === 'EE_Registry') {
722
-            return $this;
723
-        }
724
-        // have to specify something, but not anything that will conflict
725
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
726
-            ? $this->_class_abbreviations[ $class_name ]
727
-            : 'FANCY_BATMAN_PANTS';
728
-        $class_name = str_replace('\\', '_', $class_name);
729
-        // check if class has already been loaded, and return it if it has been
730
-        if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
731
-            return $this->{$class_abbreviation};
732
-        }
733
-        if (isset ($this->{$class_name})) {
734
-            return $this->{$class_name};
735
-        }
736
-        if (isset ($this->LIB->{$class_name})) {
737
-            return $this->LIB->{$class_name};
738
-        }
739
-        if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
740
-            return $this->addons->{$class_name};
741
-        }
742
-        return null;
743
-    }
744
-
745
-
746
-
747
-    /**
748
-     * removes a cached version of the requested class
749
-     *
750
-     * @param string $class_name
751
-     * @param boolean $addon
752
-     * @return boolean
753
-     */
754
-    public function clear_cached_class($class_name, $addon = false)
755
-    {
756
-        // have to specify something, but not anything that will conflict
757
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
758
-            ? $this->_class_abbreviations[ $class_name ]
759
-            : 'FANCY_BATMAN_PANTS';
760
-        $class_name = str_replace('\\', '_', $class_name);
761
-        // check if class has already been loaded, and return it if it has been
762
-        if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
763
-            $this->{$class_abbreviation} = null;
764
-            return true;
765
-        }
766
-        if (isset($this->{$class_name})) {
767
-            $this->{$class_name} = null;
768
-            return true;
769
-        }
770
-        if (isset($this->LIB->{$class_name})) {
771
-            unset($this->LIB->{$class_name});
772
-            return true;
773
-        }
774
-        if ($addon && isset($this->addons->{$class_name})) {
775
-            unset($this->addons->{$class_name});
776
-            return true;
777
-        }
778
-        return false;
779
-    }
780
-
781
-
782
-    /**
783
-     * _resolve_path
784
-     * attempts to find a full valid filepath for the requested class.
785
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
786
-     * then returns that path if the target file has been found and is readable
787
-     *
788
-     * @access protected
789
-     * @param string $class_name
790
-     * @param string $type
791
-     * @param array  $file_paths
792
-     * @return string | bool
793
-     */
794
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
795
-    {
796
-        // make sure $file_paths is an array
797
-        $file_paths = is_array($file_paths) ? $file_paths : array($file_paths);
798
-        // cycle thru paths
799
-        foreach ($file_paths as $key => $file_path) {
800
-            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
801
-            $file_path = $file_path ? str_replace(array('/', '\\'), DS, $file_path) : EE_CLASSES;
802
-            // prep file type
803
-            $type = ! empty($type) ? trim($type, '.') . '.' : '';
804
-            // build full file path
805
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
806
-            //does the file exist and can be read ?
807
-            if (is_readable($file_paths[$key])) {
808
-                return $file_paths[$key];
809
-            }
810
-        }
811
-        return false;
812
-    }
813
-
814
-
815
-
816
-    /**
817
-     * _require_file
818
-     * basically just performs a require_once()
819
-     * but with some error handling
820
-     *
821
-     * @access protected
822
-     * @param  string $path
823
-     * @param  string $class_name
824
-     * @param  string $type
825
-     * @param  array  $file_paths
826
-     * @return boolean
827
-     * @throws \EE_Error
828
-     */
829
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
830
-    {
831
-        $this->resolve_legacy_class_parent($class_name);
832
-        // don't give up! you gotta...
833
-        try {
834
-            //does the file exist and can it be read ?
835
-            if ( ! $path) {
836
-                // so sorry, can't find the file
837
-                throw new EE_Error (
838
-                    sprintf(
839
-                        __('The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s', 'event_espresso'),
840
-                        trim($type, '.'),
841
-                        $class_name,
842
-                        '<br />' . implode(',<br />', $file_paths)
843
-                    )
844
-                );
845
-            }
846
-            // get the file
847
-            require_once($path);
848
-            // if the class isn't already declared somewhere
849
-            if (class_exists($class_name, false) === false) {
850
-                // so sorry, not a class
851
-                throw new EE_Error(
852
-                    sprintf(
853
-                        __('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
854
-                        $type,
855
-                        $path,
856
-                        $class_name
857
-                    )
858
-                );
859
-            }
860
-        } catch (EE_Error $e) {
861
-            $e->get_error();
862
-            return false;
863
-        }
864
-        return true;
865
-    }
866
-
867
-
868
-
869
-    /**
870
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
871
-     * before their class declaration in order to ensure that the parent class was loaded.
872
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
873
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
874
-     *
875
-     * @param string $class_name
876
-     */
877
-    protected function resolve_legacy_class_parent($class_name = '')
878
-    {
879
-        try {
880
-            $legacy_parent_class_map = array(
881
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
882
-            );
883
-            if(isset($legacy_parent_class_map[$class_name])) {
884
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
885
-            }
886
-        } catch (Exception $exception) {
887
-        }
888
-    }
889
-
890
-
891
-
892
-    /**
893
-     * _create_object
894
-     * Attempts to instantiate the requested class via any of the
895
-     * commonly used instantiation methods employed throughout EE.
896
-     * The priority for instantiation is as follows:
897
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
898
-     *        - model objects via their 'new_instance_from_db' method
899
-     *        - model objects via their 'new_instance' method
900
-     *        - "singleton" classes" via their 'instance' method
901
-     *    - standard instantiable classes via their __constructor
902
-     * Prior to instantiation, if the classname exists in the dependency_map,
903
-     * then the constructor for the requested class will be examined to determine
904
-     * if any dependencies exist, and if they can be injected.
905
-     * If so, then those classes will be added to the array of arguments passed to the constructor
906
-     *
907
-     * @access protected
908
-     * @param string $class_name
909
-     * @param array  $arguments
910
-     * @param string $type
911
-     * @param bool   $from_db
912
-     * @return null | object
913
-     * @throws \EE_Error
914
-     */
915
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
916
-    {
917
-        $class_obj = null;
918
-        $instantiation_mode = '0) none';
919
-        // don't give up! you gotta...
920
-        try {
921
-            // create reflection
922
-            $reflector = $this->get_ReflectionClass($class_name);
923
-            // make sure arguments are an array
924
-            $arguments = is_array($arguments) ? $arguments : array($arguments);
925
-            // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
926
-            // else wrap it in an additional array so that it doesn't get split into multiple parameters
927
-            $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
928
-                ? $arguments
929
-                : array($arguments);
930
-            // attempt to inject dependencies ?
931
-            if ($this->_dependency_map->has($class_name)) {
932
-                $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
933
-            }
934
-            // instantiate the class if possible
935
-            if ($reflector->isAbstract()) {
936
-                // nothing to instantiate, loading file was enough
937
-                // does not throw an exception so $instantiation_mode is unused
938
-                // $instantiation_mode = "1) no constructor abstract class";
939
-                $class_obj = true;
940
-            } else if ($reflector->getConstructor() === null && $reflector->isInstantiable() && empty($arguments)) {
941
-                // no constructor = static methods only... nothing to instantiate, loading file was enough
942
-                $instantiation_mode = "2) no constructor but instantiable";
943
-                $class_obj = $reflector->newInstance();
944
-            } else if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
945
-                $instantiation_mode = "3) new_instance_from_db()";
946
-                $class_obj = call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
947
-            } else if (method_exists($class_name, 'new_instance')) {
948
-                $instantiation_mode = "4) new_instance()";
949
-                $class_obj = call_user_func_array(array($class_name, 'new_instance'), $arguments);
950
-            } else if (method_exists($class_name, 'instance')) {
951
-                $instantiation_mode = "5) instance()";
952
-                $class_obj = call_user_func_array(array($class_name, 'instance'), $arguments);
953
-            } else if ($reflector->isInstantiable()) {
954
-                $instantiation_mode = "6) constructor";
955
-                $class_obj = $reflector->newInstanceArgs($arguments);
956
-            } else {
957
-                // heh ? something's not right !
958
-                throw new EE_Error(
959
-                    sprintf(
960
-                        __('The %s file %s could not be instantiated.', 'event_espresso'),
961
-                        $type,
962
-                        $class_name
963
-                    )
964
-                );
965
-            }
966
-        } catch (Exception $e) {
967
-            if ( ! $e instanceof EE_Error) {
968
-                $e = new EE_Error(
969
-                    sprintf(
970
-                        __('The following error occurred while attempting to instantiate "%1$s": %2$s %3$s %2$s instantiation mode : %4$s', 'event_espresso'),
971
-                        $class_name,
972
-                        '<br />',
973
-                        $e->getMessage(),
974
-                        $instantiation_mode
975
-                    )
976
-                );
977
-            }
978
-            $e->get_error();
979
-        }
980
-        return $class_obj;
981
-    }
982
-
983
-
984
-
985
-    /**
986
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
987
-     * @param array $array
988
-     * @return bool
989
-     */
990
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
991
-    {
992
-        return ! empty($array) ? array_keys($array) === range(0, count($array) - 1) : true;
993
-    }
994
-
995
-
996
-
997
-    /**
998
-     * getReflectionClass
999
-     * checks if a ReflectionClass object has already been generated for a class
1000
-     * and returns that instead of creating a new one
1001
-     *
1002
-     * @access public
1003
-     * @param string $class_name
1004
-     * @return ReflectionClass
1005
-     */
1006
-    public function get_ReflectionClass($class_name)
1007
-    {
1008
-        if (
1009
-            ! isset($this->_reflectors[$class_name])
1010
-            || ! $this->_reflectors[$class_name] instanceof ReflectionClass
1011
-        ) {
1012
-            $this->_reflectors[$class_name] = new ReflectionClass($class_name);
1013
-        }
1014
-        return $this->_reflectors[$class_name];
1015
-    }
1016
-
1017
-
1018
-
1019
-    /**
1020
-     * _resolve_dependencies
1021
-     * examines the constructor for the requested class to determine
1022
-     * if any dependencies exist, and if they can be injected.
1023
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1024
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1025
-     * For example:
1026
-     *        if attempting to load a class "Foo" with the following constructor:
1027
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1028
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1029
-     *        but only IF they are NOT already present in the incoming arguments array,
1030
-     *        and the correct classes can be loaded
1031
-     *
1032
-     * @access protected
1033
-     * @param ReflectionClass $reflector
1034
-     * @param string          $class_name
1035
-     * @param array           $arguments
1036
-     * @return array
1037
-     * @throws \ReflectionException
1038
-     */
1039
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1040
-    {
1041
-        // let's examine the constructor
1042
-        $constructor = $reflector->getConstructor();
1043
-        // whu? huh? nothing?
1044
-        if ( ! $constructor) {
1045
-            return $arguments;
1046
-        }
1047
-        // get constructor parameters
1048
-        $params = $constructor->getParameters();
1049
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1050
-        $argument_keys = array_keys($arguments);
1051
-        // now loop thru all of the constructors expected parameters
1052
-        foreach ($params as $index => $param) {
1053
-            // is this a dependency for a specific class ?
1054
-            $param_class = $param->getClass() ? $param->getClass()->name : null;
1055
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1056
-            $param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1057
-                ? $this->_dependency_map->get_alias($param_class, $class_name)
1058
-                : $param_class;
1059
-            if (
1060
-                // param is not even a class
1061
-                empty($param_class)
1062
-                // and something already exists in the incoming arguments for this param
1063
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1064
-            ) {
1065
-                // so let's skip this argument and move on to the next
1066
-                continue;
1067
-            }
1068
-            if (
1069
-                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1070
-                ! empty($param_class)
1071
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1072
-                && $arguments[$argument_keys[$index]] instanceof $param_class
1073
-            ) {
1074
-                // skip this argument and move on to the next
1075
-                continue;
1076
-            }
1077
-            if (
1078
-                // parameter is type hinted as a class, and should be injected
1079
-                ! empty($param_class)
1080
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1081
-            ) {
1082
-                $arguments = $this->_resolve_dependency($class_name, $param_class, $arguments, $index);
1083
-            } else {
1084
-                try {
1085
-                    $arguments[$index] = $param->getDefaultValue();
1086
-                } catch (ReflectionException $e) {
1087
-                    throw new ReflectionException(
1088
-                        sprintf(
1089
-                            __('%1$s for parameter "$%2$s"', 'event_espresso'),
1090
-                            $e->getMessage(),
1091
-                            $param->getName()
1092
-                        )
1093
-                    );
1094
-                }
1095
-            }
1096
-        }
1097
-        return $arguments;
1098
-    }
1099
-
1100
-
1101
-
1102
-    /**
1103
-     * @access protected
1104
-     * @param string $class_name
1105
-     * @param string $param_class
1106
-     * @param array  $arguments
1107
-     * @param mixed  $index
1108
-     * @return array
1109
-     */
1110
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1111
-    {
1112
-        $dependency = null;
1113
-        // should dependency be loaded from cache ?
1114
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency($class_name, $param_class)
1115
-                    !== EE_Dependency_Map::load_new_object
1116
-            ? true
1117
-            : false;
1118
-        // we might have a dependency...
1119
-        // let's MAYBE try and find it in our cache if that's what's been requested
1120
-        $cached_class = $cache_on ? $this->_get_cached_class($param_class) : null;
1121
-        // and grab it if it exists
1122
-        if ($cached_class instanceof $param_class) {
1123
-            $dependency = $cached_class;
1124
-        } else if ($param_class !== $class_name) {
1125
-            // obtain the loader method from the dependency map
1126
-            $loader = $this->_dependency_map->class_loader($param_class);
1127
-            // is loader a custom closure ?
1128
-            if ($loader instanceof Closure) {
1129
-                $dependency = $loader();
1130
-            } else {
1131
-                // set the cache on property for the recursive loading call
1132
-                $this->_cache_on = $cache_on;
1133
-                // if not, then let's try and load it via the registry
1134
-                if ($loader && method_exists($this, $loader)) {
1135
-                    $dependency = $this->{$loader}($param_class);
1136
-                } else {
1137
-                    $dependency = $this->create($param_class, array(), $cache_on);
1138
-                }
1139
-            }
1140
-        }
1141
-        // did we successfully find the correct dependency ?
1142
-        if ($dependency instanceof $param_class) {
1143
-            // then let's inject it into the incoming array of arguments at the correct location
1144
-            if (isset($argument_keys[$index])) {
1145
-                $arguments[$argument_keys[$index]] = $dependency;
1146
-            } else {
1147
-                $arguments[$index] = $dependency;
1148
-            }
1149
-        }
1150
-        return $arguments;
1151
-    }
1152
-
1153
-
1154
-
1155
-    /**
1156
-     * _set_cached_class
1157
-     * attempts to cache the instantiated class locally
1158
-     * in one of the following places, in the following order:
1159
-     *        $this->{class_abbreviation}   ie:    $this->CART
1160
-     *        $this->{$class_name}          ie:    $this->Some_Class
1161
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1162
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1163
-     *
1164
-     * @access protected
1165
-     * @param object $class_obj
1166
-     * @param string $class_name
1167
-     * @param string $class_prefix
1168
-     * @param bool   $from_db
1169
-     * @return void
1170
-     */
1171
-    protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1172
-    {
1173
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1174
-            return;
1175
-        }
1176
-        // return newly instantiated class
1177
-        if (isset($this->_class_abbreviations[$class_name])) {
1178
-            $class_abbreviation = $this->_class_abbreviations[$class_name];
1179
-            $this->{$class_abbreviation} = $class_obj;
1180
-            return;
1181
-        }
1182
-        $class_name = str_replace('\\', '_', $class_name);
1183
-        if (property_exists($this, $class_name)) {
1184
-            $this->{$class_name} = $class_obj;
1185
-            return;
1186
-        }
1187
-        if ($class_prefix === 'addon') {
1188
-            $this->addons->{$class_name} = $class_obj;
1189
-            return;
1190
-        }
1191
-        if ( ! $from_db) {
1192
-            $this->LIB->{$class_name} = $class_obj;
1193
-        }
1194
-    }
1195
-
1196
-
1197
-
1198
-    /**
1199
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1200
-     *
1201
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1202
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1203
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1204
-     * @param array  $arguments
1205
-     * @return object
1206
-     */
1207
-    public static function factory($classname, $arguments = array())
1208
-    {
1209
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1210
-        if ($loader instanceof Closure) {
1211
-            return $loader($arguments);
1212
-        }
1213
-        if (method_exists(EE_Registry::instance(), $loader)) {
1214
-            return EE_Registry::instance()->{$loader}($classname, $arguments);
1215
-        }
1216
-        return null;
1217
-    }
1218
-
1219
-
1220
-
1221
-    /**
1222
-     * Gets the addon by its name/slug (not classname. For that, just
1223
-     * use the classname as the property name on EE_Config::instance()->addons)
1224
-     *
1225
-     * @param string $name
1226
-     * @return EE_Addon
1227
-     */
1228
-    public function get_addon_by_name($name)
1229
-    {
1230
-        foreach ($this->addons as $addon) {
1231
-            if ($addon->name() == $name) {
1232
-                return $addon;
1233
-            }
1234
-        }
1235
-        return null;
1236
-    }
1237
-
1238
-
1239
-
1240
-    /**
1241
-     * Gets an array of all the registered addons, where the keys are their names. (ie, what each returns for their name() function) They're already available on EE_Config::instance()->addons as properties, where each property's name is
1242
-     * the addon's classname. So if you just want to get the addon by classname, use EE_Config::instance()->addons->{classname}
1243
-     *
1244
-     * @return EE_Addon[] where the KEYS are the addon's name()
1245
-     */
1246
-    public function get_addons_by_name()
1247
-    {
1248
-        $addons = array();
1249
-        foreach ($this->addons as $addon) {
1250
-            $addons[$addon->name()] = $addon;
1251
-        }
1252
-        return $addons;
1253
-    }
1254
-
1255
-
1256
-
1257
-    /**
1258
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1259
-     * a stale copy of it around
1260
-     *
1261
-     * @param string $model_name
1262
-     * @return \EEM_Base
1263
-     * @throws \EE_Error
1264
-     */
1265
-    public function reset_model($model_name)
1266
-    {
1267
-        $model_class_name = strpos($model_name, 'EEM_') !== 0 ? "EEM_{$model_name}" : $model_name;
1268
-        if ( ! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1269
-            return null;
1270
-        }
1271
-        //get that model reset it and make sure we nuke the old reference to it
1272
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name && is_callable(array($model_class_name, 'reset'))) {
1273
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1274
-        } else {
1275
-            throw new EE_Error(sprintf(__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1276
-        }
1277
-        return $this->LIB->{$model_class_name};
1278
-    }
1279
-
1280
-
1281
-
1282
-    /**
1283
-     * Resets the registry.
1284
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when switch_to_blog
1285
-     * is used in a multisite install.  Here is a list of things that are NOT reset.
1286
-     * - $_dependency_map
1287
-     * - $_class_abbreviations
1288
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1289
-     * - $REQ:  Still on the same request so no need to change.
1290
-     * - $CAP: There is no site specific state in the EE_Capability class.
1291
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only one Session
1292
-     *         can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1293
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1294
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1295
-     *             switch or on the restore.
1296
-     * - $modules
1297
-     * - $shortcodes
1298
-     * - $widgets
1299
-     *
1300
-     * @param boolean $hard             whether to reset data in the database too, or just refresh
1301
-     *                                  the Registry to its state at the beginning of the request
1302
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1303
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not sure if you CAN
1304
-     *                                  currently reinstantiate the singletons at the moment)
1305
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so client
1306
-     *                                  code instead can just change the model context to a different blog id if necessary
1307
-     * @return EE_Registry
1308
-     */
1309
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1310
-    {
1311
-        $instance = self::instance();
1312
-        $instance->_cache_on = true;
1313
-        // reset some "special" classes
1314
-        EEH_Activation::reset();
1315
-        $instance->CFG = $instance->CFG->reset($hard, $reinstantiate);
1316
-        $instance->CART = null;
1317
-        $instance->MRM = null;
1318
-        $instance->AssetsRegistry = null;
1319
-        $instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1320
-        //messages reset
1321
-        EED_Messages::reset();
1322
-        //handle of objects cached on LIB
1323
-        foreach (array('LIB', 'modules', 'shortcodes') as $cache) {
1324
-            foreach ($instance->{$cache} as $class_name => $class) {
1325
-                if (EE_Registry::_reset_and_unset_object($class, $reset_models)) {
1326
-                    unset($instance->{$cache}->{$class_name});
1327
-                }
1328
-            }
1329
-        }
1330
-        return $instance;
1331
-    }
1332
-
1333
-
1334
-
1335
-    /**
1336
-     * if passed object implements ResettableInterface, then call it's reset() method
1337
-     * if passed object implements InterminableInterface, then return false,
1338
-     * to indicate that it should NOT be cleared from the Registry cache
1339
-     *
1340
-     * @param      $object
1341
-     * @param bool $reset_models
1342
-     * @return bool returns true if cached object should be unset
1343
-     */
1344
-    private static function _reset_and_unset_object($object, $reset_models)
1345
-    {
1346
-        static $count = 0;
1347
-        $count++;
1348
-        if ($object instanceof ResettableInterface) {
1349
-            if ($object instanceof EEM_Base) {
1350
-                if ($reset_models) {
1351
-                    $object->reset();
1352
-                    return true;
1353
-                }
1354
-                return false;
1355
-            }
1356
-            $object->reset();
1357
-            return true;
1358
-        }
1359
-        if ( ! $object instanceof InterminableInterface) {
1360
-            return true;
1361
-        }
1362
-        return false;
1363
-    }
1364
-
1365
-
1366
-
1367
-    /**
1368
-     * @override magic methods
1369
-     * @return void
1370
-     */
1371
-    public final function __destruct()
1372
-    {
1373
-    }
1374
-
1375
-
1376
-
1377
-    /**
1378
-     * @param $a
1379
-     * @param $b
1380
-     */
1381
-    public final function __call($a, $b)
1382
-    {
1383
-    }
1384
-
1385
-
1386
-
1387
-    /**
1388
-     * @param $a
1389
-     */
1390
-    public final function __get($a)
1391
-    {
1392
-    }
1393
-
1394
-
1395
-
1396
-    /**
1397
-     * @param $a
1398
-     * @param $b
1399
-     */
1400
-    public final function __set($a, $b)
1401
-    {
1402
-    }
1403
-
1404
-
1405
-
1406
-    /**
1407
-     * @param $a
1408
-     */
1409
-    public final function __isset($a)
1410
-    {
1411
-    }
22
+	/**
23
+	 *    EE_Registry Object
24
+	 *
25
+	 * @var EE_Registry $_instance
26
+	 * @access    private
27
+	 */
28
+	private static $_instance = null;
29
+
30
+	/**
31
+	 * @var EE_Dependency_Map $_dependency_map
32
+	 * @access    protected
33
+	 */
34
+	protected $_dependency_map = null;
35
+
36
+	/**
37
+	 * @var array $_class_abbreviations
38
+	 * @access    protected
39
+	 */
40
+	protected $_class_abbreviations = array();
41
+
42
+	/**
43
+	 * @access public
44
+	 * @var \EventEspresso\core\services\commands\CommandBusInterface $BUS
45
+	 */
46
+	public $BUS;
47
+
48
+	/**
49
+	 *    EE_Cart Object
50
+	 *
51
+	 * @access    public
52
+	 * @var    EE_Cart $CART
53
+	 */
54
+	public $CART = null;
55
+
56
+	/**
57
+	 *    EE_Config Object
58
+	 *
59
+	 * @access    public
60
+	 * @var    EE_Config $CFG
61
+	 */
62
+	public $CFG = null;
63
+
64
+	/**
65
+	 * EE_Network_Config Object
66
+	 *
67
+	 * @access public
68
+	 * @var EE_Network_Config $NET_CFG
69
+	 */
70
+	public $NET_CFG = null;
71
+
72
+	/**
73
+	 *    StdClass object for storing library classes in
74
+	 *
75
+	 * @public LIB
76
+	 * @var StdClass $LIB
77
+	 */
78
+	public $LIB = null;
79
+
80
+	/**
81
+	 *    EE_Request_Handler Object
82
+	 *
83
+	 * @access    public
84
+	 * @var    EE_Request_Handler $REQ
85
+	 */
86
+	public $REQ = null;
87
+
88
+	/**
89
+	 *    EE_Session Object
90
+	 *
91
+	 * @access    public
92
+	 * @var    EE_Session $SSN
93
+	 */
94
+	public $SSN = null;
95
+
96
+	/**
97
+	 * holds the ee capabilities object.
98
+	 *
99
+	 * @since 4.5.0
100
+	 * @var EE_Capabilities
101
+	 */
102
+	public $CAP = null;
103
+
104
+	/**
105
+	 * holds the EE_Message_Resource_Manager object.
106
+	 *
107
+	 * @since 4.9.0
108
+	 * @var EE_Message_Resource_Manager
109
+	 */
110
+	public $MRM = null;
111
+
112
+
113
+	/**
114
+	 * Holds the Assets Registry instance
115
+	 * @var Registry
116
+	 */
117
+	public $AssetsRegistry = null;
118
+
119
+	/**
120
+	 *    $addons - StdClass object for holding addons which have registered themselves to work with EE core
121
+	 *
122
+	 * @access    public
123
+	 * @var    EE_Addon[]
124
+	 */
125
+	public $addons = null;
126
+
127
+	/**
128
+	 *    $models
129
+	 * @access    public
130
+	 * @var    EEM_Base[] $models keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
131
+	 */
132
+	public $models = array();
133
+
134
+	/**
135
+	 *    $modules
136
+	 * @access    public
137
+	 * @var    EED_Module[] $modules
138
+	 */
139
+	public $modules = null;
140
+
141
+	/**
142
+	 *    $shortcodes
143
+	 * @access    public
144
+	 * @var    EES_Shortcode[] $shortcodes
145
+	 */
146
+	public $shortcodes = null;
147
+
148
+	/**
149
+	 *    $widgets
150
+	 * @access    public
151
+	 * @var    WP_Widget[] $widgets
152
+	 */
153
+	public $widgets = null;
154
+
155
+	/**
156
+	 * $non_abstract_db_models
157
+	 * @access public
158
+	 * @var array this is an array of all implemented model names (i.e. not the parent abstract models, or models
159
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
160
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
161
+	 * classnames (eg "EEM_Event")
162
+	 */
163
+	public $non_abstract_db_models = array();
164
+
165
+
166
+	/**
167
+	 *    $i18n_js_strings - internationalization for JS strings
168
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = __( 'string to translate.', 'event_espresso' );
169
+	 *    in js file:  var translatedString = eei18n.string_key;
170
+	 *
171
+	 * @access    public
172
+	 * @var    array
173
+	 */
174
+	public static $i18n_js_strings = array();
175
+
176
+
177
+	/**
178
+	 *    $main_file - path to espresso.php
179
+	 *
180
+	 * @access    public
181
+	 * @var    array
182
+	 */
183
+	public $main_file;
184
+
185
+	/**
186
+	 * array of ReflectionClass objects where the key is the class name
187
+	 *
188
+	 * @access    public
189
+	 * @var ReflectionClass[]
190
+	 */
191
+	public $_reflectors;
192
+
193
+	/**
194
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
195
+	 *
196
+	 * @access    protected
197
+	 * @var boolean $_cache_on
198
+	 */
199
+	protected $_cache_on = true;
200
+
201
+
202
+
203
+	/**
204
+	 * @singleton method used to instantiate class object
205
+	 * @access    public
206
+	 * @param  \EE_Dependency_Map $dependency_map
207
+	 * @return \EE_Registry instance
208
+	 */
209
+	public static function instance(\EE_Dependency_Map $dependency_map = null)
210
+	{
211
+		// check if class object is instantiated
212
+		if ( ! self::$_instance instanceof EE_Registry) {
213
+			self::$_instance = new EE_Registry($dependency_map);
214
+		}
215
+		return self::$_instance;
216
+	}
217
+
218
+
219
+
220
+	/**
221
+	 *protected constructor to prevent direct creation
222
+	 *
223
+	 * @Constructor
224
+	 * @access protected
225
+	 * @param  \EE_Dependency_Map $dependency_map
226
+	 */
227
+	protected function __construct(\EE_Dependency_Map $dependency_map)
228
+	{
229
+		$this->_dependency_map = $dependency_map;
230
+		$this->LIB = new stdClass();
231
+		$this->addons = new stdClass();
232
+		$this->modules = new stdClass();
233
+		$this->shortcodes = new stdClass();
234
+		$this->widgets = new stdClass();
235
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 * initialize
242
+	 */
243
+	public function initialize()
244
+	{
245
+		$this->_class_abbreviations = apply_filters(
246
+			'FHEE__EE_Registry____construct___class_abbreviations',
247
+			array(
248
+				'EE_Config'                                       => 'CFG',
249
+				'EE_Session'                                      => 'SSN',
250
+				'EE_Capabilities'                                 => 'CAP',
251
+				'EE_Cart'                                         => 'CART',
252
+				'EE_Network_Config'                               => 'NET_CFG',
253
+				'EE_Request_Handler'                              => 'REQ',
254
+				'EE_Message_Resource_Manager'                     => 'MRM',
255
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
256
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
257
+			)
258
+		);
259
+		$this->load_core('Base', array(), true);
260
+		// add our request and response objects to the cache
261
+		$request_loader = $this->_dependency_map->class_loader('EE_Request');
262
+		$this->_set_cached_class(
263
+			$request_loader(),
264
+			'EE_Request'
265
+		);
266
+		$response_loader = $this->_dependency_map->class_loader('EE_Response');
267
+		$this->_set_cached_class(
268
+			$response_loader(),
269
+			'EE_Response'
270
+		);
271
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
272
+	}
273
+
274
+
275
+
276
+	/**
277
+	 *    init
278
+	 *
279
+	 * @access    public
280
+	 * @return    void
281
+	 */
282
+	public function init()
283
+	{
284
+		// Get current page protocol
285
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
286
+		// Output admin-ajax.php URL with same protocol as current page
287
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
288
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
289
+	}
290
+
291
+
292
+
293
+	/**
294
+	 * localize_i18n_js_strings
295
+	 *
296
+	 * @return string
297
+	 */
298
+	public static function localize_i18n_js_strings()
299
+	{
300
+		$i18n_js_strings = (array)EE_Registry::$i18n_js_strings;
301
+		foreach ($i18n_js_strings as $key => $value) {
302
+			if (is_scalar($value)) {
303
+				$i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
304
+			}
305
+		}
306
+		return "/* <![CDATA[ */ var eei18n = " . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 * @param mixed string | EED_Module $module
313
+	 */
314
+	public function add_module($module)
315
+	{
316
+		if ($module instanceof EED_Module) {
317
+			$module_class = get_class($module);
318
+			$this->modules->{$module_class} = $module;
319
+		} else {
320
+			if ( ! class_exists('EE_Module_Request_Router', false)) {
321
+				$this->load_core('Module_Request_Router');
322
+			}
323
+			$this->modules->{$module} = EE_Module_Request_Router::module_factory($module);
324
+		}
325
+	}
326
+
327
+
328
+
329
+	/**
330
+	 * @param string $module_name
331
+	 * @return mixed EED_Module | NULL
332
+	 */
333
+	public function get_module($module_name = '')
334
+	{
335
+		return isset($this->modules->{$module_name}) ? $this->modules->{$module_name} : null;
336
+	}
337
+
338
+
339
+
340
+	/**
341
+	 *    loads core classes - must be singletons
342
+	 *
343
+	 * @access    public
344
+	 * @param string $class_name - simple class name ie: session
345
+	 * @param mixed  $arguments
346
+	 * @param bool   $load_only
347
+	 * @return mixed
348
+	 */
349
+	public function load_core($class_name, $arguments = array(), $load_only = false)
350
+	{
351
+		$core_paths = apply_filters(
352
+			'FHEE__EE_Registry__load_core__core_paths',
353
+			array(
354
+				EE_CORE,
355
+				EE_ADMIN,
356
+				EE_CPTS,
357
+				EE_CORE . 'data_migration_scripts' . DS,
358
+				EE_CORE . 'request_stack' . DS,
359
+				EE_CORE . 'middleware' . DS,
360
+			)
361
+		);
362
+		// retrieve instantiated class
363
+		return $this->_load($core_paths, 'EE_', $class_name, 'core', $arguments, false, true, $load_only);
364
+	}
365
+
366
+
367
+
368
+	/**
369
+	 *    loads service classes
370
+	 *
371
+	 * @access    public
372
+	 * @param string $class_name - simple class name ie: session
373
+	 * @param mixed  $arguments
374
+	 * @param bool   $load_only
375
+	 * @return mixed
376
+	 */
377
+	public function load_service($class_name, $arguments = array(), $load_only = false)
378
+	{
379
+		$service_paths = apply_filters(
380
+			'FHEE__EE_Registry__load_service__service_paths',
381
+			array(
382
+				EE_CORE . 'services' . DS,
383
+			)
384
+		);
385
+		// retrieve instantiated class
386
+		return $this->_load($service_paths, 'EE_', $class_name, 'class', $arguments, false, true, $load_only);
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 *    loads data_migration_scripts
393
+	 *
394
+	 * @access    public
395
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
396
+	 * @param mixed  $arguments
397
+	 * @return EE_Data_Migration_Script_Base|mixed
398
+	 */
399
+	public function load_dms($class_name, $arguments = array())
400
+	{
401
+		// retrieve instantiated class
402
+		return $this->_load(EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(), 'EE_DMS_', $class_name, 'dms', $arguments, false, false, false);
403
+	}
404
+
405
+
406
+
407
+	/**
408
+	 *    loads object creating classes - must be singletons
409
+	 *
410
+	 * @param string $class_name - simple class name ie: attendee
411
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
412
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to instantiate
413
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then set this to FALSE (ie. when instantiating model objects from client in a loop)
414
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate (default)
415
+	 * @return EE_Base_Class | bool
416
+	 */
417
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
418
+	{
419
+		$paths = apply_filters('FHEE__EE_Registry__load_class__paths', array(
420
+			EE_CORE,
421
+			EE_CLASSES,
422
+			EE_BUSINESS,
423
+		));
424
+		// retrieve instantiated class
425
+		return $this->_load($paths, 'EE_', $class_name, 'class', $arguments, $from_db, $cache, $load_only);
426
+	}
427
+
428
+
429
+
430
+	/**
431
+	 *    loads helper classes - must be singletons
432
+	 *
433
+	 * @param string $class_name - simple class name ie: price
434
+	 * @param mixed  $arguments
435
+	 * @param bool   $load_only
436
+	 * @return EEH_Base | bool
437
+	 */
438
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
439
+	{
440
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
441
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
442
+		// retrieve instantiated class
443
+		return $this->_load($helper_paths, 'EEH_', $class_name, 'helper', $arguments, false, true, $load_only);
444
+	}
445
+
446
+
447
+
448
+	/**
449
+	 *    loads core classes - must be singletons
450
+	 *
451
+	 * @access    public
452
+	 * @param string $class_name - simple class name ie: session
453
+	 * @param mixed  $arguments
454
+	 * @param bool   $load_only
455
+	 * @param bool   $cache      whether to cache the object or not.
456
+	 * @return mixed
457
+	 */
458
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
459
+	{
460
+		$paths = array(
461
+			EE_LIBRARIES,
462
+			EE_LIBRARIES . 'messages' . DS,
463
+			EE_LIBRARIES . 'shortcodes' . DS,
464
+			EE_LIBRARIES . 'qtips' . DS,
465
+			EE_LIBRARIES . 'payment_methods' . DS,
466
+			EE_LIBRARIES . 'messages' . DS . 'defaults' . DS,
467
+		);
468
+		// retrieve instantiated class
469
+		return $this->_load($paths, 'EE_', $class_name, 'lib', $arguments, false, $cache, $load_only);
470
+	}
471
+
472
+
473
+
474
+	/**
475
+	 *    loads model classes - must be singletons
476
+	 *
477
+	 * @param string $class_name - simple class name ie: price
478
+	 * @param mixed  $arguments
479
+	 * @param bool   $load_only
480
+	 * @return EEM_Base | bool
481
+	 */
482
+	public function load_model($class_name, $arguments = array(), $load_only = false)
483
+	{
484
+		$paths = apply_filters('FHEE__EE_Registry__load_model__paths', array(
485
+			EE_MODELS,
486
+			EE_CORE,
487
+		));
488
+		// retrieve instantiated class
489
+		return $this->_load($paths, 'EEM_', $class_name, 'model', $arguments, false, true, $load_only);
490
+	}
491
+
492
+
493
+
494
+	/**
495
+	 *    loads model classes - must be singletons
496
+	 *
497
+	 * @param string $class_name - simple class name ie: price
498
+	 * @param mixed  $arguments
499
+	 * @param bool   $load_only
500
+	 * @return mixed | bool
501
+	 */
502
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
503
+	{
504
+		$paths = array(
505
+			EE_MODELS . 'fields' . DS,
506
+			EE_MODELS . 'helpers' . DS,
507
+			EE_MODELS . 'relations' . DS,
508
+			EE_MODELS . 'strategies' . DS,
509
+		);
510
+		// retrieve instantiated class
511
+		return $this->_load($paths, 'EE_', $class_name, '', $arguments, false, true, $load_only);
512
+	}
513
+
514
+
515
+
516
+	/**
517
+	 * Determines if $model_name is the name of an actual EE model.
518
+	 *
519
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
520
+	 * @return boolean
521
+	 */
522
+	public function is_model_name($model_name)
523
+	{
524
+		return isset($this->models[$model_name]) ? true : false;
525
+	}
526
+
527
+
528
+
529
+	/**
530
+	 *    generic class loader
531
+	 *
532
+	 * @param string $path_to_file - directory path to file location, not including filename
533
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
534
+	 * @param string $type         - file type - core? class? helper? model?
535
+	 * @param mixed  $arguments
536
+	 * @param bool   $load_only
537
+	 * @return mixed
538
+	 */
539
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
540
+	{
541
+		// retrieve instantiated class
542
+		return $this->_load($path_to_file, '', $file_name, $type, $arguments, false, true, $load_only);
543
+	}
544
+
545
+
546
+
547
+	/**
548
+	 *    load_addon
549
+	 *
550
+	 * @param string $path_to_file - directory path to file location, not including filename
551
+	 * @param string $class_name   - full class name  ie:  My_Class
552
+	 * @param string $type         - file type - core? class? helper? model?
553
+	 * @param mixed  $arguments
554
+	 * @param bool   $load_only
555
+	 * @return EE_Addon
556
+	 */
557
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
558
+	{
559
+		// retrieve instantiated class
560
+		return $this->_load($path_to_file, 'addon', $class_name, $type, $arguments, false, true, $load_only);
561
+	}
562
+
563
+
564
+
565
+	/**
566
+	 * instantiates, caches, and automatically resolves dependencies
567
+	 * for classes that use a Fully Qualified Class Name.
568
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
569
+	 * then you need to use one of the existing load_*() methods
570
+	 * which can resolve the classname and filepath from the passed arguments
571
+	 *
572
+	 * @param bool|string $class_name   Fully Qualified Class Name
573
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
574
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
575
+	 * @param bool        $from_db      some classes are instantiated from the db
576
+	 *                                  and thus call a different method to instantiate
577
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
578
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
579
+	 * @return mixed                    null = failure to load or instantiate class object.
580
+	 *                                  object = class loaded and instantiated successfully.
581
+	 *                                  bool = fail or success when $load_only is true
582
+	 */
583
+	public function create(
584
+		$class_name = false,
585
+		$arguments = array(),
586
+		$cache = false,
587
+		$from_db = false,
588
+		$load_only = false,
589
+		$addon = false
590
+	) {
591
+		$class_name = ltrim($class_name, '\\');
592
+		$class_name = $this->_dependency_map->get_alias($class_name);
593
+		if ( ! class_exists($class_name)) {
594
+			// maybe the class is registered with a preceding \
595
+			$class_name = strpos($class_name, '\\') !== 0 ? '\\' . $class_name : $class_name;
596
+			// still doesn't exist ?
597
+			if ( ! class_exists($class_name)) {
598
+				return null;
599
+			}
600
+		}
601
+		// if we're only loading the class and it already exists, then let's just return true immediately
602
+		if ($load_only) {
603
+			return true;
604
+		}
605
+		$addon = $addon ? 'addon' : '';
606
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
607
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
608
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
609
+		if ($this->_cache_on && $cache && ! $load_only) {
610
+			// return object if it's already cached
611
+			$cached_class = $this->_get_cached_class($class_name, $addon);
612
+			if ($cached_class !== null) {
613
+				return $cached_class;
614
+			}
615
+		}
616
+		// instantiate the requested object
617
+		$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
618
+		if ($this->_cache_on && $cache) {
619
+			// save it for later... kinda like gum  { : $
620
+			$this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
621
+		}
622
+		$this->_cache_on = true;
623
+		return $class_obj;
624
+	}
625
+
626
+
627
+
628
+	/**
629
+	 * instantiates, caches, and injects dependencies for classes
630
+	 *
631
+	 * @param array       $file_paths   an array of paths to folders to look in
632
+	 * @param string      $class_prefix EE  or EEM or... ???
633
+	 * @param bool|string $class_name   $class name
634
+	 * @param string      $type         file type - core? class? helper? model?
635
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
636
+	 * @param bool        $from_db      some classes are instantiated from the db
637
+	 *                                  and thus call a different method to instantiate
638
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
639
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
640
+	 * @return null|object|bool         null = failure to load or instantiate class object.
641
+	 *                                  object = class loaded and instantiated successfully.
642
+	 *                                  bool = fail or success when $load_only is true
643
+	 */
644
+	protected function _load(
645
+		$file_paths = array(),
646
+		$class_prefix = 'EE_',
647
+		$class_name = false,
648
+		$type = 'class',
649
+		$arguments = array(),
650
+		$from_db = false,
651
+		$cache = true,
652
+		$load_only = false
653
+	) {
654
+		$class_name = ltrim($class_name, '\\');
655
+		// strip php file extension
656
+		$class_name = str_replace('.php', '', trim($class_name));
657
+		// does the class have a prefix ?
658
+		if ( ! empty($class_prefix) && $class_prefix != 'addon') {
659
+			// make sure $class_prefix is uppercase
660
+			$class_prefix = strtoupper(trim($class_prefix));
661
+			// add class prefix ONCE!!!
662
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
663
+		}
664
+		$class_name = $this->_dependency_map->get_alias($class_name);
665
+		$class_exists = class_exists($class_name, false);
666
+		// if we're only loading the class and it already exists, then let's just return true immediately
667
+		if ($load_only && $class_exists) {
668
+			return true;
669
+		}
670
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
671
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
672
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
673
+		if ($this->_cache_on && $cache && ! $load_only) {
674
+			// return object if it's already cached
675
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix);
676
+			if ($cached_class !== null) {
677
+				return $cached_class;
678
+			}
679
+		}
680
+		// if the class doesn't already exist.. then we need to try and find the file and load it
681
+		if ( ! $class_exists) {
682
+			// get full path to file
683
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
684
+			// load the file
685
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
686
+			// if loading failed, or we are only loading a file but NOT instantiating an object
687
+			if ( ! $loaded || $load_only) {
688
+				// return boolean if only loading, or null if an object was expected
689
+				return $load_only ? $loaded : null;
690
+			}
691
+		}
692
+		// instantiate the requested object
693
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
694
+		if ($this->_cache_on && $cache) {
695
+			// save it for later... kinda like gum  { : $
696
+			$this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
697
+		}
698
+		$this->_cache_on = true;
699
+		return $class_obj;
700
+	}
701
+
702
+
703
+
704
+
705
+	/**
706
+	 * _get_cached_class
707
+	 * attempts to find a cached version of the requested class
708
+	 * by looking in the following places:
709
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
710
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
711
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
712
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
713
+	 *
714
+	 * @access protected
715
+	 * @param string $class_name
716
+	 * @param string $class_prefix
717
+	 * @return mixed
718
+	 */
719
+	protected function _get_cached_class($class_name, $class_prefix = '')
720
+	{
721
+		if ($class_name === 'EE_Registry') {
722
+			return $this;
723
+		}
724
+		// have to specify something, but not anything that will conflict
725
+		$class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
726
+			? $this->_class_abbreviations[ $class_name ]
727
+			: 'FANCY_BATMAN_PANTS';
728
+		$class_name = str_replace('\\', '_', $class_name);
729
+		// check if class has already been loaded, and return it if it has been
730
+		if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
731
+			return $this->{$class_abbreviation};
732
+		}
733
+		if (isset ($this->{$class_name})) {
734
+			return $this->{$class_name};
735
+		}
736
+		if (isset ($this->LIB->{$class_name})) {
737
+			return $this->LIB->{$class_name};
738
+		}
739
+		if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
740
+			return $this->addons->{$class_name};
741
+		}
742
+		return null;
743
+	}
744
+
745
+
746
+
747
+	/**
748
+	 * removes a cached version of the requested class
749
+	 *
750
+	 * @param string $class_name
751
+	 * @param boolean $addon
752
+	 * @return boolean
753
+	 */
754
+	public function clear_cached_class($class_name, $addon = false)
755
+	{
756
+		// have to specify something, but not anything that will conflict
757
+		$class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
758
+			? $this->_class_abbreviations[ $class_name ]
759
+			: 'FANCY_BATMAN_PANTS';
760
+		$class_name = str_replace('\\', '_', $class_name);
761
+		// check if class has already been loaded, and return it if it has been
762
+		if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
763
+			$this->{$class_abbreviation} = null;
764
+			return true;
765
+		}
766
+		if (isset($this->{$class_name})) {
767
+			$this->{$class_name} = null;
768
+			return true;
769
+		}
770
+		if (isset($this->LIB->{$class_name})) {
771
+			unset($this->LIB->{$class_name});
772
+			return true;
773
+		}
774
+		if ($addon && isset($this->addons->{$class_name})) {
775
+			unset($this->addons->{$class_name});
776
+			return true;
777
+		}
778
+		return false;
779
+	}
780
+
781
+
782
+	/**
783
+	 * _resolve_path
784
+	 * attempts to find a full valid filepath for the requested class.
785
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
786
+	 * then returns that path if the target file has been found and is readable
787
+	 *
788
+	 * @access protected
789
+	 * @param string $class_name
790
+	 * @param string $type
791
+	 * @param array  $file_paths
792
+	 * @return string | bool
793
+	 */
794
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
795
+	{
796
+		// make sure $file_paths is an array
797
+		$file_paths = is_array($file_paths) ? $file_paths : array($file_paths);
798
+		// cycle thru paths
799
+		foreach ($file_paths as $key => $file_path) {
800
+			// convert all separators to proper DS, if no filepath, then use EE_CLASSES
801
+			$file_path = $file_path ? str_replace(array('/', '\\'), DS, $file_path) : EE_CLASSES;
802
+			// prep file type
803
+			$type = ! empty($type) ? trim($type, '.') . '.' : '';
804
+			// build full file path
805
+			$file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
806
+			//does the file exist and can be read ?
807
+			if (is_readable($file_paths[$key])) {
808
+				return $file_paths[$key];
809
+			}
810
+		}
811
+		return false;
812
+	}
813
+
814
+
815
+
816
+	/**
817
+	 * _require_file
818
+	 * basically just performs a require_once()
819
+	 * but with some error handling
820
+	 *
821
+	 * @access protected
822
+	 * @param  string $path
823
+	 * @param  string $class_name
824
+	 * @param  string $type
825
+	 * @param  array  $file_paths
826
+	 * @return boolean
827
+	 * @throws \EE_Error
828
+	 */
829
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
830
+	{
831
+		$this->resolve_legacy_class_parent($class_name);
832
+		// don't give up! you gotta...
833
+		try {
834
+			//does the file exist and can it be read ?
835
+			if ( ! $path) {
836
+				// so sorry, can't find the file
837
+				throw new EE_Error (
838
+					sprintf(
839
+						__('The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s', 'event_espresso'),
840
+						trim($type, '.'),
841
+						$class_name,
842
+						'<br />' . implode(',<br />', $file_paths)
843
+					)
844
+				);
845
+			}
846
+			// get the file
847
+			require_once($path);
848
+			// if the class isn't already declared somewhere
849
+			if (class_exists($class_name, false) === false) {
850
+				// so sorry, not a class
851
+				throw new EE_Error(
852
+					sprintf(
853
+						__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
854
+						$type,
855
+						$path,
856
+						$class_name
857
+					)
858
+				);
859
+			}
860
+		} catch (EE_Error $e) {
861
+			$e->get_error();
862
+			return false;
863
+		}
864
+		return true;
865
+	}
866
+
867
+
868
+
869
+	/**
870
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
871
+	 * before their class declaration in order to ensure that the parent class was loaded.
872
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
873
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
874
+	 *
875
+	 * @param string $class_name
876
+	 */
877
+	protected function resolve_legacy_class_parent($class_name = '')
878
+	{
879
+		try {
880
+			$legacy_parent_class_map = array(
881
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
882
+			);
883
+			if(isset($legacy_parent_class_map[$class_name])) {
884
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
885
+			}
886
+		} catch (Exception $exception) {
887
+		}
888
+	}
889
+
890
+
891
+
892
+	/**
893
+	 * _create_object
894
+	 * Attempts to instantiate the requested class via any of the
895
+	 * commonly used instantiation methods employed throughout EE.
896
+	 * The priority for instantiation is as follows:
897
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
898
+	 *        - model objects via their 'new_instance_from_db' method
899
+	 *        - model objects via their 'new_instance' method
900
+	 *        - "singleton" classes" via their 'instance' method
901
+	 *    - standard instantiable classes via their __constructor
902
+	 * Prior to instantiation, if the classname exists in the dependency_map,
903
+	 * then the constructor for the requested class will be examined to determine
904
+	 * if any dependencies exist, and if they can be injected.
905
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
906
+	 *
907
+	 * @access protected
908
+	 * @param string $class_name
909
+	 * @param array  $arguments
910
+	 * @param string $type
911
+	 * @param bool   $from_db
912
+	 * @return null | object
913
+	 * @throws \EE_Error
914
+	 */
915
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
916
+	{
917
+		$class_obj = null;
918
+		$instantiation_mode = '0) none';
919
+		// don't give up! you gotta...
920
+		try {
921
+			// create reflection
922
+			$reflector = $this->get_ReflectionClass($class_name);
923
+			// make sure arguments are an array
924
+			$arguments = is_array($arguments) ? $arguments : array($arguments);
925
+			// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
926
+			// else wrap it in an additional array so that it doesn't get split into multiple parameters
927
+			$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
928
+				? $arguments
929
+				: array($arguments);
930
+			// attempt to inject dependencies ?
931
+			if ($this->_dependency_map->has($class_name)) {
932
+				$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
933
+			}
934
+			// instantiate the class if possible
935
+			if ($reflector->isAbstract()) {
936
+				// nothing to instantiate, loading file was enough
937
+				// does not throw an exception so $instantiation_mode is unused
938
+				// $instantiation_mode = "1) no constructor abstract class";
939
+				$class_obj = true;
940
+			} else if ($reflector->getConstructor() === null && $reflector->isInstantiable() && empty($arguments)) {
941
+				// no constructor = static methods only... nothing to instantiate, loading file was enough
942
+				$instantiation_mode = "2) no constructor but instantiable";
943
+				$class_obj = $reflector->newInstance();
944
+			} else if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
945
+				$instantiation_mode = "3) new_instance_from_db()";
946
+				$class_obj = call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
947
+			} else if (method_exists($class_name, 'new_instance')) {
948
+				$instantiation_mode = "4) new_instance()";
949
+				$class_obj = call_user_func_array(array($class_name, 'new_instance'), $arguments);
950
+			} else if (method_exists($class_name, 'instance')) {
951
+				$instantiation_mode = "5) instance()";
952
+				$class_obj = call_user_func_array(array($class_name, 'instance'), $arguments);
953
+			} else if ($reflector->isInstantiable()) {
954
+				$instantiation_mode = "6) constructor";
955
+				$class_obj = $reflector->newInstanceArgs($arguments);
956
+			} else {
957
+				// heh ? something's not right !
958
+				throw new EE_Error(
959
+					sprintf(
960
+						__('The %s file %s could not be instantiated.', 'event_espresso'),
961
+						$type,
962
+						$class_name
963
+					)
964
+				);
965
+			}
966
+		} catch (Exception $e) {
967
+			if ( ! $e instanceof EE_Error) {
968
+				$e = new EE_Error(
969
+					sprintf(
970
+						__('The following error occurred while attempting to instantiate "%1$s": %2$s %3$s %2$s instantiation mode : %4$s', 'event_espresso'),
971
+						$class_name,
972
+						'<br />',
973
+						$e->getMessage(),
974
+						$instantiation_mode
975
+					)
976
+				);
977
+			}
978
+			$e->get_error();
979
+		}
980
+		return $class_obj;
981
+	}
982
+
983
+
984
+
985
+	/**
986
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
987
+	 * @param array $array
988
+	 * @return bool
989
+	 */
990
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
991
+	{
992
+		return ! empty($array) ? array_keys($array) === range(0, count($array) - 1) : true;
993
+	}
994
+
995
+
996
+
997
+	/**
998
+	 * getReflectionClass
999
+	 * checks if a ReflectionClass object has already been generated for a class
1000
+	 * and returns that instead of creating a new one
1001
+	 *
1002
+	 * @access public
1003
+	 * @param string $class_name
1004
+	 * @return ReflectionClass
1005
+	 */
1006
+	public function get_ReflectionClass($class_name)
1007
+	{
1008
+		if (
1009
+			! isset($this->_reflectors[$class_name])
1010
+			|| ! $this->_reflectors[$class_name] instanceof ReflectionClass
1011
+		) {
1012
+			$this->_reflectors[$class_name] = new ReflectionClass($class_name);
1013
+		}
1014
+		return $this->_reflectors[$class_name];
1015
+	}
1016
+
1017
+
1018
+
1019
+	/**
1020
+	 * _resolve_dependencies
1021
+	 * examines the constructor for the requested class to determine
1022
+	 * if any dependencies exist, and if they can be injected.
1023
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1024
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1025
+	 * For example:
1026
+	 *        if attempting to load a class "Foo" with the following constructor:
1027
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1028
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1029
+	 *        but only IF they are NOT already present in the incoming arguments array,
1030
+	 *        and the correct classes can be loaded
1031
+	 *
1032
+	 * @access protected
1033
+	 * @param ReflectionClass $reflector
1034
+	 * @param string          $class_name
1035
+	 * @param array           $arguments
1036
+	 * @return array
1037
+	 * @throws \ReflectionException
1038
+	 */
1039
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1040
+	{
1041
+		// let's examine the constructor
1042
+		$constructor = $reflector->getConstructor();
1043
+		// whu? huh? nothing?
1044
+		if ( ! $constructor) {
1045
+			return $arguments;
1046
+		}
1047
+		// get constructor parameters
1048
+		$params = $constructor->getParameters();
1049
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1050
+		$argument_keys = array_keys($arguments);
1051
+		// now loop thru all of the constructors expected parameters
1052
+		foreach ($params as $index => $param) {
1053
+			// is this a dependency for a specific class ?
1054
+			$param_class = $param->getClass() ? $param->getClass()->name : null;
1055
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1056
+			$param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1057
+				? $this->_dependency_map->get_alias($param_class, $class_name)
1058
+				: $param_class;
1059
+			if (
1060
+				// param is not even a class
1061
+				empty($param_class)
1062
+				// and something already exists in the incoming arguments for this param
1063
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1064
+			) {
1065
+				// so let's skip this argument and move on to the next
1066
+				continue;
1067
+			}
1068
+			if (
1069
+				// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1070
+				! empty($param_class)
1071
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1072
+				&& $arguments[$argument_keys[$index]] instanceof $param_class
1073
+			) {
1074
+				// skip this argument and move on to the next
1075
+				continue;
1076
+			}
1077
+			if (
1078
+				// parameter is type hinted as a class, and should be injected
1079
+				! empty($param_class)
1080
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1081
+			) {
1082
+				$arguments = $this->_resolve_dependency($class_name, $param_class, $arguments, $index);
1083
+			} else {
1084
+				try {
1085
+					$arguments[$index] = $param->getDefaultValue();
1086
+				} catch (ReflectionException $e) {
1087
+					throw new ReflectionException(
1088
+						sprintf(
1089
+							__('%1$s for parameter "$%2$s"', 'event_espresso'),
1090
+							$e->getMessage(),
1091
+							$param->getName()
1092
+						)
1093
+					);
1094
+				}
1095
+			}
1096
+		}
1097
+		return $arguments;
1098
+	}
1099
+
1100
+
1101
+
1102
+	/**
1103
+	 * @access protected
1104
+	 * @param string $class_name
1105
+	 * @param string $param_class
1106
+	 * @param array  $arguments
1107
+	 * @param mixed  $index
1108
+	 * @return array
1109
+	 */
1110
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1111
+	{
1112
+		$dependency = null;
1113
+		// should dependency be loaded from cache ?
1114
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency($class_name, $param_class)
1115
+					!== EE_Dependency_Map::load_new_object
1116
+			? true
1117
+			: false;
1118
+		// we might have a dependency...
1119
+		// let's MAYBE try and find it in our cache if that's what's been requested
1120
+		$cached_class = $cache_on ? $this->_get_cached_class($param_class) : null;
1121
+		// and grab it if it exists
1122
+		if ($cached_class instanceof $param_class) {
1123
+			$dependency = $cached_class;
1124
+		} else if ($param_class !== $class_name) {
1125
+			// obtain the loader method from the dependency map
1126
+			$loader = $this->_dependency_map->class_loader($param_class);
1127
+			// is loader a custom closure ?
1128
+			if ($loader instanceof Closure) {
1129
+				$dependency = $loader();
1130
+			} else {
1131
+				// set the cache on property for the recursive loading call
1132
+				$this->_cache_on = $cache_on;
1133
+				// if not, then let's try and load it via the registry
1134
+				if ($loader && method_exists($this, $loader)) {
1135
+					$dependency = $this->{$loader}($param_class);
1136
+				} else {
1137
+					$dependency = $this->create($param_class, array(), $cache_on);
1138
+				}
1139
+			}
1140
+		}
1141
+		// did we successfully find the correct dependency ?
1142
+		if ($dependency instanceof $param_class) {
1143
+			// then let's inject it into the incoming array of arguments at the correct location
1144
+			if (isset($argument_keys[$index])) {
1145
+				$arguments[$argument_keys[$index]] = $dependency;
1146
+			} else {
1147
+				$arguments[$index] = $dependency;
1148
+			}
1149
+		}
1150
+		return $arguments;
1151
+	}
1152
+
1153
+
1154
+
1155
+	/**
1156
+	 * _set_cached_class
1157
+	 * attempts to cache the instantiated class locally
1158
+	 * in one of the following places, in the following order:
1159
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1160
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1161
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1162
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1163
+	 *
1164
+	 * @access protected
1165
+	 * @param object $class_obj
1166
+	 * @param string $class_name
1167
+	 * @param string $class_prefix
1168
+	 * @param bool   $from_db
1169
+	 * @return void
1170
+	 */
1171
+	protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1172
+	{
1173
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1174
+			return;
1175
+		}
1176
+		// return newly instantiated class
1177
+		if (isset($this->_class_abbreviations[$class_name])) {
1178
+			$class_abbreviation = $this->_class_abbreviations[$class_name];
1179
+			$this->{$class_abbreviation} = $class_obj;
1180
+			return;
1181
+		}
1182
+		$class_name = str_replace('\\', '_', $class_name);
1183
+		if (property_exists($this, $class_name)) {
1184
+			$this->{$class_name} = $class_obj;
1185
+			return;
1186
+		}
1187
+		if ($class_prefix === 'addon') {
1188
+			$this->addons->{$class_name} = $class_obj;
1189
+			return;
1190
+		}
1191
+		if ( ! $from_db) {
1192
+			$this->LIB->{$class_name} = $class_obj;
1193
+		}
1194
+	}
1195
+
1196
+
1197
+
1198
+	/**
1199
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1200
+	 *
1201
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1202
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1203
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1204
+	 * @param array  $arguments
1205
+	 * @return object
1206
+	 */
1207
+	public static function factory($classname, $arguments = array())
1208
+	{
1209
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1210
+		if ($loader instanceof Closure) {
1211
+			return $loader($arguments);
1212
+		}
1213
+		if (method_exists(EE_Registry::instance(), $loader)) {
1214
+			return EE_Registry::instance()->{$loader}($classname, $arguments);
1215
+		}
1216
+		return null;
1217
+	}
1218
+
1219
+
1220
+
1221
+	/**
1222
+	 * Gets the addon by its name/slug (not classname. For that, just
1223
+	 * use the classname as the property name on EE_Config::instance()->addons)
1224
+	 *
1225
+	 * @param string $name
1226
+	 * @return EE_Addon
1227
+	 */
1228
+	public function get_addon_by_name($name)
1229
+	{
1230
+		foreach ($this->addons as $addon) {
1231
+			if ($addon->name() == $name) {
1232
+				return $addon;
1233
+			}
1234
+		}
1235
+		return null;
1236
+	}
1237
+
1238
+
1239
+
1240
+	/**
1241
+	 * Gets an array of all the registered addons, where the keys are their names. (ie, what each returns for their name() function) They're already available on EE_Config::instance()->addons as properties, where each property's name is
1242
+	 * the addon's classname. So if you just want to get the addon by classname, use EE_Config::instance()->addons->{classname}
1243
+	 *
1244
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1245
+	 */
1246
+	public function get_addons_by_name()
1247
+	{
1248
+		$addons = array();
1249
+		foreach ($this->addons as $addon) {
1250
+			$addons[$addon->name()] = $addon;
1251
+		}
1252
+		return $addons;
1253
+	}
1254
+
1255
+
1256
+
1257
+	/**
1258
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1259
+	 * a stale copy of it around
1260
+	 *
1261
+	 * @param string $model_name
1262
+	 * @return \EEM_Base
1263
+	 * @throws \EE_Error
1264
+	 */
1265
+	public function reset_model($model_name)
1266
+	{
1267
+		$model_class_name = strpos($model_name, 'EEM_') !== 0 ? "EEM_{$model_name}" : $model_name;
1268
+		if ( ! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1269
+			return null;
1270
+		}
1271
+		//get that model reset it and make sure we nuke the old reference to it
1272
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name && is_callable(array($model_class_name, 'reset'))) {
1273
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1274
+		} else {
1275
+			throw new EE_Error(sprintf(__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1276
+		}
1277
+		return $this->LIB->{$model_class_name};
1278
+	}
1279
+
1280
+
1281
+
1282
+	/**
1283
+	 * Resets the registry.
1284
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when switch_to_blog
1285
+	 * is used in a multisite install.  Here is a list of things that are NOT reset.
1286
+	 * - $_dependency_map
1287
+	 * - $_class_abbreviations
1288
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1289
+	 * - $REQ:  Still on the same request so no need to change.
1290
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1291
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only one Session
1292
+	 *         can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1293
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1294
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1295
+	 *             switch or on the restore.
1296
+	 * - $modules
1297
+	 * - $shortcodes
1298
+	 * - $widgets
1299
+	 *
1300
+	 * @param boolean $hard             whether to reset data in the database too, or just refresh
1301
+	 *                                  the Registry to its state at the beginning of the request
1302
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1303
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not sure if you CAN
1304
+	 *                                  currently reinstantiate the singletons at the moment)
1305
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so client
1306
+	 *                                  code instead can just change the model context to a different blog id if necessary
1307
+	 * @return EE_Registry
1308
+	 */
1309
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1310
+	{
1311
+		$instance = self::instance();
1312
+		$instance->_cache_on = true;
1313
+		// reset some "special" classes
1314
+		EEH_Activation::reset();
1315
+		$instance->CFG = $instance->CFG->reset($hard, $reinstantiate);
1316
+		$instance->CART = null;
1317
+		$instance->MRM = null;
1318
+		$instance->AssetsRegistry = null;
1319
+		$instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1320
+		//messages reset
1321
+		EED_Messages::reset();
1322
+		//handle of objects cached on LIB
1323
+		foreach (array('LIB', 'modules', 'shortcodes') as $cache) {
1324
+			foreach ($instance->{$cache} as $class_name => $class) {
1325
+				if (EE_Registry::_reset_and_unset_object($class, $reset_models)) {
1326
+					unset($instance->{$cache}->{$class_name});
1327
+				}
1328
+			}
1329
+		}
1330
+		return $instance;
1331
+	}
1332
+
1333
+
1334
+
1335
+	/**
1336
+	 * if passed object implements ResettableInterface, then call it's reset() method
1337
+	 * if passed object implements InterminableInterface, then return false,
1338
+	 * to indicate that it should NOT be cleared from the Registry cache
1339
+	 *
1340
+	 * @param      $object
1341
+	 * @param bool $reset_models
1342
+	 * @return bool returns true if cached object should be unset
1343
+	 */
1344
+	private static function _reset_and_unset_object($object, $reset_models)
1345
+	{
1346
+		static $count = 0;
1347
+		$count++;
1348
+		if ($object instanceof ResettableInterface) {
1349
+			if ($object instanceof EEM_Base) {
1350
+				if ($reset_models) {
1351
+					$object->reset();
1352
+					return true;
1353
+				}
1354
+				return false;
1355
+			}
1356
+			$object->reset();
1357
+			return true;
1358
+		}
1359
+		if ( ! $object instanceof InterminableInterface) {
1360
+			return true;
1361
+		}
1362
+		return false;
1363
+	}
1364
+
1365
+
1366
+
1367
+	/**
1368
+	 * @override magic methods
1369
+	 * @return void
1370
+	 */
1371
+	public final function __destruct()
1372
+	{
1373
+	}
1374
+
1375
+
1376
+
1377
+	/**
1378
+	 * @param $a
1379
+	 * @param $b
1380
+	 */
1381
+	public final function __call($a, $b)
1382
+	{
1383
+	}
1384
+
1385
+
1386
+
1387
+	/**
1388
+	 * @param $a
1389
+	 */
1390
+	public final function __get($a)
1391
+	{
1392
+	}
1393
+
1394
+
1395
+
1396
+	/**
1397
+	 * @param $a
1398
+	 * @param $b
1399
+	 */
1400
+	public final function __set($a, $b)
1401
+	{
1402
+	}
1403
+
1404
+
1405
+
1406
+	/**
1407
+	 * @param $a
1408
+	 */
1409
+	public final function __isset($a)
1410
+	{
1411
+	}
1412 1412
 
1413 1413
 
1414 1414
 
1415
-    /**
1416
-     * @param $a
1417
-     */
1418
-    public final function __unset($a)
1419
-    {
1420
-    }
1415
+	/**
1416
+	 * @param $a
1417
+	 */
1418
+	public final function __unset($a)
1419
+	{
1420
+	}
1421 1421
 
1422 1422
 
1423 1423
 
1424
-    /**
1425
-     * @return array
1426
-     */
1427
-    public final function __sleep()
1428
-    {
1429
-        return array();
1430
-    }
1424
+	/**
1425
+	 * @return array
1426
+	 */
1427
+	public final function __sleep()
1428
+	{
1429
+		return array();
1430
+	}
1431 1431
 
1432 1432
 
1433 1433
 
1434
-    public final function __wakeup()
1435
-    {
1436
-    }
1434
+	public final function __wakeup()
1435
+	{
1436
+	}
1437 1437
 
1438 1438
 
1439 1439
 
1440
-    /**
1441
-     * @return string
1442
-     */
1443
-    public final function __toString()
1444
-    {
1445
-        return '';
1446
-    }
1440
+	/**
1441
+	 * @return string
1442
+	 */
1443
+	public final function __toString()
1444
+	{
1445
+		return '';
1446
+	}
1447 1447
 
1448 1448
 
1449 1449
 
1450
-    public final function __invoke()
1451
-    {
1452
-    }
1450
+	public final function __invoke()
1451
+	{
1452
+	}
1453 1453
 
1454 1454
 
1455 1455
 
1456
-    public final static function __set_state($array = array())
1457
-    {
1458
-        return EE_Registry::instance();
1459
-    }
1456
+	public final static function __set_state($array = array())
1457
+	{
1458
+		return EE_Registry::instance();
1459
+	}
1460 1460
 
1461 1461
 
1462 1462
 
1463
-    public final function __clone()
1464
-    {
1465
-    }
1463
+	public final function __clone()
1464
+	{
1465
+	}
1466 1466
 
1467 1467
 
1468 1468
 
1469
-    /**
1470
-     * @param $a
1471
-     * @param $b
1472
-     */
1473
-    public final static function __callStatic($a, $b)
1474
-    {
1475
-    }
1469
+	/**
1470
+	 * @param $a
1471
+	 * @param $b
1472
+	 */
1473
+	public final static function __callStatic($a, $b)
1474
+	{
1475
+	}
1476 1476
 
1477 1477
 
1478 1478
 
1479
-    /**
1480
-     * Gets all the custom post type models defined
1481
-     *
1482
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1483
-     */
1484
-    public function cpt_models()
1485
-    {
1486
-        $cpt_models = array();
1487
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1488
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1489
-                $cpt_models[$short_name] = $classname;
1490
-            }
1491
-        }
1492
-        return $cpt_models;
1493
-    }
1479
+	/**
1480
+	 * Gets all the custom post type models defined
1481
+	 *
1482
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1483
+	 */
1484
+	public function cpt_models()
1485
+	{
1486
+		$cpt_models = array();
1487
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1488
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1489
+				$cpt_models[$short_name] = $classname;
1490
+			}
1491
+		}
1492
+		return $cpt_models;
1493
+	}
1494 1494
 
1495 1495
 
1496 1496
 
1497
-    /**
1498
-     * @return \EE_Config
1499
-     */
1500
-    public static function CFG()
1501
-    {
1502
-        return self::instance()->CFG;
1503
-    }
1497
+	/**
1498
+	 * @return \EE_Config
1499
+	 */
1500
+	public static function CFG()
1501
+	{
1502
+		return self::instance()->CFG;
1503
+	}
1504 1504
 
1505 1505
 
1506 1506
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -297,13 +297,13 @@  discard block
 block discarded – undo
297 297
      */
298 298
     public static function localize_i18n_js_strings()
299 299
     {
300
-        $i18n_js_strings = (array)EE_Registry::$i18n_js_strings;
300
+        $i18n_js_strings = (array) EE_Registry::$i18n_js_strings;
301 301
         foreach ($i18n_js_strings as $key => $value) {
302 302
             if (is_scalar($value)) {
303
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
303
+                $i18n_js_strings[$key] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
304 304
             }
305 305
         }
306
-        return "/* <![CDATA[ */ var eei18n = " . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
306
+        return "/* <![CDATA[ */ var eei18n = ".wp_json_encode($i18n_js_strings).'; /* ]]> */';
307 307
     }
308 308
 
309 309
 
@@ -354,9 +354,9 @@  discard block
 block discarded – undo
354 354
                 EE_CORE,
355 355
                 EE_ADMIN,
356 356
                 EE_CPTS,
357
-                EE_CORE . 'data_migration_scripts' . DS,
358
-                EE_CORE . 'request_stack' . DS,
359
-                EE_CORE . 'middleware' . DS,
357
+                EE_CORE.'data_migration_scripts'.DS,
358
+                EE_CORE.'request_stack'.DS,
359
+                EE_CORE.'middleware'.DS,
360 360
             )
361 361
         );
362 362
         // retrieve instantiated class
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
         $service_paths = apply_filters(
380 380
             'FHEE__EE_Registry__load_service__service_paths',
381 381
             array(
382
-                EE_CORE . 'services' . DS,
382
+                EE_CORE.'services'.DS,
383 383
             )
384 384
         );
385 385
         // retrieve instantiated class
@@ -459,11 +459,11 @@  discard block
 block discarded – undo
459 459
     {
460 460
         $paths = array(
461 461
             EE_LIBRARIES,
462
-            EE_LIBRARIES . 'messages' . DS,
463
-            EE_LIBRARIES . 'shortcodes' . DS,
464
-            EE_LIBRARIES . 'qtips' . DS,
465
-            EE_LIBRARIES . 'payment_methods' . DS,
466
-            EE_LIBRARIES . 'messages' . DS . 'defaults' . DS,
462
+            EE_LIBRARIES.'messages'.DS,
463
+            EE_LIBRARIES.'shortcodes'.DS,
464
+            EE_LIBRARIES.'qtips'.DS,
465
+            EE_LIBRARIES.'payment_methods'.DS,
466
+            EE_LIBRARIES.'messages'.DS.'defaults'.DS,
467 467
         );
468 468
         // retrieve instantiated class
469 469
         return $this->_load($paths, 'EE_', $class_name, 'lib', $arguments, false, $cache, $load_only);
@@ -502,10 +502,10 @@  discard block
 block discarded – undo
502 502
     public function load_model_class($class_name, $arguments = array(), $load_only = true)
503 503
     {
504 504
         $paths = array(
505
-            EE_MODELS . 'fields' . DS,
506
-            EE_MODELS . 'helpers' . DS,
507
-            EE_MODELS . 'relations' . DS,
508
-            EE_MODELS . 'strategies' . DS,
505
+            EE_MODELS.'fields'.DS,
506
+            EE_MODELS.'helpers'.DS,
507
+            EE_MODELS.'relations'.DS,
508
+            EE_MODELS.'strategies'.DS,
509 509
         );
510 510
         // retrieve instantiated class
511 511
         return $this->_load($paths, 'EE_', $class_name, '', $arguments, false, true, $load_only);
@@ -592,7 +592,7 @@  discard block
 block discarded – undo
592 592
         $class_name = $this->_dependency_map->get_alias($class_name);
593 593
         if ( ! class_exists($class_name)) {
594 594
             // maybe the class is registered with a preceding \
595
-            $class_name = strpos($class_name, '\\') !== 0 ? '\\' . $class_name : $class_name;
595
+            $class_name = strpos($class_name, '\\') !== 0 ? '\\'.$class_name : $class_name;
596 596
             // still doesn't exist ?
597 597
             if ( ! class_exists($class_name)) {
598 598
                 return null;
@@ -659,7 +659,7 @@  discard block
 block discarded – undo
659 659
             // make sure $class_prefix is uppercase
660 660
             $class_prefix = strtoupper(trim($class_prefix));
661 661
             // add class prefix ONCE!!!
662
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
662
+            $class_name = $class_prefix.str_replace($class_prefix, '', $class_name);
663 663
         }
664 664
         $class_name = $this->_dependency_map->get_alias($class_name);
665 665
         $class_exists = class_exists($class_name, false);
@@ -722,8 +722,8 @@  discard block
 block discarded – undo
722 722
             return $this;
723 723
         }
724 724
         // have to specify something, but not anything that will conflict
725
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
726
-            ? $this->_class_abbreviations[ $class_name ]
725
+        $class_abbreviation = isset($this->_class_abbreviations[$class_name])
726
+            ? $this->_class_abbreviations[$class_name]
727 727
             : 'FANCY_BATMAN_PANTS';
728 728
         $class_name = str_replace('\\', '_', $class_name);
729 729
         // check if class has already been loaded, and return it if it has been
@@ -754,8 +754,8 @@  discard block
 block discarded – undo
754 754
     public function clear_cached_class($class_name, $addon = false)
755 755
     {
756 756
         // have to specify something, but not anything that will conflict
757
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
758
-            ? $this->_class_abbreviations[ $class_name ]
757
+        $class_abbreviation = isset($this->_class_abbreviations[$class_name])
758
+            ? $this->_class_abbreviations[$class_name]
759 759
             : 'FANCY_BATMAN_PANTS';
760 760
         $class_name = str_replace('\\', '_', $class_name);
761 761
         // check if class has already been loaded, and return it if it has been
@@ -800,9 +800,9 @@  discard block
 block discarded – undo
800 800
             // convert all separators to proper DS, if no filepath, then use EE_CLASSES
801 801
             $file_path = $file_path ? str_replace(array('/', '\\'), DS, $file_path) : EE_CLASSES;
802 802
             // prep file type
803
-            $type = ! empty($type) ? trim($type, '.') . '.' : '';
803
+            $type = ! empty($type) ? trim($type, '.').'.' : '';
804 804
             // build full file path
805
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
805
+            $file_paths[$key] = rtrim($file_path, DS).DS.$class_name.'.'.$type.'php';
806 806
             //does the file exist and can be read ?
807 807
             if (is_readable($file_paths[$key])) {
808 808
                 return $file_paths[$key];
@@ -834,12 +834,12 @@  discard block
 block discarded – undo
834 834
             //does the file exist and can it be read ?
835 835
             if ( ! $path) {
836 836
                 // so sorry, can't find the file
837
-                throw new EE_Error (
837
+                throw new EE_Error(
838 838
                     sprintf(
839 839
                         __('The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s', 'event_espresso'),
840 840
                         trim($type, '.'),
841 841
                         $class_name,
842
-                        '<br />' . implode(',<br />', $file_paths)
842
+                        '<br />'.implode(',<br />', $file_paths)
843 843
                     )
844 844
                 );
845 845
             }
@@ -880,8 +880,8 @@  discard block
 block discarded – undo
880 880
             $legacy_parent_class_map = array(
881 881
                 'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
882 882
             );
883
-            if(isset($legacy_parent_class_map[$class_name])) {
884
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
883
+            if (isset($legacy_parent_class_map[$class_name])) {
884
+                require_once EE_PLUGIN_DIR_PATH.$legacy_parent_class_map[$class_name];
885 885
             }
886 886
         } catch (Exception $exception) {
887 887
         }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +192 added lines, -192 removed lines patch added patch discarded remove patch
@@ -38,217 +38,217 @@
 block discarded – undo
38 38
  * @since       4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 
64 64
 } else {
65
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
-        /**
68
-         * espresso_minimum_php_version_error
69
-         *
70
-         * @return void
71
-         */
72
-        function espresso_minimum_php_version_error()
73
-        {
74
-            ?>
65
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
+		/**
68
+		 * espresso_minimum_php_version_error
69
+		 *
70
+		 * @return void
71
+		 */
72
+		function espresso_minimum_php_version_error()
73
+		{
74
+			?>
75 75
             <div class="error">
76 76
                 <p>
77 77
                     <?php
78
-                    printf(
79
-                        esc_html__(
80
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
81
-                            'event_espresso'
82
-                        ),
83
-                        EE_MIN_PHP_VER_REQUIRED,
84
-                        PHP_VERSION,
85
-                        '<br/>',
86
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
87
-                    );
88
-                    ?>
78
+					printf(
79
+						esc_html__(
80
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
81
+							'event_espresso'
82
+						),
83
+						EE_MIN_PHP_VER_REQUIRED,
84
+						PHP_VERSION,
85
+						'<br/>',
86
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
87
+					);
88
+					?>
89 89
                 </p>
90 90
             </div>
91 91
             <?php
92
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
93
-        }
92
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
93
+		}
94 94
 
95
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
96
-    } else {
97
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
98
-        /**
99
-         * espresso_version
100
-         * Returns the plugin version
101
-         *
102
-         * @return string
103
-         */
104
-        function espresso_version()
105
-        {
106
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.004');
107
-        }
95
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
96
+	} else {
97
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
98
+		/**
99
+		 * espresso_version
100
+		 * Returns the plugin version
101
+		 *
102
+		 * @return string
103
+		 */
104
+		function espresso_version()
105
+		{
106
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.004');
107
+		}
108 108
 
109
-        /**
110
-         * espresso_plugin_activation
111
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
112
-         */
113
-        function espresso_plugin_activation()
114
-        {
115
-            update_option('ee_espresso_activation', true);
116
-        }
109
+		/**
110
+		 * espresso_plugin_activation
111
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
112
+		 */
113
+		function espresso_plugin_activation()
114
+		{
115
+			update_option('ee_espresso_activation', true);
116
+		}
117 117
 
118
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
119
-        /**
120
-         *    espresso_load_error_handling
121
-         *    this function loads EE's class for handling exceptions and errors
122
-         */
123
-        function espresso_load_error_handling()
124
-        {
125
-            static $error_handling_loaded = false;
126
-            if ($error_handling_loaded) {
127
-                return;
128
-            }
129
-            // load debugging tools
130
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
131
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
132
-                \EEH_Debug_Tools::instance();
133
-            }
134
-            // load error handling
135
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
136
-                require_once(EE_CORE . 'EE_Error.core.php');
137
-            } else {
138
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
139
-            }
140
-            $error_handling_loaded = true;
141
-        }
118
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
119
+		/**
120
+		 *    espresso_load_error_handling
121
+		 *    this function loads EE's class for handling exceptions and errors
122
+		 */
123
+		function espresso_load_error_handling()
124
+		{
125
+			static $error_handling_loaded = false;
126
+			if ($error_handling_loaded) {
127
+				return;
128
+			}
129
+			// load debugging tools
130
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
131
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
132
+				\EEH_Debug_Tools::instance();
133
+			}
134
+			// load error handling
135
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
136
+				require_once(EE_CORE . 'EE_Error.core.php');
137
+			} else {
138
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
139
+			}
140
+			$error_handling_loaded = true;
141
+		}
142 142
 
143
-        /**
144
-         *    espresso_load_required
145
-         *    given a class name and path, this function will load that file or throw an exception
146
-         *
147
-         * @param    string $classname
148
-         * @param    string $full_path_to_file
149
-         * @throws    EE_Error
150
-         */
151
-        function espresso_load_required($classname, $full_path_to_file)
152
-        {
153
-            if (is_readable($full_path_to_file)) {
154
-                require_once($full_path_to_file);
155
-            } else {
156
-                throw new \EE_Error (
157
-                    sprintf(
158
-                        esc_html__(
159
-                            'The %s class file could not be located or is not readable due to file permissions.',
160
-                            'event_espresso'
161
-                        ),
162
-                        $classname
163
-                    )
164
-                );
165
-            }
166
-        }
143
+		/**
144
+		 *    espresso_load_required
145
+		 *    given a class name and path, this function will load that file or throw an exception
146
+		 *
147
+		 * @param    string $classname
148
+		 * @param    string $full_path_to_file
149
+		 * @throws    EE_Error
150
+		 */
151
+		function espresso_load_required($classname, $full_path_to_file)
152
+		{
153
+			if (is_readable($full_path_to_file)) {
154
+				require_once($full_path_to_file);
155
+			} else {
156
+				throw new \EE_Error (
157
+					sprintf(
158
+						esc_html__(
159
+							'The %s class file could not be located or is not readable due to file permissions.',
160
+							'event_espresso'
161
+						),
162
+						$classname
163
+					)
164
+				);
165
+			}
166
+		}
167 167
 
168
-        /**
169
-         * @since 4.9.27
170
-         * @throws \EE_Error
171
-         * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
172
-         * @throws \EventEspresso\core\exceptions\InvalidEntityException
173
-         * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
174
-         * @throws \EventEspresso\core\exceptions\InvalidClassException
175
-         * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
176
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
177
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
178
-         * @throws \OutOfBoundsException
179
-         */
180
-        function bootstrap_espresso()
181
-        {
182
-            require_once(plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE) . 'core/espresso_definitions.php');
183
-            try {
184
-                espresso_load_error_handling();
185
-                espresso_load_required(
186
-                    'EEH_Base',
187
-                    EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
188
-                );
189
-                espresso_load_required(
190
-                    'EEH_File',
191
-                    EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
192
-                );
193
-                espresso_load_required(
194
-                    'EEH_File',
195
-                    EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
196
-                );
197
-                espresso_load_required(
198
-                    'EEH_Array',
199
-                    EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
200
-                );
201
-                // instantiate and configure PSR4 autoloader
202
-                espresso_load_required(
203
-                    'Psr4Autoloader',
204
-                    EE_CORE . 'Psr4Autoloader.php'
205
-                );
206
-                espresso_load_required(
207
-                    'EE_Psr4AutoloaderInit',
208
-                    EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
209
-                );
210
-                $AutoloaderInit = new EE_Psr4AutoloaderInit();
211
-                $AutoloaderInit->initializeAutoloader();
212
-                espresso_load_required(
213
-                    'EE_Request',
214
-                    EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
215
-                );
216
-                espresso_load_required(
217
-                    'EE_Response',
218
-                    EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
219
-                );
220
-                espresso_load_required(
221
-                    'EE_Bootstrap',
222
-                    EE_CORE . 'EE_Bootstrap.core.php'
223
-                );
224
-                // bootstrap EE and the request stack
225
-                new EE_Bootstrap(
226
-                    new EE_Request($_GET, $_POST, $_COOKIE),
227
-                    new EE_Response()
228
-                );
229
-            } catch (Exception $e) {
230
-                require_once EE_CORE . 'exceptions.' . DS . 'ExceptionStackTraceDisplay.php';
231
-                new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
232
-            }
233
-        }
234
-        bootstrap_espresso();
235
-    }
168
+		/**
169
+		 * @since 4.9.27
170
+		 * @throws \EE_Error
171
+		 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
172
+		 * @throws \EventEspresso\core\exceptions\InvalidEntityException
173
+		 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
174
+		 * @throws \EventEspresso\core\exceptions\InvalidClassException
175
+		 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
176
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
177
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
178
+		 * @throws \OutOfBoundsException
179
+		 */
180
+		function bootstrap_espresso()
181
+		{
182
+			require_once(plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE) . 'core/espresso_definitions.php');
183
+			try {
184
+				espresso_load_error_handling();
185
+				espresso_load_required(
186
+					'EEH_Base',
187
+					EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
188
+				);
189
+				espresso_load_required(
190
+					'EEH_File',
191
+					EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
192
+				);
193
+				espresso_load_required(
194
+					'EEH_File',
195
+					EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
196
+				);
197
+				espresso_load_required(
198
+					'EEH_Array',
199
+					EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
200
+				);
201
+				// instantiate and configure PSR4 autoloader
202
+				espresso_load_required(
203
+					'Psr4Autoloader',
204
+					EE_CORE . 'Psr4Autoloader.php'
205
+				);
206
+				espresso_load_required(
207
+					'EE_Psr4AutoloaderInit',
208
+					EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
209
+				);
210
+				$AutoloaderInit = new EE_Psr4AutoloaderInit();
211
+				$AutoloaderInit->initializeAutoloader();
212
+				espresso_load_required(
213
+					'EE_Request',
214
+					EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
215
+				);
216
+				espresso_load_required(
217
+					'EE_Response',
218
+					EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
219
+				);
220
+				espresso_load_required(
221
+					'EE_Bootstrap',
222
+					EE_CORE . 'EE_Bootstrap.core.php'
223
+				);
224
+				// bootstrap EE and the request stack
225
+				new EE_Bootstrap(
226
+					new EE_Request($_GET, $_POST, $_COOKIE),
227
+					new EE_Response()
228
+				);
229
+			} catch (Exception $e) {
230
+				require_once EE_CORE . 'exceptions.' . DS . 'ExceptionStackTraceDisplay.php';
231
+				new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
232
+			}
233
+		}
234
+		bootstrap_espresso();
235
+	}
236 236
 }
237 237
 if (! function_exists('espresso_deactivate_plugin')) {
238
-    /**
239
-     *    deactivate_plugin
240
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
241
-     *
242
-     * @access public
243
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
244
-     * @return    void
245
-     */
246
-    function espresso_deactivate_plugin($plugin_basename = '')
247
-    {
248
-        if (! function_exists('deactivate_plugins')) {
249
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
250
-        }
251
-        unset($_GET['activate'], $_REQUEST['activate']);
252
-        deactivate_plugins($plugin_basename);
253
-    }
238
+	/**
239
+	 *    deactivate_plugin
240
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
241
+	 *
242
+	 * @access public
243
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
244
+	 * @return    void
245
+	 */
246
+	function espresso_deactivate_plugin($plugin_basename = '')
247
+	{
248
+		if (! function_exists('deactivate_plugins')) {
249
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
250
+		}
251
+		unset($_GET['activate'], $_REQUEST['activate']);
252
+		deactivate_plugins($plugin_basename);
253
+	}
254 254
 }
Please login to merge, or discard this patch.