Completed
Branch BUG/11361/fix-log-calls-using-... (7f327a)
by
unknown
15:14 queued 34s
created
core/domain/Domain.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -66,7 +66,7 @@
 block discarded – undo
66 66
      */
67 67
     private function setCaffeinated()
68 68
     {
69
-        $this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
70
-            && is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
69
+        $this->caffeinated = ( ! defined('EE_DECAF') || EE_DECAF !== true)
70
+            && is_readable($this->pluginPath().'caffeinated/brewing_regular.php');
71 71
     }
72 72
 }
Please login to merge, or discard this patch.
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -19,54 +19,54 @@
 block discarded – undo
19 19
 class Domain extends DomainBase implements CaffeinatedInterface
20 20
 {
21 21
 
22
-    /**
23
-     * URL path component used to denote an API request
24
-     */
25
-    const API_NAMESPACE = 'ee/v';
22
+	/**
23
+	 * URL path component used to denote an API request
24
+	 */
25
+	const API_NAMESPACE = 'ee/v';
26 26
 
27
-    /**
28
-     * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
29
-     * Page ui.
30
-     */
31
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
32
-        = 'manual_registration_status_change_from_registration_admin';
27
+	/**
28
+	 * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
29
+	 * Page ui.
30
+	 */
31
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
32
+		= 'manual_registration_status_change_from_registration_admin';
33 33
 
34
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
35
-        = 'manual_registration_status_change_from_registration_admin_and_notify';
34
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
35
+		= 'manual_registration_status_change_from_registration_admin_and_notify';
36 36
 
37 37
 
38
-    /**
39
-     * Whether or not EE core is the full premium version.
40
-     * @since 4.9.59.p
41
-     * @var bool
42
-     */
43
-    private $caffeinated;
38
+	/**
39
+	 * Whether or not EE core is the full premium version.
40
+	 * @since 4.9.59.p
41
+	 * @var bool
42
+	 */
43
+	private $caffeinated;
44 44
 
45 45
 
46
-    public function __construct(FilePath $plugin_file, Version $version)
47
-    {
48
-        parent::__construct($plugin_file, $version);
49
-        $this->setCaffeinated();
50
-    }
46
+	public function __construct(FilePath $plugin_file, Version $version)
47
+	{
48
+		parent::__construct($plugin_file, $version);
49
+		$this->setCaffeinated();
50
+	}
51 51
 
52
-    /**
53
-     * Whether or not EE core is the full premium version.
54
-     * @since 4.9.59.p
55
-     * @return bool
56
-     */
57
-    public function isCaffeinated()
58
-    {
59
-        return $this->caffeinated;
60
-    }
52
+	/**
53
+	 * Whether or not EE core is the full premium version.
54
+	 * @since 4.9.59.p
55
+	 * @return bool
56
+	 */
57
+	public function isCaffeinated()
58
+	{
59
+		return $this->caffeinated;
60
+	}
61 61
 
62 62
 
63
-    /**
64
-     * Setter for $is_caffeinated property.
65
-     * @since 4.9.59.p
66
-     */
67
-    private function setCaffeinated()
68
-    {
69
-        $this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
70
-            && is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
71
-    }
63
+	/**
64
+	 * Setter for $is_caffeinated property.
65
+	 * @since 4.9.59.p
66
+	 */
67
+	private function setCaffeinated()
68
+	{
69
+		$this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
70
+			&& is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
71
+	}
72 72
 }
Please login to merge, or discard this patch.
core/EE_System.core.php 2 patches
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
         EE_Maintenance_Mode $maintenance_mode = null
149 149
     ) {
150 150
         // check if class object is instantiated
151
-        if (! self::$_instance instanceof EE_System) {
151
+        if ( ! self::$_instance instanceof EE_System) {
152 152
             self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
153 153
         }
154 154
         return self::$_instance;
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
         $this->capabilities = $this->loader->getShared('EE_Capabilities');
268 268
         add_action(
269 269
             'AHEE__EE_Capabilities__init_caps__before_initialization',
270
-            function ()
270
+            function()
271 271
             {
272 272
                 LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
273 273
             }
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
     {
312 312
         // set autoloaders for all of the classes implementing EEI_Plugin_API
313 313
         // which provide helpers for EE plugin authors to more easily register certain components with EE.
314
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
314
+        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES.'plugin_api');
315 315
         $this->loader->getShared('EE_Request_Handler');
316 316
     }
317 317
 
@@ -331,14 +331,14 @@  discard block
 block discarded – undo
331 331
         $load_callback,
332 332
         $plugin_file_constant
333 333
     ) {
334
-        if (! defined($version_constant)) {
334
+        if ( ! defined($version_constant)) {
335 335
             return;
336 336
         }
337 337
         $addon_version = constant($version_constant);
338 338
         if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
339 339
             remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
340
-            if (! function_exists('deactivate_plugins')) {
341
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
340
+            if ( ! function_exists('deactivate_plugins')) {
341
+                require_once ABSPATH.'wp-admin/includes/plugin.php';
342 342
             }
343 343
             deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
344 344
             unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
@@ -351,7 +351,7 @@  discard block
 block discarded – undo
351 351
                     $addon_name,
352 352
                     $min_version_required
353 353
                 ),
354
-                __FILE__, __FUNCTION__ . "({$addon_name})", __LINE__
354
+                __FILE__, __FUNCTION__."({$addon_name})", __LINE__
355 355
             );
356 356
             EE_Error::get_notices(false, true);
357 357
         }
@@ -401,7 +401,7 @@  discard block
 block discarded – undo
401 401
                 true
402 402
             )
403 403
         ) {
404
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
404
+            include_once EE_THIRD_PARTY.'wp-api-basic-auth'.DS.'basic-auth.php';
405 405
         }
406 406
         do_action('AHEE__EE_System__load_espresso_addons__complete');
407 407
     }
@@ -508,11 +508,11 @@  discard block
 block discarded – undo
508 508
     private function fix_espresso_db_upgrade_option($espresso_db_update = null)
509 509
     {
510 510
         do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
511
-        if (! $espresso_db_update) {
511
+        if ( ! $espresso_db_update) {
512 512
             $espresso_db_update = get_option('espresso_db_update');
513 513
         }
514 514
         // check that option is an array
515
-        if (! is_array($espresso_db_update)) {
515
+        if ( ! is_array($espresso_db_update)) {
516 516
             // if option is FALSE, then it never existed
517 517
             if ($espresso_db_update === false) {
518 518
                 // make $espresso_db_update an array and save option with autoload OFF
@@ -532,10 +532,10 @@  discard block
 block discarded – undo
532 532
                     //so it must be numerically-indexed, where values are versions installed...
533 533
                     //fix it!
534 534
                     $version_string                         = $should_be_array;
535
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
535
+                    $corrected_db_update[$version_string] = array('unknown-date');
536 536
                 } else {
537 537
                     //ok it checks out
538
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
538
+                    $corrected_db_update[$should_be_version_string] = $should_be_array;
539 539
                 }
540 540
             }
541 541
             $espresso_db_update = $corrected_db_update;
@@ -617,13 +617,13 @@  discard block
 block discarded – undo
617 617
      */
618 618
     public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
619 619
     {
620
-        if (! $version_history) {
620
+        if ( ! $version_history) {
621 621
             $version_history = $this->fix_espresso_db_upgrade_option($version_history);
622 622
         }
623 623
         if ($current_version_to_add === null) {
624 624
             $current_version_to_add = espresso_version();
625 625
         }
626
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
626
+        $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time());
627 627
         // re-save
628 628
         return update_option('espresso_db_update', $version_history);
629 629
     }
@@ -716,7 +716,7 @@  discard block
 block discarded – undo
716 716
         if ($activation_history_for_addon) {
717 717
             //it exists, so this isn't a completely new install
718 718
             //check if this version already in that list of previously installed versions
719
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
719
+            if ( ! isset($activation_history_for_addon[$version_to_upgrade_to])) {
720 720
                 //it a version we haven't seen before
721 721
                 if ($version_is_higher === 1) {
722 722
                     $req_type = EE_System::req_type_upgrade;
@@ -796,7 +796,7 @@  discard block
 block discarded – undo
796 796
             foreach ($activation_history as $version => $times_activated) {
797 797
                 //check there is a record of when this version was activated. Otherwise,
798 798
                 //mark it as unknown
799
-                if (! $times_activated) {
799
+                if ( ! $times_activated) {
800 800
                     $times_activated = array('unknown-date');
801 801
                 }
802 802
                 if (is_string($times_activated)) {
@@ -897,7 +897,7 @@  discard block
 block discarded – undo
897 897
     private function _parse_model_names()
898 898
     {
899 899
         //get all the files in the EE_MODELS folder that end in .model.php
900
-        $models                 = glob(EE_MODELS . '*.model.php');
900
+        $models                 = glob(EE_MODELS.'*.model.php');
901 901
         $model_names            = array();
902 902
         $non_abstract_db_models = array();
903 903
         foreach ($models as $model) {
@@ -906,9 +906,9 @@  discard block
 block discarded – undo
906 906
             $short_name      = str_replace('EEM_', '', $classname);
907 907
             $reflectionClass = new ReflectionClass($classname);
908 908
             if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
909
-                $non_abstract_db_models[ $short_name ] = $classname;
909
+                $non_abstract_db_models[$short_name] = $classname;
910 910
             }
911
-            $model_names[ $short_name ] = $classname;
911
+            $model_names[$short_name] = $classname;
912 912
         }
913 913
         $this->registry->models                 = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
914 914
         $this->registry->non_abstract_db_models = apply_filters(
@@ -943,7 +943,7 @@  discard block
 block discarded – undo
943 943
             )
944 944
         );
945 945
         if ($domain->isCaffeinated()) {
946
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
946
+            require_once EE_CAFF_PATH.'brewing_regular.php';
947 947
         }
948 948
     }
949 949
 
@@ -996,17 +996,17 @@  discard block
 block discarded – undo
996 996
         $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
997 997
             'AHEE__EE_System__register_shortcodes_modules_and_addons'
998 998
         );
999
-        if (! empty($class_names)) {
999
+        if ( ! empty($class_names)) {
1000 1000
             $msg = __(
1001 1001
                 'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1002 1002
                 'event_espresso'
1003 1003
             );
1004 1004
             $msg .= '<ul>';
1005 1005
             foreach ($class_names as $class_name) {
1006
-                $msg .= '<li><b>Event Espresso - ' . str_replace(
1006
+                $msg .= '<li><b>Event Espresso - '.str_replace(
1007 1007
                         array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
1008 1008
                         $class_name
1009
-                    ) . '</b></li>';
1009
+                    ).'</b></li>';
1010 1010
             }
1011 1011
             $msg .= '</ul>';
1012 1012
             $msg .= __(
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
     private function _deactivate_incompatible_addons()
1078 1078
     {
1079 1079
         $incompatible_addons = get_option('ee_incompatible_addons', array());
1080
-        if (! empty($incompatible_addons)) {
1080
+        if ( ! empty($incompatible_addons)) {
1081 1081
             $active_plugins = get_option('active_plugins', array());
1082 1082
             foreach ($active_plugins as $active_plugin) {
1083 1083
                 foreach ($incompatible_addons as $incompatible_addon) {
@@ -1172,10 +1172,10 @@  discard block
 block discarded – undo
1172 1172
         do_action('AHEE__EE_System__core_loaded_and_ready');
1173 1173
         // load_espresso_template_tags
1174 1174
         if (
1175
-            is_readable(EE_PUBLIC . 'template_tags.php')
1175
+            is_readable(EE_PUBLIC.'template_tags.php')
1176 1176
             && ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isFeed())
1177 1177
         ) {
1178
-            require_once EE_PUBLIC . 'template_tags.php';
1178
+            require_once EE_PUBLIC.'template_tags.php';
1179 1179
         }
1180 1180
         do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1181 1181
         if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
@@ -1239,13 +1239,13 @@  discard block
 block discarded – undo
1239 1239
     public static function do_not_cache()
1240 1240
     {
1241 1241
         // set no cache constants
1242
-        if (! defined('DONOTCACHEPAGE')) {
1242
+        if ( ! defined('DONOTCACHEPAGE')) {
1243 1243
             define('DONOTCACHEPAGE', true);
1244 1244
         }
1245
-        if (! defined('DONOTCACHCEOBJECT')) {
1245
+        if ( ! defined('DONOTCACHCEOBJECT')) {
1246 1246
             define('DONOTCACHCEOBJECT', true);
1247 1247
         }
1248
-        if (! defined('DONOTCACHEDB')) {
1248
+        if ( ! defined('DONOTCACHEDB')) {
1249 1249
             define('DONOTCACHEDB', true);
1250 1250
         }
1251 1251
         // add no cache headers
Please login to merge, or discard this patch.
Indentation   +1265 added lines, -1265 removed lines patch added patch discarded remove patch
@@ -32,1271 +32,1271 @@
 block discarded – undo
32 32
 {
33 33
 
34 34
 
35
-    /**
36
-     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
37
-     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
38
-     */
39
-    const req_type_normal = 0;
40
-
41
-    /**
42
-     * Indicates this is a brand new installation of EE so we should install
43
-     * tables and default data etc
44
-     */
45
-    const req_type_new_activation = 1;
46
-
47
-    /**
48
-     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
49
-     * and we just exited maintenance mode). We MUST check the database is setup properly
50
-     * and that default data is setup too
51
-     */
52
-    const req_type_reactivation = 2;
53
-
54
-    /**
55
-     * indicates that EE has been upgraded since its previous request.
56
-     * We may have data migration scripts to call and will want to trigger maintenance mode
57
-     */
58
-    const req_type_upgrade = 3;
59
-
60
-    /**
61
-     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
62
-     */
63
-    const req_type_downgrade = 4;
64
-
65
-    /**
66
-     * @deprecated since version 4.6.0.dev.006
67
-     * Now whenever a new_activation is detected the request type is still just
68
-     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
69
-     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
70
-     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
71
-     * (Specifically, when the migration manager indicates migrations are finished
72
-     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
73
-     */
74
-    const req_type_activation_but_not_installed = 5;
75
-
76
-    /**
77
-     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
78
-     */
79
-    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
80
-
81
-
82
-    /**
83
-     * @var EE_System $_instance
84
-     */
85
-    private static $_instance;
86
-
87
-    /**
88
-     * @var EE_Registry $registry
89
-     */
90
-    private $registry;
91
-
92
-    /**
93
-     * @var LoaderInterface $loader
94
-     */
95
-    private $loader;
96
-
97
-    /**
98
-     * @var EE_Capabilities $capabilities
99
-     */
100
-    private $capabilities;
101
-
102
-    /**
103
-     * @var RequestInterface $request
104
-     */
105
-    private $request;
106
-
107
-    /**
108
-     * @var EE_Maintenance_Mode $maintenance_mode
109
-     */
110
-    private $maintenance_mode;
111
-
112
-    /**
113
-     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
114
-     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
115
-     *
116
-     * @var int $_req_type
117
-     */
118
-    private $_req_type;
119
-
120
-    /**
121
-     * Whether or not there was a non-micro version change in EE core version during this request
122
-     *
123
-     * @var boolean $_major_version_change
124
-     */
125
-    private $_major_version_change = false;
126
-
127
-    /**
128
-     * A Context DTO dedicated solely to identifying the current request type.
129
-     *
130
-     * @var RequestTypeContextCheckerInterface $request_type
131
-     */
132
-    private $request_type;
133
-
134
-
135
-
136
-    /**
137
-     * @singleton method used to instantiate class object
138
-     * @param EE_Registry|null         $registry
139
-     * @param LoaderInterface|null     $loader
140
-     * @param RequestInterface|null          $request
141
-     * @param EE_Maintenance_Mode|null $maintenance_mode
142
-     * @return EE_System
143
-     */
144
-    public static function instance(
145
-        EE_Registry $registry = null,
146
-        LoaderInterface $loader = null,
147
-        RequestInterface $request = null,
148
-        EE_Maintenance_Mode $maintenance_mode = null
149
-    ) {
150
-        // check if class object is instantiated
151
-        if (! self::$_instance instanceof EE_System) {
152
-            self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
153
-        }
154
-        return self::$_instance;
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * resets the instance and returns it
161
-     *
162
-     * @return EE_System
163
-     */
164
-    public static function reset()
165
-    {
166
-        self::$_instance->_req_type = null;
167
-        //make sure none of the old hooks are left hanging around
168
-        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
169
-        //we need to reset the migration manager in order for it to detect DMSs properly
170
-        EE_Data_Migration_Manager::reset();
171
-        self::instance()->detect_activations_or_upgrades();
172
-        self::instance()->perform_activations_upgrades_and_migrations();
173
-        return self::instance();
174
-    }
175
-
176
-
177
-
178
-    /**
179
-     * sets hooks for running rest of system
180
-     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
181
-     * starting EE Addons from any other point may lead to problems
182
-     *
183
-     * @param EE_Registry         $registry
184
-     * @param LoaderInterface     $loader
185
-     * @param RequestInterface          $request
186
-     * @param EE_Maintenance_Mode $maintenance_mode
187
-     */
188
-    private function __construct(
189
-        EE_Registry $registry,
190
-        LoaderInterface $loader,
191
-        RequestInterface $request,
192
-        EE_Maintenance_Mode $maintenance_mode
193
-    ) {
194
-        $this->registry         = $registry;
195
-        $this->loader           = $loader;
196
-        $this->request          = $request;
197
-        $this->maintenance_mode = $maintenance_mode;
198
-        do_action('AHEE__EE_System__construct__begin', $this);
199
-        add_action(
200
-            'AHEE__EE_Bootstrap__load_espresso_addons',
201
-            array($this, 'loadCapabilities'),
202
-            5
203
-        );
204
-        add_action(
205
-            'AHEE__EE_Bootstrap__load_espresso_addons',
206
-            array($this, 'loadCommandBus'),
207
-            7
208
-        );
209
-        add_action(
210
-            'AHEE__EE_Bootstrap__load_espresso_addons',
211
-            array($this, 'loadPluginApi'),
212
-            9
213
-        );
214
-        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
215
-        add_action(
216
-            'AHEE__EE_Bootstrap__load_espresso_addons',
217
-            array($this, 'load_espresso_addons')
218
-        );
219
-        // when an ee addon is activated, we want to call the core hook(s) again
220
-        // because the newly-activated addon didn't get a chance to run at all
221
-        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
222
-        // detect whether install or upgrade
223
-        add_action(
224
-            'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
225
-            array($this, 'detect_activations_or_upgrades'),
226
-            3
227
-        );
228
-        // load EE_Config, EE_Textdomain, etc
229
-        add_action(
230
-            'AHEE__EE_Bootstrap__load_core_configuration',
231
-            array($this, 'load_core_configuration'),
232
-            5
233
-        );
234
-        // load EE_Config, EE_Textdomain, etc
235
-        add_action(
236
-            'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
237
-            array($this, 'register_shortcodes_modules_and_widgets'),
238
-            7
239
-        );
240
-        // you wanna get going? I wanna get going... let's get going!
241
-        add_action(
242
-            'AHEE__EE_Bootstrap__brew_espresso',
243
-            array($this, 'brew_espresso'),
244
-            9
245
-        );
246
-        //other housekeeping
247
-        //exclude EE critical pages from wp_list_pages
248
-        add_filter(
249
-            'wp_list_pages_excludes',
250
-            array($this, 'remove_pages_from_wp_list_pages'),
251
-            10
252
-        );
253
-        // ALL EE Addons should use the following hook point to attach their initial setup too
254
-        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
255
-        do_action('AHEE__EE_System__construct__complete', $this);
256
-    }
257
-
258
-
259
-    /**
260
-     * load and setup EE_Capabilities
261
-     *
262
-     * @return void
263
-     * @throws EE_Error
264
-     */
265
-    public function loadCapabilities()
266
-    {
267
-        $this->capabilities = $this->loader->getShared('EE_Capabilities');
268
-        add_action(
269
-            'AHEE__EE_Capabilities__init_caps__before_initialization',
270
-            function ()
271
-            {
272
-                LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
273
-            }
274
-        );
275
-    }
276
-
277
-
278
-
279
-    /**
280
-     * create and cache the CommandBus, and also add middleware
281
-     * The CapChecker middleware requires the use of EE_Capabilities
282
-     * which is why we need to load the CommandBus after Caps are set up
283
-     *
284
-     * @return void
285
-     * @throws EE_Error
286
-     */
287
-    public function loadCommandBus()
288
-    {
289
-        $this->loader->getShared(
290
-            'CommandBusInterface',
291
-            array(
292
-                null,
293
-                apply_filters(
294
-                    'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
295
-                    array(
296
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
297
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
298
-                    )
299
-                ),
300
-            )
301
-        );
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @return void
308
-     * @throws EE_Error
309
-     */
310
-    public function loadPluginApi()
311
-    {
312
-        // set autoloaders for all of the classes implementing EEI_Plugin_API
313
-        // which provide helpers for EE plugin authors to more easily register certain components with EE.
314
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
315
-        $this->loader->getShared('EE_Request_Handler');
316
-    }
317
-
318
-
319
-    /**
320
-     * @param string $addon_name
321
-     * @param string $version_constant
322
-     * @param string $min_version_required
323
-     * @param string $load_callback
324
-     * @param string $plugin_file_constant
325
-     * @return void
326
-     */
327
-    private function deactivateIncompatibleAddon(
328
-        $addon_name,
329
-        $version_constant,
330
-        $min_version_required,
331
-        $load_callback,
332
-        $plugin_file_constant
333
-    ) {
334
-        if (! defined($version_constant)) {
335
-            return;
336
-        }
337
-        $addon_version = constant($version_constant);
338
-        if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
339
-            remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
340
-            if (! function_exists('deactivate_plugins')) {
341
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
342
-            }
343
-            deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
344
-            unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
345
-            EE_Error::add_error(
346
-                sprintf(
347
-                    esc_html__(
348
-                        'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
349
-                        'event_espresso'
350
-                    ),
351
-                    $addon_name,
352
-                    $min_version_required
353
-                ),
354
-                __FILE__, __FUNCTION__ . "({$addon_name})", __LINE__
355
-            );
356
-            EE_Error::get_notices(false, true);
357
-        }
358
-    }
359
-
360
-
361
-    /**
362
-     * load_espresso_addons
363
-     * allow addons to load first so that they can set hooks for running DMS's, etc
364
-     * this is hooked into both:
365
-     *    'AHEE__EE_Bootstrap__load_core_configuration'
366
-     *        which runs during the WP 'plugins_loaded' action at priority 5
367
-     *    and the WP 'activate_plugin' hook point
368
-     *
369
-     * @access public
370
-     * @return void
371
-     */
372
-    public function load_espresso_addons()
373
-    {
374
-        $this->deactivateIncompatibleAddon(
375
-            'Wait Lists',
376
-            'EE_WAIT_LISTS_VERSION',
377
-            '1.0.0.beta.074',
378
-            'load_espresso_wait_lists',
379
-            'EE_WAIT_LISTS_PLUGIN_FILE'
380
-        );
381
-        $this->deactivateIncompatibleAddon(
382
-            'Automated Upcoming Event Notifications',
383
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
384
-            '1.0.0.beta.091',
385
-            'load_espresso_automated_upcoming_event_notification',
386
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
387
-        );
388
-        do_action('AHEE__EE_System__load_espresso_addons');
389
-        //if the WP API basic auth plugin isn't already loaded, load it now.
390
-        //We want it for mobile apps. Just include the entire plugin
391
-        //also, don't load the basic auth when a plugin is getting activated, because
392
-        //it could be the basic auth plugin, and it doesn't check if its methods are already defined
393
-        //and causes a fatal error
394
-        if (
395
-            $this->request->getRequestParam('activate') !== 'true'
396
-            && ! function_exists('json_basic_auth_handler')
397
-            && ! function_exists('json_basic_auth_error')
398
-            && ! in_array(
399
-                $this->request->getRequestParam('action'),
400
-                array('activate', 'activate-selected'),
401
-                true
402
-            )
403
-        ) {
404
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
405
-        }
406
-        do_action('AHEE__EE_System__load_espresso_addons__complete');
407
-    }
408
-
409
-
410
-
411
-    /**
412
-     * detect_activations_or_upgrades
413
-     * Checks for activation or upgrade of core first;
414
-     * then also checks if any registered addons have been activated or upgraded
415
-     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
416
-     * which runs during the WP 'plugins_loaded' action at priority 3
417
-     *
418
-     * @access public
419
-     * @return void
420
-     */
421
-    public function detect_activations_or_upgrades()
422
-    {
423
-        //first off: let's make sure to handle core
424
-        $this->detect_if_activation_or_upgrade();
425
-        foreach ($this->registry->addons as $addon) {
426
-            if ($addon instanceof EE_Addon) {
427
-                //detect teh request type for that addon
428
-                $addon->detect_activation_or_upgrade();
429
-            }
430
-        }
431
-    }
432
-
433
-
434
-
435
-    /**
436
-     * detect_if_activation_or_upgrade
437
-     * Takes care of detecting whether this is a brand new install or code upgrade,
438
-     * and either setting up the DB or setting up maintenance mode etc.
439
-     *
440
-     * @access public
441
-     * @return void
442
-     */
443
-    public function detect_if_activation_or_upgrade()
444
-    {
445
-        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
446
-        // check if db has been updated, or if its a brand-new installation
447
-        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
448
-        $request_type       = $this->detect_req_type($espresso_db_update);
449
-        //EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
450
-        switch ($request_type) {
451
-            case EE_System::req_type_new_activation:
452
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
453
-                $this->_handle_core_version_change($espresso_db_update);
454
-                break;
455
-            case EE_System::req_type_reactivation:
456
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
457
-                $this->_handle_core_version_change($espresso_db_update);
458
-                break;
459
-            case EE_System::req_type_upgrade:
460
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
461
-                //migrations may be required now that we've upgraded
462
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
463
-                $this->_handle_core_version_change($espresso_db_update);
464
-                //				echo "done upgrade";die;
465
-                break;
466
-            case EE_System::req_type_downgrade:
467
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
468
-                //its possible migrations are no longer required
469
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
470
-                $this->_handle_core_version_change($espresso_db_update);
471
-                break;
472
-            case EE_System::req_type_normal:
473
-            default:
474
-                break;
475
-        }
476
-        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
477
-    }
478
-
479
-
480
-
481
-    /**
482
-     * Updates the list of installed versions and sets hooks for
483
-     * initializing the database later during the request
484
-     *
485
-     * @param array $espresso_db_update
486
-     */
487
-    private function _handle_core_version_change($espresso_db_update)
488
-    {
489
-        $this->update_list_of_installed_versions($espresso_db_update);
490
-        //get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
491
-        add_action(
492
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
493
-            array($this, 'initialize_db_if_no_migrations_required')
494
-        );
495
-    }
496
-
497
-
498
-
499
-    /**
500
-     * standardizes the wp option 'espresso_db_upgrade' which actually stores
501
-     * information about what versions of EE have been installed and activated,
502
-     * NOT necessarily the state of the database
503
-     *
504
-     * @param mixed $espresso_db_update           the value of the WordPress option.
505
-     *                                            If not supplied, fetches it from the options table
506
-     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
507
-     */
508
-    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
509
-    {
510
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
511
-        if (! $espresso_db_update) {
512
-            $espresso_db_update = get_option('espresso_db_update');
513
-        }
514
-        // check that option is an array
515
-        if (! is_array($espresso_db_update)) {
516
-            // if option is FALSE, then it never existed
517
-            if ($espresso_db_update === false) {
518
-                // make $espresso_db_update an array and save option with autoload OFF
519
-                $espresso_db_update = array();
520
-                add_option('espresso_db_update', $espresso_db_update, '', 'no');
521
-            } else {
522
-                // option is NOT FALSE but also is NOT an array, so make it an array and save it
523
-                $espresso_db_update = array($espresso_db_update => array());
524
-                update_option('espresso_db_update', $espresso_db_update);
525
-            }
526
-        } else {
527
-            $corrected_db_update = array();
528
-            //if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
529
-            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
530
-                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
531
-                    //the key is an int, and the value IS NOT an array
532
-                    //so it must be numerically-indexed, where values are versions installed...
533
-                    //fix it!
534
-                    $version_string                         = $should_be_array;
535
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
536
-                } else {
537
-                    //ok it checks out
538
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
539
-                }
540
-            }
541
-            $espresso_db_update = $corrected_db_update;
542
-            update_option('espresso_db_update', $espresso_db_update);
543
-        }
544
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
545
-        return $espresso_db_update;
546
-    }
547
-
548
-
549
-
550
-    /**
551
-     * Does the traditional work of setting up the plugin's database and adding default data.
552
-     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
553
-     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
554
-     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
555
-     * so that it will be done when migrations are finished
556
-     *
557
-     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
558
-     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
559
-     *                                       This is a resource-intensive job
560
-     *                                       so we prefer to only do it when necessary
561
-     * @return void
562
-     * @throws EE_Error
563
-     */
564
-    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
565
-    {
566
-        $request_type = $this->detect_req_type();
567
-        //only initialize system if we're not in maintenance mode.
568
-        if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
569
-            update_option('ee_flush_rewrite_rules', true);
570
-            if ($verify_schema) {
571
-                EEH_Activation::initialize_db_and_folders();
572
-            }
573
-            EEH_Activation::initialize_db_content();
574
-            EEH_Activation::system_initialization();
575
-            if ($initialize_addons_too) {
576
-                $this->initialize_addons();
577
-            }
578
-        } else {
579
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
580
-        }
581
-        if ($request_type === EE_System::req_type_new_activation
582
-            || $request_type === EE_System::req_type_reactivation
583
-            || (
584
-                $request_type === EE_System::req_type_upgrade
585
-                && $this->is_major_version_change()
586
-            )
587
-        ) {
588
-            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
589
-        }
590
-    }
591
-
592
-
593
-
594
-    /**
595
-     * Initializes the db for all registered addons
596
-     *
597
-     * @throws EE_Error
598
-     */
599
-    public function initialize_addons()
600
-    {
601
-        //foreach registered addon, make sure its db is up-to-date too
602
-        foreach ($this->registry->addons as $addon) {
603
-            if ($addon instanceof EE_Addon) {
604
-                $addon->initialize_db_if_no_migrations_required();
605
-            }
606
-        }
607
-    }
608
-
609
-
610
-
611
-    /**
612
-     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
613
-     *
614
-     * @param    array  $version_history
615
-     * @param    string $current_version_to_add version to be added to the version history
616
-     * @return    boolean success as to whether or not this option was changed
617
-     */
618
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
619
-    {
620
-        if (! $version_history) {
621
-            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
622
-        }
623
-        if ($current_version_to_add === null) {
624
-            $current_version_to_add = espresso_version();
625
-        }
626
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
627
-        // re-save
628
-        return update_option('espresso_db_update', $version_history);
629
-    }
630
-
631
-
632
-
633
-    /**
634
-     * Detects if the current version indicated in the has existed in the list of
635
-     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
636
-     *
637
-     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
638
-     *                                  If not supplied, fetches it from the options table.
639
-     *                                  Also, caches its result so later parts of the code can also know whether
640
-     *                                  there's been an update or not. This way we can add the current version to
641
-     *                                  espresso_db_update, but still know if this is a new install or not
642
-     * @return int one of the constants on EE_System::req_type_
643
-     */
644
-    public function detect_req_type($espresso_db_update = null)
645
-    {
646
-        if ($this->_req_type === null) {
647
-            $espresso_db_update          = ! empty($espresso_db_update)
648
-                ? $espresso_db_update
649
-                : $this->fix_espresso_db_upgrade_option();
650
-            $this->_req_type             = EE_System::detect_req_type_given_activation_history(
651
-                $espresso_db_update,
652
-                'ee_espresso_activation', espresso_version()
653
-            );
654
-            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
655
-            $this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
656
-        }
657
-        return $this->_req_type;
658
-    }
659
-
660
-
661
-
662
-    /**
663
-     * Returns whether or not there was a non-micro version change (ie, change in either
664
-     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
665
-     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
666
-     *
667
-     * @param $activation_history
668
-     * @return bool
669
-     */
670
-    private function _detect_major_version_change($activation_history)
671
-    {
672
-        $previous_version       = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
673
-        $previous_version_parts = explode('.', $previous_version);
674
-        $current_version_parts  = explode('.', espresso_version());
675
-        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
676
-               && ($previous_version_parts[0] !== $current_version_parts[0]
677
-                   || $previous_version_parts[1] !== $current_version_parts[1]
678
-               );
679
-    }
680
-
681
-
682
-
683
-    /**
684
-     * Returns true if either the major or minor version of EE changed during this request.
685
-     * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
686
-     *
687
-     * @return bool
688
-     */
689
-    public function is_major_version_change()
690
-    {
691
-        return $this->_major_version_change;
692
-    }
693
-
694
-
695
-
696
-    /**
697
-     * Determines the request type for any ee addon, given three piece of info: the current array of activation
698
-     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
699
-     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
700
-     * just activated to (for core that will always be espresso_version())
701
-     *
702
-     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
703
-     *                                                 ee plugin. for core that's 'espresso_db_update'
704
-     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
705
-     *                                                 indicate that this plugin was just activated
706
-     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
707
-     *                                                 espresso_version())
708
-     * @return int one of the constants on EE_System::req_type_*
709
-     */
710
-    public static function detect_req_type_given_activation_history(
711
-        $activation_history_for_addon,
712
-        $activation_indicator_option_name,
713
-        $version_to_upgrade_to
714
-    ) {
715
-        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
716
-        if ($activation_history_for_addon) {
717
-            //it exists, so this isn't a completely new install
718
-            //check if this version already in that list of previously installed versions
719
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
720
-                //it a version we haven't seen before
721
-                if ($version_is_higher === 1) {
722
-                    $req_type = EE_System::req_type_upgrade;
723
-                } else {
724
-                    $req_type = EE_System::req_type_downgrade;
725
-                }
726
-                delete_option($activation_indicator_option_name);
727
-            } else {
728
-                // its not an update. maybe a reactivation?
729
-                if (get_option($activation_indicator_option_name, false)) {
730
-                    if ($version_is_higher === -1) {
731
-                        $req_type = EE_System::req_type_downgrade;
732
-                    } elseif ($version_is_higher === 0) {
733
-                        //we've seen this version before, but it's an activation. must be a reactivation
734
-                        $req_type = EE_System::req_type_reactivation;
735
-                    } else {//$version_is_higher === 1
736
-                        $req_type = EE_System::req_type_upgrade;
737
-                    }
738
-                    delete_option($activation_indicator_option_name);
739
-                } else {
740
-                    //we've seen this version before and the activation indicate doesn't show it was just activated
741
-                    if ($version_is_higher === -1) {
742
-                        $req_type = EE_System::req_type_downgrade;
743
-                    } elseif ($version_is_higher === 0) {
744
-                        //we've seen this version before and it's not an activation. its normal request
745
-                        $req_type = EE_System::req_type_normal;
746
-                    } else {//$version_is_higher === 1
747
-                        $req_type = EE_System::req_type_upgrade;
748
-                    }
749
-                }
750
-            }
751
-        } else {
752
-            //brand new install
753
-            $req_type = EE_System::req_type_new_activation;
754
-            delete_option($activation_indicator_option_name);
755
-        }
756
-        return $req_type;
757
-    }
758
-
759
-
760
-
761
-    /**
762
-     * Detects if the $version_to_upgrade_to is higher than the most recent version in
763
-     * the $activation_history_for_addon
764
-     *
765
-     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
766
-     *                                             sometimes containing 'unknown-date'
767
-     * @param string $version_to_upgrade_to        (current version)
768
-     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
769
-     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
770
-     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
771
-     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
772
-     */
773
-    private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
774
-    {
775
-        //find the most recently-activated version
776
-        $most_recently_active_version =
777
-            EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
778
-        return version_compare($version_to_upgrade_to, $most_recently_active_version);
779
-    }
780
-
781
-
782
-
783
-    /**
784
-     * Gets the most recently active version listed in the activation history,
785
-     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
786
-     *
787
-     * @param array $activation_history  (keys are versions, values are arrays of times activated,
788
-     *                                   sometimes containing 'unknown-date'
789
-     * @return string
790
-     */
791
-    private static function _get_most_recently_active_version_from_activation_history($activation_history)
792
-    {
793
-        $most_recently_active_version_activation = '1970-01-01 00:00:00';
794
-        $most_recently_active_version            = '0.0.0.dev.000';
795
-        if (is_array($activation_history)) {
796
-            foreach ($activation_history as $version => $times_activated) {
797
-                //check there is a record of when this version was activated. Otherwise,
798
-                //mark it as unknown
799
-                if (! $times_activated) {
800
-                    $times_activated = array('unknown-date');
801
-                }
802
-                if (is_string($times_activated)) {
803
-                    $times_activated = array($times_activated);
804
-                }
805
-                foreach ($times_activated as $an_activation) {
806
-                    if ($an_activation !== 'unknown-date'
807
-                        && $an_activation
808
-                           > $most_recently_active_version_activation) {
809
-                        $most_recently_active_version            = $version;
810
-                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
811
-                            ? '1970-01-01 00:00:00'
812
-                            : $an_activation;
813
-                    }
814
-                }
815
-            }
816
-        }
817
-        return $most_recently_active_version;
818
-    }
819
-
820
-
821
-
822
-    /**
823
-     * This redirects to the about EE page after activation
824
-     *
825
-     * @return void
826
-     */
827
-    public function redirect_to_about_ee()
828
-    {
829
-        $notices = EE_Error::get_notices(false);
830
-        //if current user is an admin and it's not an ajax or rest request
831
-        if (
832
-            ! isset($notices['errors'])
833
-            && $this->request->isAdmin()
834
-            && apply_filters(
835
-                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
836
-                $this->capabilities->current_user_can('manage_options', 'espresso_about_default')
837
-            )
838
-        ) {
839
-            $query_params = array('page' => 'espresso_about');
840
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
841
-                $query_params['new_activation'] = true;
842
-            }
843
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
844
-                $query_params['reactivation'] = true;
845
-            }
846
-            $url = add_query_arg($query_params, admin_url('admin.php'));
847
-            wp_safe_redirect($url);
848
-            exit();
849
-        }
850
-    }
851
-
852
-
853
-
854
-    /**
855
-     * load_core_configuration
856
-     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
857
-     * which runs during the WP 'plugins_loaded' action at priority 5
858
-     *
859
-     * @return void
860
-     * @throws ReflectionException
861
-     */
862
-    public function load_core_configuration()
863
-    {
864
-        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
865
-        $this->loader->getShared('EE_Load_Textdomain');
866
-        //load textdomain
867
-        EE_Load_Textdomain::load_textdomain();
868
-        // load and setup EE_Config and EE_Network_Config
869
-        $config = $this->loader->getShared('EE_Config');
870
-        $this->loader->getShared('EE_Network_Config');
871
-        // setup autoloaders
872
-        // enable logging?
873
-        if ($config->admin->use_full_logging) {
874
-            $this->loader->getShared('EE_Log');
875
-        }
876
-        // check for activation errors
877
-        $activation_errors = get_option('ee_plugin_activation_errors', false);
878
-        if ($activation_errors) {
879
-            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
880
-            update_option('ee_plugin_activation_errors', false);
881
-        }
882
-        // get model names
883
-        $this->_parse_model_names();
884
-        //load caf stuff a chance to play during the activation process too.
885
-        $this->_maybe_brew_regular();
886
-        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
887
-    }
888
-
889
-
890
-
891
-    /**
892
-     * cycles through all of the models/*.model.php files, and assembles an array of model names
893
-     *
894
-     * @return void
895
-     * @throws ReflectionException
896
-     */
897
-    private function _parse_model_names()
898
-    {
899
-        //get all the files in the EE_MODELS folder that end in .model.php
900
-        $models                 = glob(EE_MODELS . '*.model.php');
901
-        $model_names            = array();
902
-        $non_abstract_db_models = array();
903
-        foreach ($models as $model) {
904
-            // get model classname
905
-            $classname       = EEH_File::get_classname_from_filepath_with_standard_filename($model);
906
-            $short_name      = str_replace('EEM_', '', $classname);
907
-            $reflectionClass = new ReflectionClass($classname);
908
-            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
909
-                $non_abstract_db_models[ $short_name ] = $classname;
910
-            }
911
-            $model_names[ $short_name ] = $classname;
912
-        }
913
-        $this->registry->models                 = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
914
-        $this->registry->non_abstract_db_models = apply_filters(
915
-            'FHEE__EE_System__parse_implemented_model_names',
916
-            $non_abstract_db_models
917
-        );
918
-    }
919
-
920
-
921
-    /**
922
-     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
923
-     * that need to be setup before our EE_System launches.
924
-     *
925
-     * @return void
926
-     * @throws DomainException
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidDataTypeException
929
-     * @throws InvalidInterfaceException
930
-     * @throws InvalidClassException
931
-     * @throws InvalidFilePathException
932
-     */
933
-    private function _maybe_brew_regular()
934
-    {
935
-        /** @var Domain $domain */
936
-        $domain = DomainFactory::getShared(
937
-            new FullyQualifiedName(
938
-                'EventEspresso\core\domain\Domain'
939
-            ),
940
-            array(
941
-                new FilePath(EVENT_ESPRESSO_MAIN_FILE),
942
-                Version::fromString(espresso_version())
943
-            )
944
-        );
945
-        if ($domain->isCaffeinated()) {
946
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
947
-        }
948
-    }
949
-
950
-
951
-
952
-    /**
953
-     * register_shortcodes_modules_and_widgets
954
-     * generate lists of shortcodes and modules, then verify paths and classes
955
-     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
956
-     * which runs during the WP 'plugins_loaded' action at priority 7
957
-     *
958
-     * @access public
959
-     * @return void
960
-     * @throws Exception
961
-     */
962
-    public function register_shortcodes_modules_and_widgets()
963
-    {
964
-        if ($this->request->isFrontend() || $this->request->isIframe()) {
965
-            try {
966
-                // load, register, and add shortcodes the new way
967
-                $this->loader->getShared(
968
-                    'EventEspresso\core\services\shortcodes\ShortcodesManager',
969
-                    array(
970
-                        // and the old way, but we'll put it under control of the new system
971
-                        EE_Config::getLegacyShortcodesManager(),
972
-                    )
973
-                );
974
-            } catch (Exception $exception) {
975
-                new ExceptionStackTraceDisplay($exception);
976
-            }
977
-        }
978
-        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
979
-        // check for addons using old hook point
980
-        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
981
-            $this->_incompatible_addon_error();
982
-        }
983
-    }
984
-
985
-
986
-
987
-    /**
988
-     * _incompatible_addon_error
989
-     *
990
-     * @access public
991
-     * @return void
992
-     */
993
-    private function _incompatible_addon_error()
994
-    {
995
-        // get array of classes hooking into here
996
-        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
997
-            'AHEE__EE_System__register_shortcodes_modules_and_addons'
998
-        );
999
-        if (! empty($class_names)) {
1000
-            $msg = __(
1001
-                'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1002
-                'event_espresso'
1003
-            );
1004
-            $msg .= '<ul>';
1005
-            foreach ($class_names as $class_name) {
1006
-                $msg .= '<li><b>Event Espresso - ' . str_replace(
1007
-                        array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
1008
-                        $class_name
1009
-                    ) . '</b></li>';
1010
-            }
1011
-            $msg .= '</ul>';
1012
-            $msg .= __(
1013
-                'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1014
-                'event_espresso'
1015
-            );
1016
-            // save list of incompatible addons to wp-options for later use
1017
-            add_option('ee_incompatible_addons', $class_names, '', 'no');
1018
-            if (is_admin()) {
1019
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1020
-            }
1021
-        }
1022
-    }
1023
-
1024
-
1025
-
1026
-    /**
1027
-     * brew_espresso
1028
-     * begins the process of setting hooks for initializing EE in the correct order
1029
-     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1030
-     * which runs during the WP 'plugins_loaded' action at priority 9
1031
-     *
1032
-     * @return void
1033
-     */
1034
-    public function brew_espresso()
1035
-    {
1036
-        do_action('AHEE__EE_System__brew_espresso__begin', $this);
1037
-        // load some final core systems
1038
-        add_action('init', array($this, 'set_hooks_for_core'), 1);
1039
-        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1040
-        add_action('init', array($this, 'load_CPTs_and_session'), 5);
1041
-        add_action('init', array($this, 'load_controllers'), 7);
1042
-        add_action('init', array($this, 'core_loaded_and_ready'), 9);
1043
-        add_action('init', array($this, 'initialize'), 10);
1044
-        add_action('init', array($this, 'initialize_last'), 100);
1045
-        if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1046
-            // pew pew pew
1047
-            $this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1048
-            do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1049
-        }
1050
-        do_action('AHEE__EE_System__brew_espresso__complete', $this);
1051
-    }
1052
-
1053
-
1054
-
1055
-    /**
1056
-     *    set_hooks_for_core
1057
-     *
1058
-     * @access public
1059
-     * @return    void
1060
-     * @throws EE_Error
1061
-     */
1062
-    public function set_hooks_for_core()
1063
-    {
1064
-        $this->_deactivate_incompatible_addons();
1065
-        do_action('AHEE__EE_System__set_hooks_for_core');
1066
-        $this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1067
-        //caps need to be initialized on every request so that capability maps are set.
1068
-        //@see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1069
-        $this->registry->CAP->init_caps();
1070
-    }
1071
-
1072
-
1073
-
1074
-    /**
1075
-     * Using the information gathered in EE_System::_incompatible_addon_error,
1076
-     * deactivates any addons considered incompatible with the current version of EE
1077
-     */
1078
-    private function _deactivate_incompatible_addons()
1079
-    {
1080
-        $incompatible_addons = get_option('ee_incompatible_addons', array());
1081
-        if (! empty($incompatible_addons)) {
1082
-            $active_plugins = get_option('active_plugins', array());
1083
-            foreach ($active_plugins as $active_plugin) {
1084
-                foreach ($incompatible_addons as $incompatible_addon) {
1085
-                    if (strpos($active_plugin, $incompatible_addon) !== false) {
1086
-                        unset($_GET['activate']);
1087
-                        espresso_deactivate_plugin($active_plugin);
1088
-                    }
1089
-                }
1090
-            }
1091
-        }
1092
-    }
1093
-
1094
-
1095
-
1096
-    /**
1097
-     *    perform_activations_upgrades_and_migrations
1098
-     *
1099
-     * @access public
1100
-     * @return    void
1101
-     */
1102
-    public function perform_activations_upgrades_and_migrations()
1103
-    {
1104
-        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1105
-    }
1106
-
1107
-
1108
-
1109
-    /**
1110
-     *    load_CPTs_and_session
1111
-     *
1112
-     * @access public
1113
-     * @return    void
1114
-     */
1115
-    public function load_CPTs_and_session()
1116
-    {
1117
-        do_action('AHEE__EE_System__load_CPTs_and_session__start');
1118
-        // register Custom Post Types
1119
-        $this->loader->getShared('EE_Register_CPTs');
1120
-        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1121
-    }
1122
-
1123
-
1124
-
1125
-    /**
1126
-     * load_controllers
1127
-     * this is the best place to load any additional controllers that needs access to EE core.
1128
-     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1129
-     * time
1130
-     *
1131
-     * @access public
1132
-     * @return void
1133
-     */
1134
-    public function load_controllers()
1135
-    {
1136
-        do_action('AHEE__EE_System__load_controllers__start');
1137
-        // let's get it started
1138
-        if (
1139
-            ! $this->maintenance_mode->level()
1140
-            && ($this->request->isFrontend() || $this->request->isFrontAjax())
1141
-        ) {
1142
-            do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1143
-            $this->loader->getShared('EE_Front_Controller');
1144
-        } elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1145
-            do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1146
-            $this->loader->getShared('EE_Admin');
1147
-        }
1148
-        do_action('AHEE__EE_System__load_controllers__complete');
1149
-    }
1150
-
1151
-
1152
-
1153
-    /**
1154
-     * core_loaded_and_ready
1155
-     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1156
-     *
1157
-     * @access public
1158
-     * @return void
1159
-     */
1160
-    public function core_loaded_and_ready()
1161
-    {
1162
-        if (
1163
-            $this->request->isAdmin()
1164
-            || $this->request->isEeAjax()
1165
-            || $this->request->isFrontend()
1166
-        ) {
1167
-            $this->loader->getShared('EE_Session');
1168
-        }
1169
-        do_action('AHEE__EE_System__core_loaded_and_ready');
1170
-        // load_espresso_template_tags
1171
-        if (
1172
-            is_readable(EE_PUBLIC . 'template_tags.php')
1173
-            && ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isFeed())
1174
-        ) {
1175
-            require_once EE_PUBLIC . 'template_tags.php';
1176
-        }
1177
-        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1178
-        if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
1179
-            $this->loader->getShared('EventEspresso\core\services\assets\Registry');
1180
-        }
1181
-    }
1182
-
1183
-
1184
-
1185
-    /**
1186
-     * initialize
1187
-     * this is the best place to begin initializing client code
1188
-     *
1189
-     * @access public
1190
-     * @return void
1191
-     */
1192
-    public function initialize()
1193
-    {
1194
-        do_action('AHEE__EE_System__initialize');
1195
-    }
1196
-
1197
-
1198
-
1199
-    /**
1200
-     * initialize_last
1201
-     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1202
-     * initialize has done so
1203
-     *
1204
-     * @access public
1205
-     * @return void
1206
-     */
1207
-    public function initialize_last()
1208
-    {
1209
-        do_action('AHEE__EE_System__initialize_last');
1210
-        add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1211
-    }
1212
-
1213
-
1214
-
1215
-    /**
1216
-     * @return void
1217
-     * @throws EE_Error
1218
-     */
1219
-    public function addEspressoToolbar()
1220
-    {
1221
-        $this->loader->getShared(
1222
-            'EventEspresso\core\domain\services\admin\AdminToolBar',
1223
-            array($this->registry->CAP)
1224
-        );
1225
-    }
1226
-
1227
-
1228
-
1229
-    /**
1230
-     * do_not_cache
1231
-     * sets no cache headers and defines no cache constants for WP plugins
1232
-     *
1233
-     * @access public
1234
-     * @return void
1235
-     */
1236
-    public static function do_not_cache()
1237
-    {
1238
-        // set no cache constants
1239
-        if (! defined('DONOTCACHEPAGE')) {
1240
-            define('DONOTCACHEPAGE', true);
1241
-        }
1242
-        if (! defined('DONOTCACHCEOBJECT')) {
1243
-            define('DONOTCACHCEOBJECT', true);
1244
-        }
1245
-        if (! defined('DONOTCACHEDB')) {
1246
-            define('DONOTCACHEDB', true);
1247
-        }
1248
-        // add no cache headers
1249
-        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1250
-        // plus a little extra for nginx and Google Chrome
1251
-        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1252
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1253
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1254
-    }
1255
-
1256
-
1257
-
1258
-    /**
1259
-     *    extra_nocache_headers
1260
-     *
1261
-     * @access    public
1262
-     * @param $headers
1263
-     * @return    array
1264
-     */
1265
-    public static function extra_nocache_headers($headers)
1266
-    {
1267
-        // for NGINX
1268
-        $headers['X-Accel-Expires'] = 0;
1269
-        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1270
-        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1271
-        return $headers;
1272
-    }
1273
-
1274
-
1275
-
1276
-    /**
1277
-     *    nocache_headers
1278
-     *
1279
-     * @access    public
1280
-     * @return    void
1281
-     */
1282
-    public static function nocache_headers()
1283
-    {
1284
-        nocache_headers();
1285
-    }
1286
-
1287
-
1288
-
1289
-    /**
1290
-     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1291
-     * never returned with the function.
1292
-     *
1293
-     * @param  array $exclude_array any existing pages being excluded are in this array.
1294
-     * @return array
1295
-     */
1296
-    public function remove_pages_from_wp_list_pages($exclude_array)
1297
-    {
1298
-        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1299
-    }
35
+	/**
36
+	 * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
37
+	 * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
38
+	 */
39
+	const req_type_normal = 0;
40
+
41
+	/**
42
+	 * Indicates this is a brand new installation of EE so we should install
43
+	 * tables and default data etc
44
+	 */
45
+	const req_type_new_activation = 1;
46
+
47
+	/**
48
+	 * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
49
+	 * and we just exited maintenance mode). We MUST check the database is setup properly
50
+	 * and that default data is setup too
51
+	 */
52
+	const req_type_reactivation = 2;
53
+
54
+	/**
55
+	 * indicates that EE has been upgraded since its previous request.
56
+	 * We may have data migration scripts to call and will want to trigger maintenance mode
57
+	 */
58
+	const req_type_upgrade = 3;
59
+
60
+	/**
61
+	 * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
62
+	 */
63
+	const req_type_downgrade = 4;
64
+
65
+	/**
66
+	 * @deprecated since version 4.6.0.dev.006
67
+	 * Now whenever a new_activation is detected the request type is still just
68
+	 * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
69
+	 * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
70
+	 * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
71
+	 * (Specifically, when the migration manager indicates migrations are finished
72
+	 * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
73
+	 */
74
+	const req_type_activation_but_not_installed = 5;
75
+
76
+	/**
77
+	 * option prefix for recording the activation history (like core's "espresso_db_update") of addons
78
+	 */
79
+	const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
80
+
81
+
82
+	/**
83
+	 * @var EE_System $_instance
84
+	 */
85
+	private static $_instance;
86
+
87
+	/**
88
+	 * @var EE_Registry $registry
89
+	 */
90
+	private $registry;
91
+
92
+	/**
93
+	 * @var LoaderInterface $loader
94
+	 */
95
+	private $loader;
96
+
97
+	/**
98
+	 * @var EE_Capabilities $capabilities
99
+	 */
100
+	private $capabilities;
101
+
102
+	/**
103
+	 * @var RequestInterface $request
104
+	 */
105
+	private $request;
106
+
107
+	/**
108
+	 * @var EE_Maintenance_Mode $maintenance_mode
109
+	 */
110
+	private $maintenance_mode;
111
+
112
+	/**
113
+	 * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
114
+	 * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
115
+	 *
116
+	 * @var int $_req_type
117
+	 */
118
+	private $_req_type;
119
+
120
+	/**
121
+	 * Whether or not there was a non-micro version change in EE core version during this request
122
+	 *
123
+	 * @var boolean $_major_version_change
124
+	 */
125
+	private $_major_version_change = false;
126
+
127
+	/**
128
+	 * A Context DTO dedicated solely to identifying the current request type.
129
+	 *
130
+	 * @var RequestTypeContextCheckerInterface $request_type
131
+	 */
132
+	private $request_type;
133
+
134
+
135
+
136
+	/**
137
+	 * @singleton method used to instantiate class object
138
+	 * @param EE_Registry|null         $registry
139
+	 * @param LoaderInterface|null     $loader
140
+	 * @param RequestInterface|null          $request
141
+	 * @param EE_Maintenance_Mode|null $maintenance_mode
142
+	 * @return EE_System
143
+	 */
144
+	public static function instance(
145
+		EE_Registry $registry = null,
146
+		LoaderInterface $loader = null,
147
+		RequestInterface $request = null,
148
+		EE_Maintenance_Mode $maintenance_mode = null
149
+	) {
150
+		// check if class object is instantiated
151
+		if (! self::$_instance instanceof EE_System) {
152
+			self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
153
+		}
154
+		return self::$_instance;
155
+	}
156
+
157
+
158
+
159
+	/**
160
+	 * resets the instance and returns it
161
+	 *
162
+	 * @return EE_System
163
+	 */
164
+	public static function reset()
165
+	{
166
+		self::$_instance->_req_type = null;
167
+		//make sure none of the old hooks are left hanging around
168
+		remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
169
+		//we need to reset the migration manager in order for it to detect DMSs properly
170
+		EE_Data_Migration_Manager::reset();
171
+		self::instance()->detect_activations_or_upgrades();
172
+		self::instance()->perform_activations_upgrades_and_migrations();
173
+		return self::instance();
174
+	}
175
+
176
+
177
+
178
+	/**
179
+	 * sets hooks for running rest of system
180
+	 * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
181
+	 * starting EE Addons from any other point may lead to problems
182
+	 *
183
+	 * @param EE_Registry         $registry
184
+	 * @param LoaderInterface     $loader
185
+	 * @param RequestInterface          $request
186
+	 * @param EE_Maintenance_Mode $maintenance_mode
187
+	 */
188
+	private function __construct(
189
+		EE_Registry $registry,
190
+		LoaderInterface $loader,
191
+		RequestInterface $request,
192
+		EE_Maintenance_Mode $maintenance_mode
193
+	) {
194
+		$this->registry         = $registry;
195
+		$this->loader           = $loader;
196
+		$this->request          = $request;
197
+		$this->maintenance_mode = $maintenance_mode;
198
+		do_action('AHEE__EE_System__construct__begin', $this);
199
+		add_action(
200
+			'AHEE__EE_Bootstrap__load_espresso_addons',
201
+			array($this, 'loadCapabilities'),
202
+			5
203
+		);
204
+		add_action(
205
+			'AHEE__EE_Bootstrap__load_espresso_addons',
206
+			array($this, 'loadCommandBus'),
207
+			7
208
+		);
209
+		add_action(
210
+			'AHEE__EE_Bootstrap__load_espresso_addons',
211
+			array($this, 'loadPluginApi'),
212
+			9
213
+		);
214
+		// allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
215
+		add_action(
216
+			'AHEE__EE_Bootstrap__load_espresso_addons',
217
+			array($this, 'load_espresso_addons')
218
+		);
219
+		// when an ee addon is activated, we want to call the core hook(s) again
220
+		// because the newly-activated addon didn't get a chance to run at all
221
+		add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
222
+		// detect whether install or upgrade
223
+		add_action(
224
+			'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
225
+			array($this, 'detect_activations_or_upgrades'),
226
+			3
227
+		);
228
+		// load EE_Config, EE_Textdomain, etc
229
+		add_action(
230
+			'AHEE__EE_Bootstrap__load_core_configuration',
231
+			array($this, 'load_core_configuration'),
232
+			5
233
+		);
234
+		// load EE_Config, EE_Textdomain, etc
235
+		add_action(
236
+			'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
237
+			array($this, 'register_shortcodes_modules_and_widgets'),
238
+			7
239
+		);
240
+		// you wanna get going? I wanna get going... let's get going!
241
+		add_action(
242
+			'AHEE__EE_Bootstrap__brew_espresso',
243
+			array($this, 'brew_espresso'),
244
+			9
245
+		);
246
+		//other housekeeping
247
+		//exclude EE critical pages from wp_list_pages
248
+		add_filter(
249
+			'wp_list_pages_excludes',
250
+			array($this, 'remove_pages_from_wp_list_pages'),
251
+			10
252
+		);
253
+		// ALL EE Addons should use the following hook point to attach their initial setup too
254
+		// it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
255
+		do_action('AHEE__EE_System__construct__complete', $this);
256
+	}
257
+
258
+
259
+	/**
260
+	 * load and setup EE_Capabilities
261
+	 *
262
+	 * @return void
263
+	 * @throws EE_Error
264
+	 */
265
+	public function loadCapabilities()
266
+	{
267
+		$this->capabilities = $this->loader->getShared('EE_Capabilities');
268
+		add_action(
269
+			'AHEE__EE_Capabilities__init_caps__before_initialization',
270
+			function ()
271
+			{
272
+				LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
273
+			}
274
+		);
275
+	}
276
+
277
+
278
+
279
+	/**
280
+	 * create and cache the CommandBus, and also add middleware
281
+	 * The CapChecker middleware requires the use of EE_Capabilities
282
+	 * which is why we need to load the CommandBus after Caps are set up
283
+	 *
284
+	 * @return void
285
+	 * @throws EE_Error
286
+	 */
287
+	public function loadCommandBus()
288
+	{
289
+		$this->loader->getShared(
290
+			'CommandBusInterface',
291
+			array(
292
+				null,
293
+				apply_filters(
294
+					'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
295
+					array(
296
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
297
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
298
+					)
299
+				),
300
+			)
301
+		);
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @return void
308
+	 * @throws EE_Error
309
+	 */
310
+	public function loadPluginApi()
311
+	{
312
+		// set autoloaders for all of the classes implementing EEI_Plugin_API
313
+		// which provide helpers for EE plugin authors to more easily register certain components with EE.
314
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
315
+		$this->loader->getShared('EE_Request_Handler');
316
+	}
317
+
318
+
319
+	/**
320
+	 * @param string $addon_name
321
+	 * @param string $version_constant
322
+	 * @param string $min_version_required
323
+	 * @param string $load_callback
324
+	 * @param string $plugin_file_constant
325
+	 * @return void
326
+	 */
327
+	private function deactivateIncompatibleAddon(
328
+		$addon_name,
329
+		$version_constant,
330
+		$min_version_required,
331
+		$load_callback,
332
+		$plugin_file_constant
333
+	) {
334
+		if (! defined($version_constant)) {
335
+			return;
336
+		}
337
+		$addon_version = constant($version_constant);
338
+		if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
339
+			remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
340
+			if (! function_exists('deactivate_plugins')) {
341
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
342
+			}
343
+			deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
344
+			unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
345
+			EE_Error::add_error(
346
+				sprintf(
347
+					esc_html__(
348
+						'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
349
+						'event_espresso'
350
+					),
351
+					$addon_name,
352
+					$min_version_required
353
+				),
354
+				__FILE__, __FUNCTION__ . "({$addon_name})", __LINE__
355
+			);
356
+			EE_Error::get_notices(false, true);
357
+		}
358
+	}
359
+
360
+
361
+	/**
362
+	 * load_espresso_addons
363
+	 * allow addons to load first so that they can set hooks for running DMS's, etc
364
+	 * this is hooked into both:
365
+	 *    'AHEE__EE_Bootstrap__load_core_configuration'
366
+	 *        which runs during the WP 'plugins_loaded' action at priority 5
367
+	 *    and the WP 'activate_plugin' hook point
368
+	 *
369
+	 * @access public
370
+	 * @return void
371
+	 */
372
+	public function load_espresso_addons()
373
+	{
374
+		$this->deactivateIncompatibleAddon(
375
+			'Wait Lists',
376
+			'EE_WAIT_LISTS_VERSION',
377
+			'1.0.0.beta.074',
378
+			'load_espresso_wait_lists',
379
+			'EE_WAIT_LISTS_PLUGIN_FILE'
380
+		);
381
+		$this->deactivateIncompatibleAddon(
382
+			'Automated Upcoming Event Notifications',
383
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
384
+			'1.0.0.beta.091',
385
+			'load_espresso_automated_upcoming_event_notification',
386
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
387
+		);
388
+		do_action('AHEE__EE_System__load_espresso_addons');
389
+		//if the WP API basic auth plugin isn't already loaded, load it now.
390
+		//We want it for mobile apps. Just include the entire plugin
391
+		//also, don't load the basic auth when a plugin is getting activated, because
392
+		//it could be the basic auth plugin, and it doesn't check if its methods are already defined
393
+		//and causes a fatal error
394
+		if (
395
+			$this->request->getRequestParam('activate') !== 'true'
396
+			&& ! function_exists('json_basic_auth_handler')
397
+			&& ! function_exists('json_basic_auth_error')
398
+			&& ! in_array(
399
+				$this->request->getRequestParam('action'),
400
+				array('activate', 'activate-selected'),
401
+				true
402
+			)
403
+		) {
404
+			include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
405
+		}
406
+		do_action('AHEE__EE_System__load_espresso_addons__complete');
407
+	}
408
+
409
+
410
+
411
+	/**
412
+	 * detect_activations_or_upgrades
413
+	 * Checks for activation or upgrade of core first;
414
+	 * then also checks if any registered addons have been activated or upgraded
415
+	 * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
416
+	 * which runs during the WP 'plugins_loaded' action at priority 3
417
+	 *
418
+	 * @access public
419
+	 * @return void
420
+	 */
421
+	public function detect_activations_or_upgrades()
422
+	{
423
+		//first off: let's make sure to handle core
424
+		$this->detect_if_activation_or_upgrade();
425
+		foreach ($this->registry->addons as $addon) {
426
+			if ($addon instanceof EE_Addon) {
427
+				//detect teh request type for that addon
428
+				$addon->detect_activation_or_upgrade();
429
+			}
430
+		}
431
+	}
432
+
433
+
434
+
435
+	/**
436
+	 * detect_if_activation_or_upgrade
437
+	 * Takes care of detecting whether this is a brand new install or code upgrade,
438
+	 * and either setting up the DB or setting up maintenance mode etc.
439
+	 *
440
+	 * @access public
441
+	 * @return void
442
+	 */
443
+	public function detect_if_activation_or_upgrade()
444
+	{
445
+		do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
446
+		// check if db has been updated, or if its a brand-new installation
447
+		$espresso_db_update = $this->fix_espresso_db_upgrade_option();
448
+		$request_type       = $this->detect_req_type($espresso_db_update);
449
+		//EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
450
+		switch ($request_type) {
451
+			case EE_System::req_type_new_activation:
452
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
453
+				$this->_handle_core_version_change($espresso_db_update);
454
+				break;
455
+			case EE_System::req_type_reactivation:
456
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
457
+				$this->_handle_core_version_change($espresso_db_update);
458
+				break;
459
+			case EE_System::req_type_upgrade:
460
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
461
+				//migrations may be required now that we've upgraded
462
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
463
+				$this->_handle_core_version_change($espresso_db_update);
464
+				//				echo "done upgrade";die;
465
+				break;
466
+			case EE_System::req_type_downgrade:
467
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
468
+				//its possible migrations are no longer required
469
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
470
+				$this->_handle_core_version_change($espresso_db_update);
471
+				break;
472
+			case EE_System::req_type_normal:
473
+			default:
474
+				break;
475
+		}
476
+		do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
477
+	}
478
+
479
+
480
+
481
+	/**
482
+	 * Updates the list of installed versions and sets hooks for
483
+	 * initializing the database later during the request
484
+	 *
485
+	 * @param array $espresso_db_update
486
+	 */
487
+	private function _handle_core_version_change($espresso_db_update)
488
+	{
489
+		$this->update_list_of_installed_versions($espresso_db_update);
490
+		//get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
491
+		add_action(
492
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
493
+			array($this, 'initialize_db_if_no_migrations_required')
494
+		);
495
+	}
496
+
497
+
498
+
499
+	/**
500
+	 * standardizes the wp option 'espresso_db_upgrade' which actually stores
501
+	 * information about what versions of EE have been installed and activated,
502
+	 * NOT necessarily the state of the database
503
+	 *
504
+	 * @param mixed $espresso_db_update           the value of the WordPress option.
505
+	 *                                            If not supplied, fetches it from the options table
506
+	 * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
507
+	 */
508
+	private function fix_espresso_db_upgrade_option($espresso_db_update = null)
509
+	{
510
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
511
+		if (! $espresso_db_update) {
512
+			$espresso_db_update = get_option('espresso_db_update');
513
+		}
514
+		// check that option is an array
515
+		if (! is_array($espresso_db_update)) {
516
+			// if option is FALSE, then it never existed
517
+			if ($espresso_db_update === false) {
518
+				// make $espresso_db_update an array and save option with autoload OFF
519
+				$espresso_db_update = array();
520
+				add_option('espresso_db_update', $espresso_db_update, '', 'no');
521
+			} else {
522
+				// option is NOT FALSE but also is NOT an array, so make it an array and save it
523
+				$espresso_db_update = array($espresso_db_update => array());
524
+				update_option('espresso_db_update', $espresso_db_update);
525
+			}
526
+		} else {
527
+			$corrected_db_update = array();
528
+			//if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
529
+			foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
530
+				if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
531
+					//the key is an int, and the value IS NOT an array
532
+					//so it must be numerically-indexed, where values are versions installed...
533
+					//fix it!
534
+					$version_string                         = $should_be_array;
535
+					$corrected_db_update[ $version_string ] = array('unknown-date');
536
+				} else {
537
+					//ok it checks out
538
+					$corrected_db_update[ $should_be_version_string ] = $should_be_array;
539
+				}
540
+			}
541
+			$espresso_db_update = $corrected_db_update;
542
+			update_option('espresso_db_update', $espresso_db_update);
543
+		}
544
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
545
+		return $espresso_db_update;
546
+	}
547
+
548
+
549
+
550
+	/**
551
+	 * Does the traditional work of setting up the plugin's database and adding default data.
552
+	 * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
553
+	 * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
554
+	 * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
555
+	 * so that it will be done when migrations are finished
556
+	 *
557
+	 * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
558
+	 * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
559
+	 *                                       This is a resource-intensive job
560
+	 *                                       so we prefer to only do it when necessary
561
+	 * @return void
562
+	 * @throws EE_Error
563
+	 */
564
+	public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
565
+	{
566
+		$request_type = $this->detect_req_type();
567
+		//only initialize system if we're not in maintenance mode.
568
+		if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
569
+			update_option('ee_flush_rewrite_rules', true);
570
+			if ($verify_schema) {
571
+				EEH_Activation::initialize_db_and_folders();
572
+			}
573
+			EEH_Activation::initialize_db_content();
574
+			EEH_Activation::system_initialization();
575
+			if ($initialize_addons_too) {
576
+				$this->initialize_addons();
577
+			}
578
+		} else {
579
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
580
+		}
581
+		if ($request_type === EE_System::req_type_new_activation
582
+			|| $request_type === EE_System::req_type_reactivation
583
+			|| (
584
+				$request_type === EE_System::req_type_upgrade
585
+				&& $this->is_major_version_change()
586
+			)
587
+		) {
588
+			add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
589
+		}
590
+	}
591
+
592
+
593
+
594
+	/**
595
+	 * Initializes the db for all registered addons
596
+	 *
597
+	 * @throws EE_Error
598
+	 */
599
+	public function initialize_addons()
600
+	{
601
+		//foreach registered addon, make sure its db is up-to-date too
602
+		foreach ($this->registry->addons as $addon) {
603
+			if ($addon instanceof EE_Addon) {
604
+				$addon->initialize_db_if_no_migrations_required();
605
+			}
606
+		}
607
+	}
608
+
609
+
610
+
611
+	/**
612
+	 * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
613
+	 *
614
+	 * @param    array  $version_history
615
+	 * @param    string $current_version_to_add version to be added to the version history
616
+	 * @return    boolean success as to whether or not this option was changed
617
+	 */
618
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
619
+	{
620
+		if (! $version_history) {
621
+			$version_history = $this->fix_espresso_db_upgrade_option($version_history);
622
+		}
623
+		if ($current_version_to_add === null) {
624
+			$current_version_to_add = espresso_version();
625
+		}
626
+		$version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
627
+		// re-save
628
+		return update_option('espresso_db_update', $version_history);
629
+	}
630
+
631
+
632
+
633
+	/**
634
+	 * Detects if the current version indicated in the has existed in the list of
635
+	 * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
636
+	 *
637
+	 * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
638
+	 *                                  If not supplied, fetches it from the options table.
639
+	 *                                  Also, caches its result so later parts of the code can also know whether
640
+	 *                                  there's been an update or not. This way we can add the current version to
641
+	 *                                  espresso_db_update, but still know if this is a new install or not
642
+	 * @return int one of the constants on EE_System::req_type_
643
+	 */
644
+	public function detect_req_type($espresso_db_update = null)
645
+	{
646
+		if ($this->_req_type === null) {
647
+			$espresso_db_update          = ! empty($espresso_db_update)
648
+				? $espresso_db_update
649
+				: $this->fix_espresso_db_upgrade_option();
650
+			$this->_req_type             = EE_System::detect_req_type_given_activation_history(
651
+				$espresso_db_update,
652
+				'ee_espresso_activation', espresso_version()
653
+			);
654
+			$this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
655
+			$this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
656
+		}
657
+		return $this->_req_type;
658
+	}
659
+
660
+
661
+
662
+	/**
663
+	 * Returns whether or not there was a non-micro version change (ie, change in either
664
+	 * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
665
+	 * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
666
+	 *
667
+	 * @param $activation_history
668
+	 * @return bool
669
+	 */
670
+	private function _detect_major_version_change($activation_history)
671
+	{
672
+		$previous_version       = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
673
+		$previous_version_parts = explode('.', $previous_version);
674
+		$current_version_parts  = explode('.', espresso_version());
675
+		return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
676
+			   && ($previous_version_parts[0] !== $current_version_parts[0]
677
+				   || $previous_version_parts[1] !== $current_version_parts[1]
678
+			   );
679
+	}
680
+
681
+
682
+
683
+	/**
684
+	 * Returns true if either the major or minor version of EE changed during this request.
685
+	 * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
686
+	 *
687
+	 * @return bool
688
+	 */
689
+	public function is_major_version_change()
690
+	{
691
+		return $this->_major_version_change;
692
+	}
693
+
694
+
695
+
696
+	/**
697
+	 * Determines the request type for any ee addon, given three piece of info: the current array of activation
698
+	 * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
699
+	 * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
700
+	 * just activated to (for core that will always be espresso_version())
701
+	 *
702
+	 * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
703
+	 *                                                 ee plugin. for core that's 'espresso_db_update'
704
+	 * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
705
+	 *                                                 indicate that this plugin was just activated
706
+	 * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
707
+	 *                                                 espresso_version())
708
+	 * @return int one of the constants on EE_System::req_type_*
709
+	 */
710
+	public static function detect_req_type_given_activation_history(
711
+		$activation_history_for_addon,
712
+		$activation_indicator_option_name,
713
+		$version_to_upgrade_to
714
+	) {
715
+		$version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
716
+		if ($activation_history_for_addon) {
717
+			//it exists, so this isn't a completely new install
718
+			//check if this version already in that list of previously installed versions
719
+			if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
720
+				//it a version we haven't seen before
721
+				if ($version_is_higher === 1) {
722
+					$req_type = EE_System::req_type_upgrade;
723
+				} else {
724
+					$req_type = EE_System::req_type_downgrade;
725
+				}
726
+				delete_option($activation_indicator_option_name);
727
+			} else {
728
+				// its not an update. maybe a reactivation?
729
+				if (get_option($activation_indicator_option_name, false)) {
730
+					if ($version_is_higher === -1) {
731
+						$req_type = EE_System::req_type_downgrade;
732
+					} elseif ($version_is_higher === 0) {
733
+						//we've seen this version before, but it's an activation. must be a reactivation
734
+						$req_type = EE_System::req_type_reactivation;
735
+					} else {//$version_is_higher === 1
736
+						$req_type = EE_System::req_type_upgrade;
737
+					}
738
+					delete_option($activation_indicator_option_name);
739
+				} else {
740
+					//we've seen this version before and the activation indicate doesn't show it was just activated
741
+					if ($version_is_higher === -1) {
742
+						$req_type = EE_System::req_type_downgrade;
743
+					} elseif ($version_is_higher === 0) {
744
+						//we've seen this version before and it's not an activation. its normal request
745
+						$req_type = EE_System::req_type_normal;
746
+					} else {//$version_is_higher === 1
747
+						$req_type = EE_System::req_type_upgrade;
748
+					}
749
+				}
750
+			}
751
+		} else {
752
+			//brand new install
753
+			$req_type = EE_System::req_type_new_activation;
754
+			delete_option($activation_indicator_option_name);
755
+		}
756
+		return $req_type;
757
+	}
758
+
759
+
760
+
761
+	/**
762
+	 * Detects if the $version_to_upgrade_to is higher than the most recent version in
763
+	 * the $activation_history_for_addon
764
+	 *
765
+	 * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
766
+	 *                                             sometimes containing 'unknown-date'
767
+	 * @param string $version_to_upgrade_to        (current version)
768
+	 * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
769
+	 *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
770
+	 *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
771
+	 *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
772
+	 */
773
+	private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
774
+	{
775
+		//find the most recently-activated version
776
+		$most_recently_active_version =
777
+			EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
778
+		return version_compare($version_to_upgrade_to, $most_recently_active_version);
779
+	}
780
+
781
+
782
+
783
+	/**
784
+	 * Gets the most recently active version listed in the activation history,
785
+	 * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
786
+	 *
787
+	 * @param array $activation_history  (keys are versions, values are arrays of times activated,
788
+	 *                                   sometimes containing 'unknown-date'
789
+	 * @return string
790
+	 */
791
+	private static function _get_most_recently_active_version_from_activation_history($activation_history)
792
+	{
793
+		$most_recently_active_version_activation = '1970-01-01 00:00:00';
794
+		$most_recently_active_version            = '0.0.0.dev.000';
795
+		if (is_array($activation_history)) {
796
+			foreach ($activation_history as $version => $times_activated) {
797
+				//check there is a record of when this version was activated. Otherwise,
798
+				//mark it as unknown
799
+				if (! $times_activated) {
800
+					$times_activated = array('unknown-date');
801
+				}
802
+				if (is_string($times_activated)) {
803
+					$times_activated = array($times_activated);
804
+				}
805
+				foreach ($times_activated as $an_activation) {
806
+					if ($an_activation !== 'unknown-date'
807
+						&& $an_activation
808
+						   > $most_recently_active_version_activation) {
809
+						$most_recently_active_version            = $version;
810
+						$most_recently_active_version_activation = $an_activation === 'unknown-date'
811
+							? '1970-01-01 00:00:00'
812
+							: $an_activation;
813
+					}
814
+				}
815
+			}
816
+		}
817
+		return $most_recently_active_version;
818
+	}
819
+
820
+
821
+
822
+	/**
823
+	 * This redirects to the about EE page after activation
824
+	 *
825
+	 * @return void
826
+	 */
827
+	public function redirect_to_about_ee()
828
+	{
829
+		$notices = EE_Error::get_notices(false);
830
+		//if current user is an admin and it's not an ajax or rest request
831
+		if (
832
+			! isset($notices['errors'])
833
+			&& $this->request->isAdmin()
834
+			&& apply_filters(
835
+				'FHEE__EE_System__redirect_to_about_ee__do_redirect',
836
+				$this->capabilities->current_user_can('manage_options', 'espresso_about_default')
837
+			)
838
+		) {
839
+			$query_params = array('page' => 'espresso_about');
840
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
841
+				$query_params['new_activation'] = true;
842
+			}
843
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
844
+				$query_params['reactivation'] = true;
845
+			}
846
+			$url = add_query_arg($query_params, admin_url('admin.php'));
847
+			wp_safe_redirect($url);
848
+			exit();
849
+		}
850
+	}
851
+
852
+
853
+
854
+	/**
855
+	 * load_core_configuration
856
+	 * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
857
+	 * which runs during the WP 'plugins_loaded' action at priority 5
858
+	 *
859
+	 * @return void
860
+	 * @throws ReflectionException
861
+	 */
862
+	public function load_core_configuration()
863
+	{
864
+		do_action('AHEE__EE_System__load_core_configuration__begin', $this);
865
+		$this->loader->getShared('EE_Load_Textdomain');
866
+		//load textdomain
867
+		EE_Load_Textdomain::load_textdomain();
868
+		// load and setup EE_Config and EE_Network_Config
869
+		$config = $this->loader->getShared('EE_Config');
870
+		$this->loader->getShared('EE_Network_Config');
871
+		// setup autoloaders
872
+		// enable logging?
873
+		if ($config->admin->use_full_logging) {
874
+			$this->loader->getShared('EE_Log');
875
+		}
876
+		// check for activation errors
877
+		$activation_errors = get_option('ee_plugin_activation_errors', false);
878
+		if ($activation_errors) {
879
+			EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
880
+			update_option('ee_plugin_activation_errors', false);
881
+		}
882
+		// get model names
883
+		$this->_parse_model_names();
884
+		//load caf stuff a chance to play during the activation process too.
885
+		$this->_maybe_brew_regular();
886
+		do_action('AHEE__EE_System__load_core_configuration__complete', $this);
887
+	}
888
+
889
+
890
+
891
+	/**
892
+	 * cycles through all of the models/*.model.php files, and assembles an array of model names
893
+	 *
894
+	 * @return void
895
+	 * @throws ReflectionException
896
+	 */
897
+	private function _parse_model_names()
898
+	{
899
+		//get all the files in the EE_MODELS folder that end in .model.php
900
+		$models                 = glob(EE_MODELS . '*.model.php');
901
+		$model_names            = array();
902
+		$non_abstract_db_models = array();
903
+		foreach ($models as $model) {
904
+			// get model classname
905
+			$classname       = EEH_File::get_classname_from_filepath_with_standard_filename($model);
906
+			$short_name      = str_replace('EEM_', '', $classname);
907
+			$reflectionClass = new ReflectionClass($classname);
908
+			if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
909
+				$non_abstract_db_models[ $short_name ] = $classname;
910
+			}
911
+			$model_names[ $short_name ] = $classname;
912
+		}
913
+		$this->registry->models                 = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
914
+		$this->registry->non_abstract_db_models = apply_filters(
915
+			'FHEE__EE_System__parse_implemented_model_names',
916
+			$non_abstract_db_models
917
+		);
918
+	}
919
+
920
+
921
+	/**
922
+	 * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
923
+	 * that need to be setup before our EE_System launches.
924
+	 *
925
+	 * @return void
926
+	 * @throws DomainException
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidDataTypeException
929
+	 * @throws InvalidInterfaceException
930
+	 * @throws InvalidClassException
931
+	 * @throws InvalidFilePathException
932
+	 */
933
+	private function _maybe_brew_regular()
934
+	{
935
+		/** @var Domain $domain */
936
+		$domain = DomainFactory::getShared(
937
+			new FullyQualifiedName(
938
+				'EventEspresso\core\domain\Domain'
939
+			),
940
+			array(
941
+				new FilePath(EVENT_ESPRESSO_MAIN_FILE),
942
+				Version::fromString(espresso_version())
943
+			)
944
+		);
945
+		if ($domain->isCaffeinated()) {
946
+			require_once EE_CAFF_PATH . 'brewing_regular.php';
947
+		}
948
+	}
949
+
950
+
951
+
952
+	/**
953
+	 * register_shortcodes_modules_and_widgets
954
+	 * generate lists of shortcodes and modules, then verify paths and classes
955
+	 * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
956
+	 * which runs during the WP 'plugins_loaded' action at priority 7
957
+	 *
958
+	 * @access public
959
+	 * @return void
960
+	 * @throws Exception
961
+	 */
962
+	public function register_shortcodes_modules_and_widgets()
963
+	{
964
+		if ($this->request->isFrontend() || $this->request->isIframe()) {
965
+			try {
966
+				// load, register, and add shortcodes the new way
967
+				$this->loader->getShared(
968
+					'EventEspresso\core\services\shortcodes\ShortcodesManager',
969
+					array(
970
+						// and the old way, but we'll put it under control of the new system
971
+						EE_Config::getLegacyShortcodesManager(),
972
+					)
973
+				);
974
+			} catch (Exception $exception) {
975
+				new ExceptionStackTraceDisplay($exception);
976
+			}
977
+		}
978
+		do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
979
+		// check for addons using old hook point
980
+		if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
981
+			$this->_incompatible_addon_error();
982
+		}
983
+	}
984
+
985
+
986
+
987
+	/**
988
+	 * _incompatible_addon_error
989
+	 *
990
+	 * @access public
991
+	 * @return void
992
+	 */
993
+	private function _incompatible_addon_error()
994
+	{
995
+		// get array of classes hooking into here
996
+		$class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
997
+			'AHEE__EE_System__register_shortcodes_modules_and_addons'
998
+		);
999
+		if (! empty($class_names)) {
1000
+			$msg = __(
1001
+				'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1002
+				'event_espresso'
1003
+			);
1004
+			$msg .= '<ul>';
1005
+			foreach ($class_names as $class_name) {
1006
+				$msg .= '<li><b>Event Espresso - ' . str_replace(
1007
+						array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
1008
+						$class_name
1009
+					) . '</b></li>';
1010
+			}
1011
+			$msg .= '</ul>';
1012
+			$msg .= __(
1013
+				'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1014
+				'event_espresso'
1015
+			);
1016
+			// save list of incompatible addons to wp-options for later use
1017
+			add_option('ee_incompatible_addons', $class_names, '', 'no');
1018
+			if (is_admin()) {
1019
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1020
+			}
1021
+		}
1022
+	}
1023
+
1024
+
1025
+
1026
+	/**
1027
+	 * brew_espresso
1028
+	 * begins the process of setting hooks for initializing EE in the correct order
1029
+	 * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1030
+	 * which runs during the WP 'plugins_loaded' action at priority 9
1031
+	 *
1032
+	 * @return void
1033
+	 */
1034
+	public function brew_espresso()
1035
+	{
1036
+		do_action('AHEE__EE_System__brew_espresso__begin', $this);
1037
+		// load some final core systems
1038
+		add_action('init', array($this, 'set_hooks_for_core'), 1);
1039
+		add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1040
+		add_action('init', array($this, 'load_CPTs_and_session'), 5);
1041
+		add_action('init', array($this, 'load_controllers'), 7);
1042
+		add_action('init', array($this, 'core_loaded_and_ready'), 9);
1043
+		add_action('init', array($this, 'initialize'), 10);
1044
+		add_action('init', array($this, 'initialize_last'), 100);
1045
+		if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1046
+			// pew pew pew
1047
+			$this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1048
+			do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1049
+		}
1050
+		do_action('AHEE__EE_System__brew_espresso__complete', $this);
1051
+	}
1052
+
1053
+
1054
+
1055
+	/**
1056
+	 *    set_hooks_for_core
1057
+	 *
1058
+	 * @access public
1059
+	 * @return    void
1060
+	 * @throws EE_Error
1061
+	 */
1062
+	public function set_hooks_for_core()
1063
+	{
1064
+		$this->_deactivate_incompatible_addons();
1065
+		do_action('AHEE__EE_System__set_hooks_for_core');
1066
+		$this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1067
+		//caps need to be initialized on every request so that capability maps are set.
1068
+		//@see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1069
+		$this->registry->CAP->init_caps();
1070
+	}
1071
+
1072
+
1073
+
1074
+	/**
1075
+	 * Using the information gathered in EE_System::_incompatible_addon_error,
1076
+	 * deactivates any addons considered incompatible with the current version of EE
1077
+	 */
1078
+	private function _deactivate_incompatible_addons()
1079
+	{
1080
+		$incompatible_addons = get_option('ee_incompatible_addons', array());
1081
+		if (! empty($incompatible_addons)) {
1082
+			$active_plugins = get_option('active_plugins', array());
1083
+			foreach ($active_plugins as $active_plugin) {
1084
+				foreach ($incompatible_addons as $incompatible_addon) {
1085
+					if (strpos($active_plugin, $incompatible_addon) !== false) {
1086
+						unset($_GET['activate']);
1087
+						espresso_deactivate_plugin($active_plugin);
1088
+					}
1089
+				}
1090
+			}
1091
+		}
1092
+	}
1093
+
1094
+
1095
+
1096
+	/**
1097
+	 *    perform_activations_upgrades_and_migrations
1098
+	 *
1099
+	 * @access public
1100
+	 * @return    void
1101
+	 */
1102
+	public function perform_activations_upgrades_and_migrations()
1103
+	{
1104
+		do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1105
+	}
1106
+
1107
+
1108
+
1109
+	/**
1110
+	 *    load_CPTs_and_session
1111
+	 *
1112
+	 * @access public
1113
+	 * @return    void
1114
+	 */
1115
+	public function load_CPTs_and_session()
1116
+	{
1117
+		do_action('AHEE__EE_System__load_CPTs_and_session__start');
1118
+		// register Custom Post Types
1119
+		$this->loader->getShared('EE_Register_CPTs');
1120
+		do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1121
+	}
1122
+
1123
+
1124
+
1125
+	/**
1126
+	 * load_controllers
1127
+	 * this is the best place to load any additional controllers that needs access to EE core.
1128
+	 * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1129
+	 * time
1130
+	 *
1131
+	 * @access public
1132
+	 * @return void
1133
+	 */
1134
+	public function load_controllers()
1135
+	{
1136
+		do_action('AHEE__EE_System__load_controllers__start');
1137
+		// let's get it started
1138
+		if (
1139
+			! $this->maintenance_mode->level()
1140
+			&& ($this->request->isFrontend() || $this->request->isFrontAjax())
1141
+		) {
1142
+			do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1143
+			$this->loader->getShared('EE_Front_Controller');
1144
+		} elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1145
+			do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1146
+			$this->loader->getShared('EE_Admin');
1147
+		}
1148
+		do_action('AHEE__EE_System__load_controllers__complete');
1149
+	}
1150
+
1151
+
1152
+
1153
+	/**
1154
+	 * core_loaded_and_ready
1155
+	 * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1156
+	 *
1157
+	 * @access public
1158
+	 * @return void
1159
+	 */
1160
+	public function core_loaded_and_ready()
1161
+	{
1162
+		if (
1163
+			$this->request->isAdmin()
1164
+			|| $this->request->isEeAjax()
1165
+			|| $this->request->isFrontend()
1166
+		) {
1167
+			$this->loader->getShared('EE_Session');
1168
+		}
1169
+		do_action('AHEE__EE_System__core_loaded_and_ready');
1170
+		// load_espresso_template_tags
1171
+		if (
1172
+			is_readable(EE_PUBLIC . 'template_tags.php')
1173
+			&& ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isFeed())
1174
+		) {
1175
+			require_once EE_PUBLIC . 'template_tags.php';
1176
+		}
1177
+		do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1178
+		if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
1179
+			$this->loader->getShared('EventEspresso\core\services\assets\Registry');
1180
+		}
1181
+	}
1182
+
1183
+
1184
+
1185
+	/**
1186
+	 * initialize
1187
+	 * this is the best place to begin initializing client code
1188
+	 *
1189
+	 * @access public
1190
+	 * @return void
1191
+	 */
1192
+	public function initialize()
1193
+	{
1194
+		do_action('AHEE__EE_System__initialize');
1195
+	}
1196
+
1197
+
1198
+
1199
+	/**
1200
+	 * initialize_last
1201
+	 * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1202
+	 * initialize has done so
1203
+	 *
1204
+	 * @access public
1205
+	 * @return void
1206
+	 */
1207
+	public function initialize_last()
1208
+	{
1209
+		do_action('AHEE__EE_System__initialize_last');
1210
+		add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1211
+	}
1212
+
1213
+
1214
+
1215
+	/**
1216
+	 * @return void
1217
+	 * @throws EE_Error
1218
+	 */
1219
+	public function addEspressoToolbar()
1220
+	{
1221
+		$this->loader->getShared(
1222
+			'EventEspresso\core\domain\services\admin\AdminToolBar',
1223
+			array($this->registry->CAP)
1224
+		);
1225
+	}
1226
+
1227
+
1228
+
1229
+	/**
1230
+	 * do_not_cache
1231
+	 * sets no cache headers and defines no cache constants for WP plugins
1232
+	 *
1233
+	 * @access public
1234
+	 * @return void
1235
+	 */
1236
+	public static function do_not_cache()
1237
+	{
1238
+		// set no cache constants
1239
+		if (! defined('DONOTCACHEPAGE')) {
1240
+			define('DONOTCACHEPAGE', true);
1241
+		}
1242
+		if (! defined('DONOTCACHCEOBJECT')) {
1243
+			define('DONOTCACHCEOBJECT', true);
1244
+		}
1245
+		if (! defined('DONOTCACHEDB')) {
1246
+			define('DONOTCACHEDB', true);
1247
+		}
1248
+		// add no cache headers
1249
+		add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1250
+		// plus a little extra for nginx and Google Chrome
1251
+		add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1252
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1253
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1254
+	}
1255
+
1256
+
1257
+
1258
+	/**
1259
+	 *    extra_nocache_headers
1260
+	 *
1261
+	 * @access    public
1262
+	 * @param $headers
1263
+	 * @return    array
1264
+	 */
1265
+	public static function extra_nocache_headers($headers)
1266
+	{
1267
+		// for NGINX
1268
+		$headers['X-Accel-Expires'] = 0;
1269
+		// plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1270
+		$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1271
+		return $headers;
1272
+	}
1273
+
1274
+
1275
+
1276
+	/**
1277
+	 *    nocache_headers
1278
+	 *
1279
+	 * @access    public
1280
+	 * @return    void
1281
+	 */
1282
+	public static function nocache_headers()
1283
+	{
1284
+		nocache_headers();
1285
+	}
1286
+
1287
+
1288
+
1289
+	/**
1290
+	 * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1291
+	 * never returned with the function.
1292
+	 *
1293
+	 * @param  array $exclude_array any existing pages being excluded are in this array.
1294
+	 * @return array
1295
+	 */
1296
+	public function remove_pages_from_wp_list_pages($exclude_array)
1297
+	{
1298
+		return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1299
+	}
1300 1300
 
1301 1301
 
1302 1302
 
Please login to merge, or discard this patch.
core/admin/EE_Admin.core.php 1 patch
Indentation   +915 added lines, -915 removed lines patch added patch discarded remove patch
@@ -23,458 +23,458 @@  discard block
 block discarded – undo
23 23
 final class EE_Admin implements InterminableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Admin $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
33
-     */
34
-    private $persistent_admin_notice_manager;
35
-
36
-    /**
37
-     * @singleton method used to instantiate class object
38
-     * @return EE_Admin
39
-     * @throws EE_Error
40
-     */
41
-    public static function instance()
42
-    {
43
-        // check if class object is instantiated
44
-        if (! self::$_instance instanceof EE_Admin) {
45
-            self::$_instance = new self();
46
-        }
47
-        return self::$_instance;
48
-    }
49
-
50
-
51
-    /**
52
-     * @return EE_Admin
53
-     * @throws EE_Error
54
-     */
55
-    public static function reset()
56
-    {
57
-        self::$_instance = null;
58
-        return self::instance();
59
-    }
60
-
61
-
62
-    /**
63
-     * class constructor
64
-     *
65
-     * @throws EE_Error
66
-     * @throws InvalidDataTypeException
67
-     * @throws InvalidInterfaceException
68
-     * @throws InvalidArgumentException
69
-     */
70
-    protected function __construct()
71
-    {
72
-        // define global EE_Admin constants
73
-        $this->_define_all_constants();
74
-        // set autoloaders for our admin page classes based on included path information
75
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
76
-        // admin hooks
77
-        add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
78
-        // load EE_Request_Handler early
79
-        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
80
-        add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
81
-        add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
82
-        add_action('wp_loaded', array($this, 'wp_loaded'), 100);
83
-        add_action('admin_init', array($this, 'admin_init'), 100);
84
-        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
85
-        add_action('admin_notices', array($this, 'display_admin_notices'), 10);
86
-        add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
87
-        add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
88
-        add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
89
-        add_action('load-plugins.php', array($this, 'hookIntoWpPluginsPage'));
90
-        //reset Environment config (we only do this on admin page loads);
91
-        EE_Registry::instance()->CFG->environment->recheck_values();
92
-        do_action('AHEE__EE_Admin__loaded');
93
-    }
94
-
95
-
96
-
97
-    /**
98
-     * _define_all_constants
99
-     * define constants that are set globally for all admin pages
100
-     *
101
-     * @return void
102
-     */
103
-    private function _define_all_constants()
104
-    {
105
-        if (! defined('EE_ADMIN_URL')) {
106
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
107
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
108
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
109
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
110
-            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
111
-        }
112
-    }
113
-
114
-
115
-    /**
116
-     * filter_plugin_actions - adds links to the Plugins page listing
117
-     *
118
-     * @param    array  $links
119
-     * @param    string $plugin
120
-     * @return    array
121
-     */
122
-    public function filter_plugin_actions($links, $plugin)
123
-    {
124
-        // set $main_file in stone
125
-        static $main_file;
126
-        // if $main_file is not set yet
127
-        if (! $main_file) {
128
-            $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
129
-        }
130
-        if ($plugin === $main_file) {
131
-            // compare current plugin to this one
132
-            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
133
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
134
-                                    . ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
135
-                                    . esc_html__('Maintenance Mode Active', 'event_espresso')
136
-                                    . '</a>';
137
-                array_unshift($links, $maintenance_link);
138
-            } else {
139
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
140
-                                     . esc_html__('Settings', 'event_espresso')
141
-                                     . '</a>';
142
-                $events_link       = '<a href="admin.php?page=espresso_events">'
143
-                                     . esc_html__('Events', 'event_espresso')
144
-                                     . '</a>';
145
-                // add before other links
146
-                array_unshift($links, $org_settings_link, $events_link);
147
-            }
148
-        }
149
-        return $links;
150
-    }
151
-
152
-
153
-    /**
154
-     * _get_request
155
-     *
156
-     * @return void
157
-     * @throws EE_Error
158
-     * @throws InvalidArgumentException
159
-     * @throws InvalidDataTypeException
160
-     * @throws InvalidInterfaceException
161
-     * @throws ReflectionException
162
-     */
163
-    public function get_request()
164
-    {
165
-        EE_Registry::instance()->load_core('Request_Handler');
166
-        EE_Registry::instance()->load_core('CPT_Strategy');
167
-    }
168
-
169
-
170
-
171
-    /**
172
-     * hide_admin_pages_except_maintenance_mode
173
-     *
174
-     * @param array $admin_page_folder_names
175
-     * @return array
176
-     */
177
-    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
178
-    {
179
-        return array(
180
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
181
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
182
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
183
-        );
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
190
-     * EE_Front_Controller's init phases have run
191
-     *
192
-     * @return void
193
-     * @throws EE_Error
194
-     * @throws InvalidArgumentException
195
-     * @throws InvalidDataTypeException
196
-     * @throws InvalidInterfaceException
197
-     * @throws ReflectionException
198
-     * @throws ServiceNotFoundException
199
-     */
200
-    public function init()
201
-    {
202
-        //only enable most of the EE_Admin IF we're not in full maintenance mode
203
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
204
-            //ok so we want to enable the entire admin
205
-            $this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
206
-                'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
207
-            );
208
-            $this->persistent_admin_notice_manager->setReturnUrl(
209
-                EE_Admin_Page::add_query_args_and_nonce(
210
-                    array(
211
-                        'page'   => EE_Registry::instance()->REQ->get('page', ''),
212
-                        'action' => EE_Registry::instance()->REQ->get('action', ''),
213
-                    ),
214
-                    EE_ADMIN_URL
215
-                )
216
-            );
217
-            $this->maybeSetDatetimeWarningNotice();
218
-            //at a glance dashboard widget
219
-            add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
220
-            //filter for get_edit_post_link used on comments for custom post types
221
-            add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
222
-        }
223
-        // run the admin page factory but ONLY if we are doing an ee admin ajax request
224
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
225
-            try {
226
-                //this loads the controller for the admin pages which will setup routing etc
227
-                EE_Registry::instance()->load_core('Admin_Page_Loader');
228
-            } catch (EE_Error $e) {
229
-                $e->get_error();
230
-            }
231
-        }
232
-        add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
233
-        //make sure our CPTs and custom taxonomy metaboxes get shown for first time users
234
-        add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
235
-        add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
236
-        //exclude EE critical pages from all nav menus and wp_list_pages
237
-        add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
238
-    }
239
-
240
-
241
-    /**
242
-     *    get_persistent_admin_notices
243
-     *
244
-     * @access    public
245
-     * @return void
246
-     * @throws EE_Error
247
-     * @throws InvalidArgumentException
248
-     * @throws InvalidDataTypeException
249
-     * @throws InvalidInterfaceException
250
-     */
251
-    public function maybeSetDatetimeWarningNotice()
252
-    {
253
-        //add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
254
-        //@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
255
-        //with this.  But after enough time (indeterminate at this point) we can just remove this notice.
256
-        //this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
257
-        if (apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
258
-            && ! get_option('timezone_string')
259
-            && EEM_Event::instance()->count() > 0
260
-        ) {
261
-            new PersistentAdminNotice(
262
-                'datetime_fix_notice',
263
-                sprintf(
264
-                    esc_html__(
265
-                        '%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
266
-                        'event_espresso'
267
-                    ),
268
-                    '<strong>',
269
-                    '</strong>',
270
-                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
271
-                    '</a>',
272
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
273
-                        array(
274
-                            'page' => 'espresso_maintenance_settings',
275
-                            'action' => 'datetime_tools'
276
-                        ),
277
-                        admin_url('admin.php')
278
-                    ) . '">'
279
-                ),
280
-                false,
281
-                'manage_options',
282
-                'datetime_fix_persistent_notice'
283
-            );
284
-        }
285
-    }
286
-
287
-
288
-
289
-    /**
290
-     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
291
-     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
292
-     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
293
-     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
294
-     * normal property on the post_type object.  It's found ONLY in this particular context.
295
-     *
296
-     * @param WP_Post $post_type WP post type object
297
-     * @return WP_Post
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     */
302
-    public function remove_pages_from_nav_menu($post_type)
303
-    {
304
-        //if this isn't the "pages" post type let's get out
305
-        if ($post_type->name !== 'page') {
306
-            return $post_type;
307
-        }
308
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
309
-        $post_type->_default_query = array(
310
-            'post__not_in' => $critical_pages,
311
-        );
312
-        return $post_type;
313
-    }
314
-
315
-
316
-
317
-    /**
318
-     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
319
-     * metaboxes get shown as well
320
-     *
321
-     * @return void
322
-     */
323
-    public function enable_hidden_ee_nav_menu_metaboxes()
324
-    {
325
-        global $wp_meta_boxes, $pagenow;
326
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
327
-            return;
328
-        }
329
-        $user = wp_get_current_user();
330
-        //has this been done yet?
331
-        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
332
-            return;
333
-        }
334
-
335
-        $hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
336
-        $initial_meta_boxes = apply_filters(
337
-            'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
338
-            array(
339
-                'nav-menu-theme-locations',
340
-                'add-page',
341
-                'add-custom-links',
342
-                'add-category',
343
-                'add-espresso_events',
344
-                'add-espresso_venues',
345
-                'add-espresso_event_categories',
346
-                'add-espresso_venue_categories',
347
-                'add-post-type-post',
348
-                'add-post-type-page',
349
-            )
350
-        );
351
-
352
-        if (is_array($hidden_meta_boxes)) {
353
-            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
354
-                if (in_array($meta_box_id, $initial_meta_boxes, true)) {
355
-                    unset($hidden_meta_boxes[$key]);
356
-                }
357
-            }
358
-        }
359
-        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
360
-        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * This method simply registers custom nav menu boxes for "nav_menus.php route"
367
-     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
368
-     *
369
-     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
370
-     *         addons etc.
371
-     * @return void
372
-     */
373
-    public function register_custom_nav_menu_boxes()
374
-    {
375
-        add_meta_box(
376
-            'add-extra-nav-menu-pages',
377
-            esc_html__('Event Espresso Pages', 'event_espresso'),
378
-            array($this, 'ee_cpt_archive_pages'),
379
-            'nav-menus',
380
-            'side',
381
-            'core'
382
-        );
383
-    }
384
-
385
-
386
-
387
-    /**
388
-     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
389
-     *
390
-     * @since   4.3.0
391
-     * @param string $link the original link generated by wp
392
-     * @param int    $id   post id
393
-     * @return string  the (maybe) modified link
394
-     */
395
-    public function modify_edit_post_link($link, $id)
396
-    {
397
-        if (! $post = get_post($id)) {
398
-            return $link;
399
-        }
400
-        if ($post->post_type === 'espresso_attendees') {
401
-            $query_args = array(
402
-                'action' => 'edit_attendee',
403
-                'post'   => $id,
404
-            );
405
-            return EEH_URL::add_query_args_and_nonce(
406
-                $query_args,
407
-                admin_url('admin.php?page=espresso_registrations')
408
-            );
409
-        }
410
-        return $link;
411
-    }
412
-
413
-
414
-
415
-    public function ee_cpt_archive_pages()
416
-    {
417
-        global $nav_menu_selected_id;
418
-        $db_fields   = false;
419
-        $walker      = new Walker_Nav_Menu_Checklist($db_fields);
420
-        $current_tab = 'event-archives';
421
-        $removed_args = array(
422
-            'action',
423
-            'customlink-tab',
424
-            'edit-menu-item',
425
-            'menu-item',
426
-            'page-tab',
427
-            '_wpnonce',
428
-        );
429
-        ?>
26
+	/**
27
+	 * @var EE_Admin $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
33
+	 */
34
+	private $persistent_admin_notice_manager;
35
+
36
+	/**
37
+	 * @singleton method used to instantiate class object
38
+	 * @return EE_Admin
39
+	 * @throws EE_Error
40
+	 */
41
+	public static function instance()
42
+	{
43
+		// check if class object is instantiated
44
+		if (! self::$_instance instanceof EE_Admin) {
45
+			self::$_instance = new self();
46
+		}
47
+		return self::$_instance;
48
+	}
49
+
50
+
51
+	/**
52
+	 * @return EE_Admin
53
+	 * @throws EE_Error
54
+	 */
55
+	public static function reset()
56
+	{
57
+		self::$_instance = null;
58
+		return self::instance();
59
+	}
60
+
61
+
62
+	/**
63
+	 * class constructor
64
+	 *
65
+	 * @throws EE_Error
66
+	 * @throws InvalidDataTypeException
67
+	 * @throws InvalidInterfaceException
68
+	 * @throws InvalidArgumentException
69
+	 */
70
+	protected function __construct()
71
+	{
72
+		// define global EE_Admin constants
73
+		$this->_define_all_constants();
74
+		// set autoloaders for our admin page classes based on included path information
75
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
76
+		// admin hooks
77
+		add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
78
+		// load EE_Request_Handler early
79
+		add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
80
+		add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
81
+		add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
82
+		add_action('wp_loaded', array($this, 'wp_loaded'), 100);
83
+		add_action('admin_init', array($this, 'admin_init'), 100);
84
+		add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
85
+		add_action('admin_notices', array($this, 'display_admin_notices'), 10);
86
+		add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
87
+		add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
88
+		add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
89
+		add_action('load-plugins.php', array($this, 'hookIntoWpPluginsPage'));
90
+		//reset Environment config (we only do this on admin page loads);
91
+		EE_Registry::instance()->CFG->environment->recheck_values();
92
+		do_action('AHEE__EE_Admin__loaded');
93
+	}
94
+
95
+
96
+
97
+	/**
98
+	 * _define_all_constants
99
+	 * define constants that are set globally for all admin pages
100
+	 *
101
+	 * @return void
102
+	 */
103
+	private function _define_all_constants()
104
+	{
105
+		if (! defined('EE_ADMIN_URL')) {
106
+			define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
107
+			define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
108
+			define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
109
+			define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
110
+			define('WP_AJAX_URL', admin_url('admin-ajax.php'));
111
+		}
112
+	}
113
+
114
+
115
+	/**
116
+	 * filter_plugin_actions - adds links to the Plugins page listing
117
+	 *
118
+	 * @param    array  $links
119
+	 * @param    string $plugin
120
+	 * @return    array
121
+	 */
122
+	public function filter_plugin_actions($links, $plugin)
123
+	{
124
+		// set $main_file in stone
125
+		static $main_file;
126
+		// if $main_file is not set yet
127
+		if (! $main_file) {
128
+			$main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
129
+		}
130
+		if ($plugin === $main_file) {
131
+			// compare current plugin to this one
132
+			if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
133
+				$maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
134
+									. ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
135
+									. esc_html__('Maintenance Mode Active', 'event_espresso')
136
+									. '</a>';
137
+				array_unshift($links, $maintenance_link);
138
+			} else {
139
+				$org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
140
+									 . esc_html__('Settings', 'event_espresso')
141
+									 . '</a>';
142
+				$events_link       = '<a href="admin.php?page=espresso_events">'
143
+									 . esc_html__('Events', 'event_espresso')
144
+									 . '</a>';
145
+				// add before other links
146
+				array_unshift($links, $org_settings_link, $events_link);
147
+			}
148
+		}
149
+		return $links;
150
+	}
151
+
152
+
153
+	/**
154
+	 * _get_request
155
+	 *
156
+	 * @return void
157
+	 * @throws EE_Error
158
+	 * @throws InvalidArgumentException
159
+	 * @throws InvalidDataTypeException
160
+	 * @throws InvalidInterfaceException
161
+	 * @throws ReflectionException
162
+	 */
163
+	public function get_request()
164
+	{
165
+		EE_Registry::instance()->load_core('Request_Handler');
166
+		EE_Registry::instance()->load_core('CPT_Strategy');
167
+	}
168
+
169
+
170
+
171
+	/**
172
+	 * hide_admin_pages_except_maintenance_mode
173
+	 *
174
+	 * @param array $admin_page_folder_names
175
+	 * @return array
176
+	 */
177
+	public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
178
+	{
179
+		return array(
180
+			'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
181
+			'about'       => EE_ADMIN_PAGES . 'about' . DS,
182
+			'support'     => EE_ADMIN_PAGES . 'support' . DS,
183
+		);
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
190
+	 * EE_Front_Controller's init phases have run
191
+	 *
192
+	 * @return void
193
+	 * @throws EE_Error
194
+	 * @throws InvalidArgumentException
195
+	 * @throws InvalidDataTypeException
196
+	 * @throws InvalidInterfaceException
197
+	 * @throws ReflectionException
198
+	 * @throws ServiceNotFoundException
199
+	 */
200
+	public function init()
201
+	{
202
+		//only enable most of the EE_Admin IF we're not in full maintenance mode
203
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
204
+			//ok so we want to enable the entire admin
205
+			$this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
206
+				'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
207
+			);
208
+			$this->persistent_admin_notice_manager->setReturnUrl(
209
+				EE_Admin_Page::add_query_args_and_nonce(
210
+					array(
211
+						'page'   => EE_Registry::instance()->REQ->get('page', ''),
212
+						'action' => EE_Registry::instance()->REQ->get('action', ''),
213
+					),
214
+					EE_ADMIN_URL
215
+				)
216
+			);
217
+			$this->maybeSetDatetimeWarningNotice();
218
+			//at a glance dashboard widget
219
+			add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
220
+			//filter for get_edit_post_link used on comments for custom post types
221
+			add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
222
+		}
223
+		// run the admin page factory but ONLY if we are doing an ee admin ajax request
224
+		if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
225
+			try {
226
+				//this loads the controller for the admin pages which will setup routing etc
227
+				EE_Registry::instance()->load_core('Admin_Page_Loader');
228
+			} catch (EE_Error $e) {
229
+				$e->get_error();
230
+			}
231
+		}
232
+		add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
233
+		//make sure our CPTs and custom taxonomy metaboxes get shown for first time users
234
+		add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
235
+		add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
236
+		//exclude EE critical pages from all nav menus and wp_list_pages
237
+		add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
238
+	}
239
+
240
+
241
+	/**
242
+	 *    get_persistent_admin_notices
243
+	 *
244
+	 * @access    public
245
+	 * @return void
246
+	 * @throws EE_Error
247
+	 * @throws InvalidArgumentException
248
+	 * @throws InvalidDataTypeException
249
+	 * @throws InvalidInterfaceException
250
+	 */
251
+	public function maybeSetDatetimeWarningNotice()
252
+	{
253
+		//add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
254
+		//@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
255
+		//with this.  But after enough time (indeterminate at this point) we can just remove this notice.
256
+		//this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
257
+		if (apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
258
+			&& ! get_option('timezone_string')
259
+			&& EEM_Event::instance()->count() > 0
260
+		) {
261
+			new PersistentAdminNotice(
262
+				'datetime_fix_notice',
263
+				sprintf(
264
+					esc_html__(
265
+						'%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
266
+						'event_espresso'
267
+					),
268
+					'<strong>',
269
+					'</strong>',
270
+					'<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
271
+					'</a>',
272
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
273
+						array(
274
+							'page' => 'espresso_maintenance_settings',
275
+							'action' => 'datetime_tools'
276
+						),
277
+						admin_url('admin.php')
278
+					) . '">'
279
+				),
280
+				false,
281
+				'manage_options',
282
+				'datetime_fix_persistent_notice'
283
+			);
284
+		}
285
+	}
286
+
287
+
288
+
289
+	/**
290
+	 * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
291
+	 * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
292
+	 * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
293
+	 * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
294
+	 * normal property on the post_type object.  It's found ONLY in this particular context.
295
+	 *
296
+	 * @param WP_Post $post_type WP post type object
297
+	 * @return WP_Post
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 */
302
+	public function remove_pages_from_nav_menu($post_type)
303
+	{
304
+		//if this isn't the "pages" post type let's get out
305
+		if ($post_type->name !== 'page') {
306
+			return $post_type;
307
+		}
308
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
309
+		$post_type->_default_query = array(
310
+			'post__not_in' => $critical_pages,
311
+		);
312
+		return $post_type;
313
+	}
314
+
315
+
316
+
317
+	/**
318
+	 * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
319
+	 * metaboxes get shown as well
320
+	 *
321
+	 * @return void
322
+	 */
323
+	public function enable_hidden_ee_nav_menu_metaboxes()
324
+	{
325
+		global $wp_meta_boxes, $pagenow;
326
+		if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
327
+			return;
328
+		}
329
+		$user = wp_get_current_user();
330
+		//has this been done yet?
331
+		if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
332
+			return;
333
+		}
334
+
335
+		$hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
336
+		$initial_meta_boxes = apply_filters(
337
+			'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
338
+			array(
339
+				'nav-menu-theme-locations',
340
+				'add-page',
341
+				'add-custom-links',
342
+				'add-category',
343
+				'add-espresso_events',
344
+				'add-espresso_venues',
345
+				'add-espresso_event_categories',
346
+				'add-espresso_venue_categories',
347
+				'add-post-type-post',
348
+				'add-post-type-page',
349
+			)
350
+		);
351
+
352
+		if (is_array($hidden_meta_boxes)) {
353
+			foreach ($hidden_meta_boxes as $key => $meta_box_id) {
354
+				if (in_array($meta_box_id, $initial_meta_boxes, true)) {
355
+					unset($hidden_meta_boxes[$key]);
356
+				}
357
+			}
358
+		}
359
+		update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
360
+		update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * This method simply registers custom nav menu boxes for "nav_menus.php route"
367
+	 * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
368
+	 *
369
+	 * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
370
+	 *         addons etc.
371
+	 * @return void
372
+	 */
373
+	public function register_custom_nav_menu_boxes()
374
+	{
375
+		add_meta_box(
376
+			'add-extra-nav-menu-pages',
377
+			esc_html__('Event Espresso Pages', 'event_espresso'),
378
+			array($this, 'ee_cpt_archive_pages'),
379
+			'nav-menus',
380
+			'side',
381
+			'core'
382
+		);
383
+	}
384
+
385
+
386
+
387
+	/**
388
+	 * Use this to edit the post link for our cpts so that the edit link points to the correct page.
389
+	 *
390
+	 * @since   4.3.0
391
+	 * @param string $link the original link generated by wp
392
+	 * @param int    $id   post id
393
+	 * @return string  the (maybe) modified link
394
+	 */
395
+	public function modify_edit_post_link($link, $id)
396
+	{
397
+		if (! $post = get_post($id)) {
398
+			return $link;
399
+		}
400
+		if ($post->post_type === 'espresso_attendees') {
401
+			$query_args = array(
402
+				'action' => 'edit_attendee',
403
+				'post'   => $id,
404
+			);
405
+			return EEH_URL::add_query_args_and_nonce(
406
+				$query_args,
407
+				admin_url('admin.php?page=espresso_registrations')
408
+			);
409
+		}
410
+		return $link;
411
+	}
412
+
413
+
414
+
415
+	public function ee_cpt_archive_pages()
416
+	{
417
+		global $nav_menu_selected_id;
418
+		$db_fields   = false;
419
+		$walker      = new Walker_Nav_Menu_Checklist($db_fields);
420
+		$current_tab = 'event-archives';
421
+		$removed_args = array(
422
+			'action',
423
+			'customlink-tab',
424
+			'edit-menu-item',
425
+			'menu-item',
426
+			'page-tab',
427
+			'_wpnonce',
428
+		);
429
+		?>
430 430
         <div id="posttype-extra-nav-menu-pages" class="posttypediv">
431 431
             <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs">
432 432
                 <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>>
433 433
                     <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives"
434 434
                        href="<?php if ($nav_menu_selected_id) {
435
-                            echo esc_url(
436
-                                add_query_arg(
437
-                                    'extra-nav-menu-pages-tab',
438
-                                    'event-archives',
439
-                                    remove_query_arg($removed_args)
440
-                                )
441
-                            );
442
-                       } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
435
+							echo esc_url(
436
+								add_query_arg(
437
+									'extra-nav-menu-pages-tab',
438
+									'event-archives',
439
+									remove_query_arg($removed_args)
440
+								)
441
+							);
442
+					   } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
443 443
                         <?php _e('Event Archive Pages', 'event_espresso'); ?>
444 444
                     </a>
445 445
                 </li>
446 446
             </ul><!-- .posttype-tabs -->
447 447
 
448 448
             <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php
449
-                echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
450
-                ?>">
449
+				echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
450
+				?>">
451 451
                     <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear">
452 452
                         <?php
453
-                        $pages          = $this->_get_extra_nav_menu_pages_items();
454
-                        $args['walker'] = $walker;
455
-                        echo walk_nav_menu_tree(
456
-                            array_map(
457
-                                array($this, '_setup_extra_nav_menu_pages_items'),
458
-                                $pages
459
-                            ),
460
-                            0,
461
-                            (object) $args
462
-                        );
463
-                        ?>
453
+						$pages          = $this->_get_extra_nav_menu_pages_items();
454
+						$args['walker'] = $walker;
455
+						echo walk_nav_menu_tree(
456
+							array_map(
457
+								array($this, '_setup_extra_nav_menu_pages_items'),
458
+								$pages
459
+							),
460
+							0,
461
+							(object) $args
462
+						);
463
+						?>
464 464
                     </ul>
465 465
                 </div><!-- /.tabs-panel -->
466 466
 
467 467
                 <p class="button-controls">
468 468
                 <span class="list-controls">
469 469
                     <a href="<?php
470
-                    echo esc_url(add_query_arg(
471
-                        array(
472
-                            'extra-nav-menu-pages-tab' => 'event-archives',
473
-                            'selectall'                => 1,
474
-                        ),
475
-                        remove_query_arg($removed_args)
476
-                    ));
477
-                    ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
470
+					echo esc_url(add_query_arg(
471
+						array(
472
+							'extra-nav-menu-pages-tab' => 'event-archives',
473
+							'selectall'                => 1,
474
+						),
475
+						remove_query_arg($removed_args)
476
+					));
477
+					?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
478 478
                 </span>
479 479
                 <span class="add-to-menu">
480 480
                     <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?>
@@ -487,486 +487,486 @@  discard block
 block discarded – undo
487 487
 
488 488
         </div><!-- /.posttypediv -->
489 489
         <?php
490
-    }
491
-
492
-
493
-    /**
494
-     * Returns an array of event archive nav items.
495
-     *
496
-     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
497
-     *        method we use for getting the extra nav menu items
498
-     * @return array
499
-     */
500
-    private function _get_extra_nav_menu_pages_items()
501
-    {
502
-        $menuitems[] = array(
503
-            'title'       => esc_html__('Event List', 'event_espresso'),
504
-            'url'         => get_post_type_archive_link('espresso_events'),
505
-            'description' => esc_html__('Archive page for all events.', 'event_espresso'),
506
-        );
507
-        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
508
-    }
509
-
510
-
511
-    /**
512
-     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
513
-     * the properties and converts it to the menu item object.
514
-     *
515
-     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
516
-     * @param $menu_item_values
517
-     * @return stdClass
518
-     */
519
-    private function _setup_extra_nav_menu_pages_items($menu_item_values)
520
-    {
521
-        $menu_item = new stdClass();
522
-        $keys      = array(
523
-            'ID'               => 0,
524
-            'db_id'            => 0,
525
-            'menu_item_parent' => 0,
526
-            'object_id'        => -1,
527
-            'post_parent'      => 0,
528
-            'type'             => 'custom',
529
-            'object'           => '',
530
-            'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
531
-            'title'            => '',
532
-            'url'              => '',
533
-            'target'           => '',
534
-            'attr_title'       => '',
535
-            'description'      => '',
536
-            'classes'          => array(),
537
-            'xfn'              => '',
538
-        );
539
-
540
-        foreach ($keys as $key => $value) {
541
-            $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
542
-        }
543
-        return $menu_item;
544
-    }
545
-
546
-
547
-    /**
548
-     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
549
-     * EE_Admin_Page route is called.
550
-     *
551
-     * @return void
552
-     */
553
-    public function route_admin_request()
554
-    {
555
-    }
556
-
557
-
558
-    /**
559
-     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
560
-     *
561
-     * @return void
562
-     */
563
-    public function wp_loaded()
564
-    {
565
-    }
566
-
567
-
568
-    /**
569
-     * admin_init
570
-     *
571
-     * @return void
572
-     * @throws EE_Error
573
-     * @throws InvalidArgumentException
574
-     * @throws InvalidDataTypeException
575
-     * @throws InvalidInterfaceException
576
-     * @throws ReflectionException
577
-     */
578
-    public function admin_init()
579
-    {
580
-
581
-        /**
582
-         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
583
-         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
584
-         * - check if doing post processing.
585
-         * - check if doing post processing of one of EE CPTs
586
-         * - instantiate the corresponding EE CPT model for the post_type being processed.
587
-         */
588
-        if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
589
-            EE_Registry::instance()->load_core('Register_CPTs');
590
-            EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
591
-        }
592
-
593
-
594
-        /**
595
-         * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
596
-         * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
597
-         * Pages" tab in the EE General Settings Admin page.
598
-         * This is for user-proofing.
599
-         */
600
-        add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
601
-    }
602
-
603
-
604
-    /**
605
-     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
606
-     *
607
-     * @param string $output Current output.
608
-     * @return string
609
-     * @throws InvalidArgumentException
610
-     * @throws InvalidDataTypeException
611
-     * @throws InvalidInterfaceException
612
-     */
613
-    public function modify_dropdown_pages($output)
614
-    {
615
-        //get critical pages
616
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
617
-
618
-        //split current output by line break for easier parsing.
619
-        $split_output = explode("\n", $output);
620
-
621
-        //loop through to remove any critical pages from the array.
622
-        foreach ($critical_pages as $page_id) {
623
-            $needle = 'value="' . $page_id . '"';
624
-            foreach ($split_output as $key => $haystack) {
625
-                if (strpos($haystack, $needle) !== false) {
626
-                    unset($split_output[$key]);
627
-                }
628
-            }
629
-        }
630
-        //replace output with the new contents
631
-        return implode("\n", $split_output);
632
-    }
633
-
634
-
635
-    /**
636
-     * enqueue all admin scripts that need loaded for admin pages
637
-     *
638
-     * @return void
639
-     */
640
-    public function enqueue_admin_scripts()
641
-    {
642
-        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
643
-        // Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
644
-        // calls.
645
-        wp_enqueue_script(
646
-            'ee-inject-wp',
647
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
648
-            array('jquery'),
649
-            EVENT_ESPRESSO_VERSION,
650
-            true
651
-        );
652
-        // register cookie script for future dependencies
653
-        wp_register_script(
654
-            'jquery-cookie',
655
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
656
-            array('jquery'),
657
-            '2.1',
658
-            true
659
-        );
660
-        //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
661
-        // via: add_filter('FHEE_load_joyride', '__return_true' );
662
-        if (apply_filters('FHEE_load_joyride', false)) {
663
-            //joyride style
664
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
665
-            wp_register_style(
666
-                'ee-joyride-css',
667
-                EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
668
-                array('joyride-css'),
669
-                EVENT_ESPRESSO_VERSION
670
-            );
671
-            wp_register_script(
672
-                'joyride-modernizr',
673
-                EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
674
-                array(),
675
-                '2.1',
676
-                true
677
-            );
678
-            //joyride JS
679
-            wp_register_script(
680
-                'jquery-joyride',
681
-                EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
682
-                array('jquery-cookie', 'joyride-modernizr'),
683
-                '2.1',
684
-                true
685
-            );
686
-            // wanna go for a joyride?
687
-            wp_enqueue_style('ee-joyride-css');
688
-            wp_enqueue_script('jquery-joyride');
689
-        }
690
-    }
691
-
692
-
693
-    /**
694
-     * display_admin_notices
695
-     *
696
-     * @return void
697
-     */
698
-    public function display_admin_notices()
699
-    {
700
-        echo EE_Error::get_notices();
701
-    }
702
-
703
-
704
-
705
-    /**
706
-     * @param array $elements
707
-     * @return array
708
-     * @throws EE_Error
709
-     * @throws InvalidArgumentException
710
-     * @throws InvalidDataTypeException
711
-     * @throws InvalidInterfaceException
712
-     */
713
-    public function dashboard_glance_items($elements)
714
-    {
715
-        $elements                        = is_array($elements) ? $elements : array($elements);
716
-        $events                          = EEM_Event::instance()->count();
717
-        $items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
718
-            array('page' => 'espresso_events'),
719
-            admin_url('admin.php')
720
-        );
721
-        $items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
722
-        $items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
723
-        $registrations                   = EEM_Registration::instance()->count(
724
-            array(
725
-                array(
726
-                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
727
-                ),
728
-            )
729
-        );
730
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
731
-            array('page' => 'espresso_registrations'),
732
-            admin_url('admin.php')
733
-        );
734
-        $items['registrations']['text']  = sprintf(
735
-            _n('%s Registration', '%s Registrations', $registrations),
736
-            number_format_i18n($registrations)
737
-        );
738
-        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
739
-
740
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
741
-
742
-        foreach ($items as $type => $item_properties) {
743
-            $elements[] = sprintf(
744
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
745
-                $item_properties['url'],
746
-                $item_properties['title'],
747
-                $item_properties['text']
748
-            );
749
-        }
750
-        return $elements;
751
-    }
752
-
753
-
754
-    /**
755
-     * check_for_invalid_datetime_formats
756
-     * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
757
-     * their selected format can be parsed by PHP
758
-     *
759
-     * @param    $value
760
-     * @param    $option
761
-     * @throws EE_Error
762
-     * @return    string
763
-     */
764
-    public function check_for_invalid_datetime_formats($value, $option)
765
-    {
766
-        // check for date_format or time_format
767
-        switch ($option) {
768
-            case 'date_format':
769
-                $date_time_format = $value . ' ' . get_option('time_format');
770
-                break;
771
-            case 'time_format':
772
-                $date_time_format = get_option('date_format') . ' ' . $value;
773
-                break;
774
-            default:
775
-                $date_time_format = false;
776
-        }
777
-        // do we have a date_time format to check ?
778
-        if ($date_time_format) {
779
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
780
-
781
-            if (is_array($error_msg)) {
782
-                $msg = '<p>'
783
-                       . sprintf(
784
-                           esc_html__(
785
-                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
786
-                               'event_espresso'
787
-                           ),
788
-                           date($date_time_format),
789
-                           $date_time_format
790
-                       )
791
-                       . '</p><p><ul>';
792
-
793
-
794
-                foreach ($error_msg as $error) {
795
-                    $msg .= '<li>' . $error . '</li>';
796
-                }
797
-
798
-                $msg .= '</ul></p><p>'
799
-                        . sprintf(
800
-                            esc_html__(
801
-                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
802
-                                'event_espresso'
803
-                            ),
804
-                            '<span style="color:#D54E21;">',
805
-                            '</span>'
806
-                        )
807
-                        . '</p>';
808
-
809
-                // trigger WP settings error
810
-                add_settings_error(
811
-                    'date_format',
812
-                    'date_format',
813
-                    $msg
814
-                );
815
-
816
-                // set format to something valid
817
-                switch ($option) {
818
-                    case 'date_format':
819
-                        $value = 'F j, Y';
820
-                        break;
821
-                    case 'time_format':
822
-                        $value = 'g:i a';
823
-                        break;
824
-                }
825
-            }
826
-        }
827
-        return $value;
828
-    }
829
-
830
-
831
-    /**
832
-     * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
833
-     *
834
-     * @param $content
835
-     * @return    string
836
-     */
837
-    public function its_eSpresso($content)
838
-    {
839
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
840
-    }
841
-
842
-
843
-    /**
844
-     * espresso_admin_footer
845
-     *
846
-     * @return    string
847
-     */
848
-    public function espresso_admin_footer()
849
-    {
850
-        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
851
-    }
852
-
853
-
854
-    /**
855
-     * static method for registering ee admin page.
856
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
857
-     *
858
-     * @since      4.3.0
859
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
860
-     * @see        EE_Register_Admin_Page::register()
861
-     * @param       $page_basename
862
-     * @param       $page_path
863
-     * @param array $config
864
-     * @return void
865
-     * @throws EE_Error
866
-     */
867
-    public static function register_ee_admin_page($page_basename, $page_path, $config = array())
868
-    {
869
-        EE_Error::doing_it_wrong(
870
-            __METHOD__,
871
-            sprintf(
872
-                esc_html__(
873
-                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
874
-                    'event_espresso'
875
-                ),
876
-                $page_basename
877
-            ),
878
-            '4.3'
879
-        );
880
-        if (class_exists('EE_Register_Admin_Page')) {
881
-            $config['page_path'] = $page_path;
882
-        }
883
-        EE_Register_Admin_Page::register($page_basename, $config);
884
-    }
885
-
886
-
887
-    /**
888
-     * @deprecated 4.8.41
889
-     * @param  int      $post_ID
890
-     * @param  \WP_Post $post
891
-     * @return void
892
-     */
893
-    public static function parse_post_content_on_save($post_ID, $post)
894
-    {
895
-        EE_Error::doing_it_wrong(
896
-            __METHOD__,
897
-            esc_html__('Usage is deprecated', 'event_espresso'),
898
-            '4.8.41'
899
-        );
900
-    }
901
-
902
-
903
-    /**
904
-     * @deprecated 4.8.41
905
-     * @param  $option
906
-     * @param  $old_value
907
-     * @param  $value
908
-     * @return void
909
-     */
910
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
911
-    {
912
-        EE_Error::doing_it_wrong(
913
-            __METHOD__,
914
-            esc_html__('Usage is deprecated', 'event_espresso'),
915
-            '4.8.41'
916
-        );
917
-    }
918
-
919
-
920
-
921
-    /**
922
-     * @deprecated 4.9.27
923
-     * @return void
924
-     */
925
-    public function get_persistent_admin_notices()
926
-    {
927
-        EE_Error::doing_it_wrong(
928
-            __METHOD__,
929
-            sprintf(
930
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
931
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
932
-            ),
933
-            '4.9.27'
934
-        );
935
-    }
936
-
937
-
938
-
939
-    /**
940
-     * @deprecated 4.9.27
941
-     * @throws InvalidInterfaceException
942
-     * @throws InvalidDataTypeException
943
-     * @throws DomainException
944
-     */
945
-    public function dismiss_ee_nag_notice_callback()
946
-    {
947
-        EE_Error::doing_it_wrong(
948
-            __METHOD__,
949
-            sprintf(
950
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
951
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
952
-            ),
953
-            '4.9.27'
954
-        );
955
-        $this->persistent_admin_notice_manager->dismissNotice();
956
-    }
957
-
958
-
959
-    /**
960
-     * Callback on load-plugins.php hook for setting up anything hooking into the wp plugins page.
961
-     * @throws InvalidArgumentException
962
-     * @throws InvalidDataTypeException
963
-     * @throws InvalidInterfaceException
964
-     */
965
-    public function hookIntoWpPluginsPage()
966
-    {
967
-        LoaderFactory::getLoader()->getShared('EventEspresso\core\domain\services\admin\ExitModal');
968
-        LoaderFactory::getLoader()
969
-                     ->getShared('EventEspresso\core\domain\services\admin\PluginUpsells')
970
-                     ->decafUpsells();
971
-    }
490
+	}
491
+
492
+
493
+	/**
494
+	 * Returns an array of event archive nav items.
495
+	 *
496
+	 * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
497
+	 *        method we use for getting the extra nav menu items
498
+	 * @return array
499
+	 */
500
+	private function _get_extra_nav_menu_pages_items()
501
+	{
502
+		$menuitems[] = array(
503
+			'title'       => esc_html__('Event List', 'event_espresso'),
504
+			'url'         => get_post_type_archive_link('espresso_events'),
505
+			'description' => esc_html__('Archive page for all events.', 'event_espresso'),
506
+		);
507
+		return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
508
+	}
509
+
510
+
511
+	/**
512
+	 * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
513
+	 * the properties and converts it to the menu item object.
514
+	 *
515
+	 * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
516
+	 * @param $menu_item_values
517
+	 * @return stdClass
518
+	 */
519
+	private function _setup_extra_nav_menu_pages_items($menu_item_values)
520
+	{
521
+		$menu_item = new stdClass();
522
+		$keys      = array(
523
+			'ID'               => 0,
524
+			'db_id'            => 0,
525
+			'menu_item_parent' => 0,
526
+			'object_id'        => -1,
527
+			'post_parent'      => 0,
528
+			'type'             => 'custom',
529
+			'object'           => '',
530
+			'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
531
+			'title'            => '',
532
+			'url'              => '',
533
+			'target'           => '',
534
+			'attr_title'       => '',
535
+			'description'      => '',
536
+			'classes'          => array(),
537
+			'xfn'              => '',
538
+		);
539
+
540
+		foreach ($keys as $key => $value) {
541
+			$menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
542
+		}
543
+		return $menu_item;
544
+	}
545
+
546
+
547
+	/**
548
+	 * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
549
+	 * EE_Admin_Page route is called.
550
+	 *
551
+	 * @return void
552
+	 */
553
+	public function route_admin_request()
554
+	{
555
+	}
556
+
557
+
558
+	/**
559
+	 * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
560
+	 *
561
+	 * @return void
562
+	 */
563
+	public function wp_loaded()
564
+	{
565
+	}
566
+
567
+
568
+	/**
569
+	 * admin_init
570
+	 *
571
+	 * @return void
572
+	 * @throws EE_Error
573
+	 * @throws InvalidArgumentException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws InvalidInterfaceException
576
+	 * @throws ReflectionException
577
+	 */
578
+	public function admin_init()
579
+	{
580
+
581
+		/**
582
+		 * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
583
+		 * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
584
+		 * - check if doing post processing.
585
+		 * - check if doing post processing of one of EE CPTs
586
+		 * - instantiate the corresponding EE CPT model for the post_type being processed.
587
+		 */
588
+		if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
589
+			EE_Registry::instance()->load_core('Register_CPTs');
590
+			EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
591
+		}
592
+
593
+
594
+		/**
595
+		 * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
596
+		 * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
597
+		 * Pages" tab in the EE General Settings Admin page.
598
+		 * This is for user-proofing.
599
+		 */
600
+		add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
601
+	}
602
+
603
+
604
+	/**
605
+	 * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
606
+	 *
607
+	 * @param string $output Current output.
608
+	 * @return string
609
+	 * @throws InvalidArgumentException
610
+	 * @throws InvalidDataTypeException
611
+	 * @throws InvalidInterfaceException
612
+	 */
613
+	public function modify_dropdown_pages($output)
614
+	{
615
+		//get critical pages
616
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
617
+
618
+		//split current output by line break for easier parsing.
619
+		$split_output = explode("\n", $output);
620
+
621
+		//loop through to remove any critical pages from the array.
622
+		foreach ($critical_pages as $page_id) {
623
+			$needle = 'value="' . $page_id . '"';
624
+			foreach ($split_output as $key => $haystack) {
625
+				if (strpos($haystack, $needle) !== false) {
626
+					unset($split_output[$key]);
627
+				}
628
+			}
629
+		}
630
+		//replace output with the new contents
631
+		return implode("\n", $split_output);
632
+	}
633
+
634
+
635
+	/**
636
+	 * enqueue all admin scripts that need loaded for admin pages
637
+	 *
638
+	 * @return void
639
+	 */
640
+	public function enqueue_admin_scripts()
641
+	{
642
+		// this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
643
+		// Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
644
+		// calls.
645
+		wp_enqueue_script(
646
+			'ee-inject-wp',
647
+			EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
648
+			array('jquery'),
649
+			EVENT_ESPRESSO_VERSION,
650
+			true
651
+		);
652
+		// register cookie script for future dependencies
653
+		wp_register_script(
654
+			'jquery-cookie',
655
+			EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
656
+			array('jquery'),
657
+			'2.1',
658
+			true
659
+		);
660
+		//joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
661
+		// via: add_filter('FHEE_load_joyride', '__return_true' );
662
+		if (apply_filters('FHEE_load_joyride', false)) {
663
+			//joyride style
664
+			wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
665
+			wp_register_style(
666
+				'ee-joyride-css',
667
+				EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
668
+				array('joyride-css'),
669
+				EVENT_ESPRESSO_VERSION
670
+			);
671
+			wp_register_script(
672
+				'joyride-modernizr',
673
+				EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
674
+				array(),
675
+				'2.1',
676
+				true
677
+			);
678
+			//joyride JS
679
+			wp_register_script(
680
+				'jquery-joyride',
681
+				EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
682
+				array('jquery-cookie', 'joyride-modernizr'),
683
+				'2.1',
684
+				true
685
+			);
686
+			// wanna go for a joyride?
687
+			wp_enqueue_style('ee-joyride-css');
688
+			wp_enqueue_script('jquery-joyride');
689
+		}
690
+	}
691
+
692
+
693
+	/**
694
+	 * display_admin_notices
695
+	 *
696
+	 * @return void
697
+	 */
698
+	public function display_admin_notices()
699
+	{
700
+		echo EE_Error::get_notices();
701
+	}
702
+
703
+
704
+
705
+	/**
706
+	 * @param array $elements
707
+	 * @return array
708
+	 * @throws EE_Error
709
+	 * @throws InvalidArgumentException
710
+	 * @throws InvalidDataTypeException
711
+	 * @throws InvalidInterfaceException
712
+	 */
713
+	public function dashboard_glance_items($elements)
714
+	{
715
+		$elements                        = is_array($elements) ? $elements : array($elements);
716
+		$events                          = EEM_Event::instance()->count();
717
+		$items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
718
+			array('page' => 'espresso_events'),
719
+			admin_url('admin.php')
720
+		);
721
+		$items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
722
+		$items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
723
+		$registrations                   = EEM_Registration::instance()->count(
724
+			array(
725
+				array(
726
+					'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
727
+				),
728
+			)
729
+		);
730
+		$items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
731
+			array('page' => 'espresso_registrations'),
732
+			admin_url('admin.php')
733
+		);
734
+		$items['registrations']['text']  = sprintf(
735
+			_n('%s Registration', '%s Registrations', $registrations),
736
+			number_format_i18n($registrations)
737
+		);
738
+		$items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
739
+
740
+		$items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
741
+
742
+		foreach ($items as $type => $item_properties) {
743
+			$elements[] = sprintf(
744
+				'<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
745
+				$item_properties['url'],
746
+				$item_properties['title'],
747
+				$item_properties['text']
748
+			);
749
+		}
750
+		return $elements;
751
+	}
752
+
753
+
754
+	/**
755
+	 * check_for_invalid_datetime_formats
756
+	 * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
757
+	 * their selected format can be parsed by PHP
758
+	 *
759
+	 * @param    $value
760
+	 * @param    $option
761
+	 * @throws EE_Error
762
+	 * @return    string
763
+	 */
764
+	public function check_for_invalid_datetime_formats($value, $option)
765
+	{
766
+		// check for date_format or time_format
767
+		switch ($option) {
768
+			case 'date_format':
769
+				$date_time_format = $value . ' ' . get_option('time_format');
770
+				break;
771
+			case 'time_format':
772
+				$date_time_format = get_option('date_format') . ' ' . $value;
773
+				break;
774
+			default:
775
+				$date_time_format = false;
776
+		}
777
+		// do we have a date_time format to check ?
778
+		if ($date_time_format) {
779
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
780
+
781
+			if (is_array($error_msg)) {
782
+				$msg = '<p>'
783
+					   . sprintf(
784
+						   esc_html__(
785
+							   'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
786
+							   'event_espresso'
787
+						   ),
788
+						   date($date_time_format),
789
+						   $date_time_format
790
+					   )
791
+					   . '</p><p><ul>';
792
+
793
+
794
+				foreach ($error_msg as $error) {
795
+					$msg .= '<li>' . $error . '</li>';
796
+				}
797
+
798
+				$msg .= '</ul></p><p>'
799
+						. sprintf(
800
+							esc_html__(
801
+								'%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
802
+								'event_espresso'
803
+							),
804
+							'<span style="color:#D54E21;">',
805
+							'</span>'
806
+						)
807
+						. '</p>';
808
+
809
+				// trigger WP settings error
810
+				add_settings_error(
811
+					'date_format',
812
+					'date_format',
813
+					$msg
814
+				);
815
+
816
+				// set format to something valid
817
+				switch ($option) {
818
+					case 'date_format':
819
+						$value = 'F j, Y';
820
+						break;
821
+					case 'time_format':
822
+						$value = 'g:i a';
823
+						break;
824
+				}
825
+			}
826
+		}
827
+		return $value;
828
+	}
829
+
830
+
831
+	/**
832
+	 * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
833
+	 *
834
+	 * @param $content
835
+	 * @return    string
836
+	 */
837
+	public function its_eSpresso($content)
838
+	{
839
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
840
+	}
841
+
842
+
843
+	/**
844
+	 * espresso_admin_footer
845
+	 *
846
+	 * @return    string
847
+	 */
848
+	public function espresso_admin_footer()
849
+	{
850
+		return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
851
+	}
852
+
853
+
854
+	/**
855
+	 * static method for registering ee admin page.
856
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
857
+	 *
858
+	 * @since      4.3.0
859
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
860
+	 * @see        EE_Register_Admin_Page::register()
861
+	 * @param       $page_basename
862
+	 * @param       $page_path
863
+	 * @param array $config
864
+	 * @return void
865
+	 * @throws EE_Error
866
+	 */
867
+	public static function register_ee_admin_page($page_basename, $page_path, $config = array())
868
+	{
869
+		EE_Error::doing_it_wrong(
870
+			__METHOD__,
871
+			sprintf(
872
+				esc_html__(
873
+					'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
874
+					'event_espresso'
875
+				),
876
+				$page_basename
877
+			),
878
+			'4.3'
879
+		);
880
+		if (class_exists('EE_Register_Admin_Page')) {
881
+			$config['page_path'] = $page_path;
882
+		}
883
+		EE_Register_Admin_Page::register($page_basename, $config);
884
+	}
885
+
886
+
887
+	/**
888
+	 * @deprecated 4.8.41
889
+	 * @param  int      $post_ID
890
+	 * @param  \WP_Post $post
891
+	 * @return void
892
+	 */
893
+	public static function parse_post_content_on_save($post_ID, $post)
894
+	{
895
+		EE_Error::doing_it_wrong(
896
+			__METHOD__,
897
+			esc_html__('Usage is deprecated', 'event_espresso'),
898
+			'4.8.41'
899
+		);
900
+	}
901
+
902
+
903
+	/**
904
+	 * @deprecated 4.8.41
905
+	 * @param  $option
906
+	 * @param  $old_value
907
+	 * @param  $value
908
+	 * @return void
909
+	 */
910
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
911
+	{
912
+		EE_Error::doing_it_wrong(
913
+			__METHOD__,
914
+			esc_html__('Usage is deprecated', 'event_espresso'),
915
+			'4.8.41'
916
+		);
917
+	}
918
+
919
+
920
+
921
+	/**
922
+	 * @deprecated 4.9.27
923
+	 * @return void
924
+	 */
925
+	public function get_persistent_admin_notices()
926
+	{
927
+		EE_Error::doing_it_wrong(
928
+			__METHOD__,
929
+			sprintf(
930
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
931
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
932
+			),
933
+			'4.9.27'
934
+		);
935
+	}
936
+
937
+
938
+
939
+	/**
940
+	 * @deprecated 4.9.27
941
+	 * @throws InvalidInterfaceException
942
+	 * @throws InvalidDataTypeException
943
+	 * @throws DomainException
944
+	 */
945
+	public function dismiss_ee_nag_notice_callback()
946
+	{
947
+		EE_Error::doing_it_wrong(
948
+			__METHOD__,
949
+			sprintf(
950
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
951
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
952
+			),
953
+			'4.9.27'
954
+		);
955
+		$this->persistent_admin_notice_manager->dismissNotice();
956
+	}
957
+
958
+
959
+	/**
960
+	 * Callback on load-plugins.php hook for setting up anything hooking into the wp plugins page.
961
+	 * @throws InvalidArgumentException
962
+	 * @throws InvalidDataTypeException
963
+	 * @throws InvalidInterfaceException
964
+	 */
965
+	public function hookIntoWpPluginsPage()
966
+	{
967
+		LoaderFactory::getLoader()->getShared('EventEspresso\core\domain\services\admin\ExitModal');
968
+		LoaderFactory::getLoader()
969
+					 ->getShared('EventEspresso\core\domain\services\admin\PluginUpsells')
970
+					 ->decafUpsells();
971
+	}
972 972
 }
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 2 patches
Indentation   +3722 added lines, -3722 removed lines patch added patch discarded remove patch
@@ -30,2339 +30,2339 @@  discard block
 block discarded – undo
30 30
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
31 31
 {
32 32
 
33
-    /**
34
-     * @var EE_Registration
35
-     */
36
-    private $_registration;
37
-
38
-    /**
39
-     * @var EE_Event
40
-     */
41
-    private $_reg_event;
42
-
43
-    /**
44
-     * @var EE_Session
45
-     */
46
-    private $_session;
47
-
48
-    private static $_reg_status;
49
-
50
-    /**
51
-     * Form for displaying the custom questions for this registration.
52
-     * This gets used a few times throughout the request so its best to cache it
53
-     *
54
-     * @var EE_Registration_Custom_Questions_Form
55
-     */
56
-    protected $_reg_custom_questions_form = null;
57
-
58
-
59
-    /**
60
-     *        constructor
61
-     *
62
-     * @Constructor
63
-     * @access public
64
-     * @param bool $routing
65
-     * @return Registrations_Admin_Page
66
-     */
67
-    public function __construct($routing = true)
68
-    {
69
-        parent::__construct($routing);
70
-        add_action('wp_loaded', array($this, 'wp_loaded'));
71
-    }
72
-
73
-
74
-    public function wp_loaded()
75
-    {
76
-        // when adding a new registration...
77
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
78
-            EE_System::do_not_cache();
79
-            if (! isset($this->_req_data['processing_registration'])
80
-                 || absint($this->_req_data['processing_registration']) !== 1
81
-            ) {
82
-                // and it's NOT the attendee information reg step
83
-                // force cookie expiration by setting time to last week
84
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
85
-                // and update the global
86
-                $_COOKIE['ee_registration_added'] = 0;
87
-            }
88
-        }
89
-    }
90
-
91
-
92
-    protected function _init_page_props()
93
-    {
94
-        $this->page_slug        = REG_PG_SLUG;
95
-        $this->_admin_base_url  = REG_ADMIN_URL;
96
-        $this->_admin_base_path = REG_ADMIN;
97
-        $this->page_label       = esc_html__('Registrations', 'event_espresso');
98
-        $this->_cpt_routes      = array(
99
-            'add_new_attendee' => 'espresso_attendees',
100
-            'edit_attendee'    => 'espresso_attendees',
101
-            'insert_attendee'  => 'espresso_attendees',
102
-            'update_attendee'  => 'espresso_attendees',
103
-        );
104
-        $this->_cpt_model_names = array(
105
-            'add_new_attendee' => 'EEM_Attendee',
106
-            'edit_attendee'    => 'EEM_Attendee',
107
-        );
108
-        $this->_cpt_edit_routes = array(
109
-            'espresso_attendees' => 'edit_attendee',
110
-        );
111
-        $this->_pagenow_map     = array(
112
-            'add_new_attendee' => 'post-new.php',
113
-            'edit_attendee'    => 'post.php',
114
-            'trash'            => 'post.php',
115
-        );
116
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
117
-        //add filters so that the comment urls don't take users to a confusing 404 page
118
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
119
-    }
120
-
121
-
122
-    public function clear_comment_link($link, $comment, $args)
123
-    {
124
-        //gotta make sure this only happens on this route
125
-        $post_type = get_post_type($comment->comment_post_ID);
126
-        if ($post_type === 'espresso_attendees') {
127
-            return '#commentsdiv';
128
-        }
129
-        return $link;
130
-    }
131
-
132
-
133
-    protected function _ajax_hooks()
134
-    {
135
-        //todo: all hooks for registrations ajax goes in here
136
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
137
-    }
138
-
139
-
140
-    protected function _define_page_props()
141
-    {
142
-        $this->_admin_page_title = $this->page_label;
143
-        $this->_labels           = array(
144
-            'buttons'                      => array(
145
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
146
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
147
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
148
-                'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
149
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
150
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
151
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
152
-                'contact_list_export' => esc_html__("Export Data", "event_espresso"),
153
-            ),
154
-            'publishbox'                   => array(
155
-                'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
156
-                'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
157
-            ),
158
-            'hide_add_button_on_cpt_route' => array(
159
-                'edit_attendee' => true,
160
-            ),
161
-        );
162
-    }
163
-
164
-
165
-    /**
166
-     *        grab url requests and route them
167
-     *
168
-     * @access private
169
-     * @return void
170
-     */
171
-    public function _set_page_routes()
172
-    {
173
-        $this->_get_registration_status_array();
174
-        $reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
175
-            ? $this->_req_data['_REG_ID'] : 0;
176
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
177
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
178
-            : $reg_id;
179
-        $att_id             = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
180
-            ? $this->_req_data['ATT_ID'] : 0;
181
-        $att_id             = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
182
-            ? $this->_req_data['post']
183
-            : $att_id;
184
-        $this->_page_routes = array(
185
-            'default'                            => array(
186
-                'func'       => '_registrations_overview_list_table',
187
-                'capability' => 'ee_read_registrations',
188
-            ),
189
-            'view_registration'                  => array(
190
-                'func'       => '_registration_details',
191
-                'capability' => 'ee_read_registration',
192
-                'obj_id'     => $reg_id,
193
-            ),
194
-            'edit_registration'                  => array(
195
-                'func'               => '_update_attendee_registration_form',
196
-                'noheader'           => true,
197
-                'headers_sent_route' => 'view_registration',
198
-                'capability'         => 'ee_edit_registration',
199
-                'obj_id'             => $reg_id,
200
-                '_REG_ID'            => $reg_id,
201
-            ),
202
-            'trash_registrations'                => array(
203
-                'func'       => '_trash_or_restore_registrations',
204
-                'args'       => array('trash' => true),
205
-                'noheader'   => true,
206
-                'capability' => 'ee_delete_registrations',
207
-            ),
208
-            'restore_registrations'              => array(
209
-                'func'       => '_trash_or_restore_registrations',
210
-                'args'       => array('trash' => false),
211
-                'noheader'   => true,
212
-                'capability' => 'ee_delete_registrations',
213
-            ),
214
-            'delete_registrations'               => array(
215
-                'func'       => '_delete_registrations',
216
-                'noheader'   => true,
217
-                'capability' => 'ee_delete_registrations',
218
-            ),
219
-            'new_registration'                   => array(
220
-                'func'       => 'new_registration',
221
-                'capability' => 'ee_edit_registrations',
222
-            ),
223
-            'process_reg_step'                   => array(
224
-                'func'       => 'process_reg_step',
225
-                'noheader'   => true,
226
-                'capability' => 'ee_edit_registrations',
227
-            ),
228
-            'redirect_to_txn'                    => array(
229
-                'func'       => 'redirect_to_txn',
230
-                'noheader'   => true,
231
-                'capability' => 'ee_edit_registrations',
232
-            ),
233
-            'change_reg_status'                  => array(
234
-                'func'       => '_change_reg_status',
235
-                'noheader'   => true,
236
-                'capability' => 'ee_edit_registration',
237
-                'obj_id'     => $reg_id,
238
-            ),
239
-            'approve_registration'               => array(
240
-                'func'       => 'approve_registration',
241
-                'noheader'   => true,
242
-                'capability' => 'ee_edit_registration',
243
-                'obj_id'     => $reg_id,
244
-            ),
245
-            'approve_and_notify_registration'    => array(
246
-                'func'       => 'approve_registration',
247
-                'noheader'   => true,
248
-                'args'       => array(true),
249
-                'capability' => 'ee_edit_registration',
250
-                'obj_id'     => $reg_id,
251
-            ),
252
-            'approve_registrations'               => array(
253
-                'func'       => 'bulk_action_on_registrations',
254
-                'noheader'   => true,
255
-                'capability' => 'ee_edit_registrations',
256
-                'args' => array('approve')
257
-            ),
258
-            'approve_and_notify_registrations'               => array(
259
-                'func'       => 'bulk_action_on_registrations',
260
-                'noheader'   => true,
261
-                'capability' => 'ee_edit_registrations',
262
-                'args' => array('approve', true)
263
-            ),
264
-            'decline_registration'               => array(
265
-                'func'       => 'decline_registration',
266
-                'noheader'   => true,
267
-                'capability' => 'ee_edit_registration',
268
-                'obj_id'     => $reg_id,
269
-            ),
270
-            'decline_and_notify_registration'    => array(
271
-                'func'       => 'decline_registration',
272
-                'noheader'   => true,
273
-                'args'       => array(true),
274
-                'capability' => 'ee_edit_registration',
275
-                'obj_id'     => $reg_id,
276
-            ),
277
-            'decline_registrations'               => array(
278
-                'func'       => 'bulk_action_on_registrations',
279
-                'noheader'   => true,
280
-                'capability' => 'ee_edit_registrations',
281
-                'args' => array('decline')
282
-            ),
283
-            'decline_and_notify_registrations'    => array(
284
-                'func'       => 'bulk_action_on_registrations',
285
-                'noheader'   => true,
286
-                'capability' => 'ee_edit_registrations',
287
-                'args' => array('decline', true)
288
-            ),
289
-            'pending_registration'               => array(
290
-                'func'       => 'pending_registration',
291
-                'noheader'   => true,
292
-                'capability' => 'ee_edit_registration',
293
-                'obj_id'     => $reg_id,
294
-            ),
295
-            'pending_and_notify_registration'    => array(
296
-                'func'       => 'pending_registration',
297
-                'noheader'   => true,
298
-                'args'       => array(true),
299
-                'capability' => 'ee_edit_registration',
300
-                'obj_id'     => $reg_id,
301
-            ),
302
-            'pending_registrations'               => array(
303
-                'func'       => 'bulk_action_on_registrations',
304
-                'noheader'   => true,
305
-                'capability' => 'ee_edit_registrations',
306
-                'args' => array('pending')
307
-            ),
308
-            'pending_and_notify_registrations'    => array(
309
-                'func'       => 'bulk_action_on_registrations',
310
-                'noheader'   => true,
311
-                'capability' => 'ee_edit_registrations',
312
-                'args' => array('pending', true)
313
-            ),
314
-            'no_approve_registration'            => array(
315
-                'func'       => 'not_approve_registration',
316
-                'noheader'   => true,
317
-                'capability' => 'ee_edit_registration',
318
-                'obj_id'     => $reg_id,
319
-            ),
320
-            'no_approve_and_notify_registration' => array(
321
-                'func'       => 'not_approve_registration',
322
-                'noheader'   => true,
323
-                'args'       => array(true),
324
-                'capability' => 'ee_edit_registration',
325
-                'obj_id'     => $reg_id,
326
-            ),
327
-            'no_approve_registrations'            => array(
328
-                'func'       => 'bulk_action_on_registrations',
329
-                'noheader'   => true,
330
-                'capability' => 'ee_edit_registrations',
331
-                'args' => array('not_approve')
332
-            ),
333
-            'no_approve_and_notify_registrations' => array(
334
-                'func'       => 'bulk_action_on_registrations',
335
-                'noheader'   => true,
336
-                'capability' => 'ee_edit_registrations',
337
-                'args' => array('not_approve', true)
338
-            ),
339
-            'cancel_registration'                => array(
340
-                'func'       => 'cancel_registration',
341
-                'noheader'   => true,
342
-                'capability' => 'ee_edit_registration',
343
-                'obj_id'     => $reg_id,
344
-            ),
345
-            'cancel_and_notify_registration'     => array(
346
-                'func'       => 'cancel_registration',
347
-                'noheader'   => true,
348
-                'args'       => array(true),
349
-                'capability' => 'ee_edit_registration',
350
-                'obj_id'     => $reg_id,
351
-            ),
352
-            'cancel_registrations'                => array(
353
-                'func'       => 'bulk_action_on_registrations',
354
-                'noheader'   => true,
355
-                'capability' => 'ee_edit_registrations',
356
-                'args' => array('cancel')
357
-            ),
358
-            'cancel_and_notify_registrations'     => array(
359
-                'func'       => 'bulk_action_on_registrations',
360
-                'noheader'   => true,
361
-                'capability' => 'ee_edit_registrations',
362
-                'args' => array('cancel', true)
363
-            ),
364
-            'wait_list_registration' => array(
365
-                'func'       => 'wait_list_registration',
366
-                'noheader'   => true,
367
-                'capability' => 'ee_edit_registration',
368
-                'obj_id'     => $reg_id,
369
-            ),
370
-            'wait_list_and_notify_registration' => array(
371
-                'func'       => 'wait_list_registration',
372
-                'noheader'   => true,
373
-                'args'       => array(true),
374
-                'capability' => 'ee_edit_registration',
375
-                'obj_id'     => $reg_id,
376
-            ),
377
-            'contact_list'                       => array(
378
-                'func'       => '_attendee_contact_list_table',
379
-                'capability' => 'ee_read_contacts',
380
-            ),
381
-            'add_new_attendee'                   => array(
382
-                'func' => '_create_new_cpt_item',
383
-                'args' => array(
384
-                    'new_attendee' => true,
385
-                    'capability'   => 'ee_edit_contacts',
386
-                ),
387
-            ),
388
-            'edit_attendee'                      => array(
389
-                'func'       => '_edit_cpt_item',
390
-                'capability' => 'ee_edit_contacts',
391
-                'obj_id'     => $att_id,
392
-            ),
393
-            'duplicate_attendee'                 => array(
394
-                'func'       => '_duplicate_attendee',
395
-                'noheader'   => true,
396
-                'capability' => 'ee_edit_contacts',
397
-                'obj_id'     => $att_id,
398
-            ),
399
-            'insert_attendee'                    => array(
400
-                'func'       => '_insert_or_update_attendee',
401
-                'args'       => array(
402
-                    'new_attendee' => true,
403
-                ),
404
-                'noheader'   => true,
405
-                'capability' => 'ee_edit_contacts',
406
-            ),
407
-            'update_attendee'                    => array(
408
-                'func'       => '_insert_or_update_attendee',
409
-                'args'       => array(
410
-                    'new_attendee' => false,
411
-                ),
412
-                'noheader'   => true,
413
-                'capability' => 'ee_edit_contacts',
414
-                'obj_id'     => $att_id,
415
-            ),
416
-            'trash_attendees' => array(
417
-                'func' => '_trash_or_restore_attendees',
418
-                'args' => array(
419
-                    'trash' => 'true'
420
-                ),
421
-                'noheader' => true,
422
-                'capability' => 'ee_delete_contacts'
423
-            ),
424
-            'trash_attendee'                    => array(
425
-                'func'       => '_trash_or_restore_attendees',
426
-                'args'       => array(
427
-                    'trash' => true,
428
-                ),
429
-                'noheader'   => true,
430
-                'capability' => 'ee_delete_contacts',
431
-                'obj_id'     => $att_id,
432
-            ),
433
-            'restore_attendees'                  => array(
434
-                'func'       => '_trash_or_restore_attendees',
435
-                'args'       => array(
436
-                    'trash' => false,
437
-                ),
438
-                'noheader'   => true,
439
-                'capability' => 'ee_delete_contacts',
440
-                'obj_id'     => $att_id,
441
-            ),
442
-            'resend_registration'                => array(
443
-                'func'       => '_resend_registration',
444
-                'noheader'   => true,
445
-                'capability' => 'ee_send_message',
446
-            ),
447
-            'registrations_report'               => array(
448
-                'func'       => '_registrations_report',
449
-                'noheader'   => true,
450
-                'capability' => 'ee_read_registrations',
451
-            ),
452
-            'contact_list_export'                => array(
453
-                'func'       => '_contact_list_export',
454
-                'noheader'   => true,
455
-                'capability' => 'export',
456
-            ),
457
-            'contact_list_report'                => array(
458
-                'func'       => '_contact_list_report',
459
-                'noheader'   => true,
460
-                'capability' => 'ee_read_contacts',
461
-            ),
462
-        );
463
-    }
464
-
465
-
466
-    protected function _set_page_config()
467
-    {
468
-        $this->_page_config = array(
469
-            'default'           => array(
470
-                'nav'           => array(
471
-                    'label' => esc_html__('Overview', 'event_espresso'),
472
-                    'order' => 5,
473
-                ),
474
-                'help_tabs'     => array(
475
-                    'registrations_overview_help_tab'                       => array(
476
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
477
-                        'filename' => 'registrations_overview',
478
-                    ),
479
-                    'registrations_overview_table_column_headings_help_tab' => array(
480
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
481
-                        'filename' => 'registrations_overview_table_column_headings',
482
-                    ),
483
-                    'registrations_overview_filters_help_tab'               => array(
484
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
485
-                        'filename' => 'registrations_overview_filters',
486
-                    ),
487
-                    'registrations_overview_views_help_tab'                 => array(
488
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
489
-                        'filename' => 'registrations_overview_views',
490
-                    ),
491
-                    'registrations_regoverview_other_help_tab'              => array(
492
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
493
-                        'filename' => 'registrations_overview_other',
494
-                    ),
495
-                ),
496
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
497
-                'qtips'         => array('Registration_List_Table_Tips'),
498
-                'list_table'    => 'EE_Registrations_List_Table',
499
-                'require_nonce' => false,
500
-            ),
501
-            'view_registration' => array(
502
-                'nav'           => array(
503
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
504
-                    'order'      => 15,
505
-                    'url'        => isset($this->_req_data['_REG_ID'])
506
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
507
-                        : $this->_admin_base_url,
508
-                    'persistent' => false,
509
-                ),
510
-                'help_tabs'     => array(
511
-                    'registrations_details_help_tab'                    => array(
512
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
513
-                        'filename' => 'registrations_details',
514
-                    ),
515
-                    'registrations_details_table_help_tab'              => array(
516
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
517
-                        'filename' => 'registrations_details_table',
518
-                    ),
519
-                    'registrations_details_form_answers_help_tab'       => array(
520
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
521
-                        'filename' => 'registrations_details_form_answers',
522
-                    ),
523
-                    'registrations_details_registrant_details_help_tab' => array(
524
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
525
-                        'filename' => 'registrations_details_registrant_details',
526
-                    ),
527
-                ),
528
-                'help_tour'     => array('Registration_Details_Help_Tour'),
529
-                'metaboxes'     => array_merge(
530
-                    $this->_default_espresso_metaboxes,
531
-                    array('_registration_details_metaboxes')
532
-                ),
533
-                'require_nonce' => false,
534
-            ),
535
-            'new_registration'  => array(
536
-                'nav'           => array(
537
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
538
-                    'url'        => '#',
539
-                    'order'      => 15,
540
-                    'persistent' => false,
541
-                ),
542
-                'metaboxes'     => $this->_default_espresso_metaboxes,
543
-                'labels'        => array(
544
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
545
-                ),
546
-                'require_nonce' => false,
547
-            ),
548
-            'add_new_attendee'  => array(
549
-                'nav'           => array(
550
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
551
-                    'order'      => 15,
552
-                    'persistent' => false,
553
-                ),
554
-                'metaboxes'     => array_merge(
555
-                    $this->_default_espresso_metaboxes,
556
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
557
-                ),
558
-                'require_nonce' => false,
559
-            ),
560
-            'edit_attendee'     => array(
561
-                'nav'           => array(
562
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
563
-                    'order'      => 15,
564
-                    'persistent' => false,
565
-                    'url'        => isset($this->_req_data['ATT_ID'])
566
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
567
-                        : $this->_admin_base_url,
568
-                ),
569
-                'metaboxes'     => array('attendee_editor_metaboxes'),
570
-                'require_nonce' => false,
571
-            ),
572
-            'contact_list'      => array(
573
-                'nav'           => array(
574
-                    'label' => esc_html__('Contact List', 'event_espresso'),
575
-                    'order' => 20,
576
-                ),
577
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
578
-                'help_tabs'     => array(
579
-                    'registrations_contact_list_help_tab'                       => array(
580
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
581
-                        'filename' => 'registrations_contact_list',
582
-                    ),
583
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
584
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
585
-                        'filename' => 'registrations_contact_list_table_column_headings',
586
-                    ),
587
-                    'registrations_contact_list_views_help_tab'                 => array(
588
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
589
-                        'filename' => 'registrations_contact_list_views',
590
-                    ),
591
-                    'registrations_contact_list_other_help_tab'                 => array(
592
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
593
-                        'filename' => 'registrations_contact_list_other',
594
-                    ),
595
-                ),
596
-                'help_tour'     => array('Contact_List_Help_Tour'),
597
-                'metaboxes'     => array(),
598
-                'require_nonce' => false,
599
-            ),
600
-            //override default cpt routes
601
-            'create_new'        => '',
602
-            'edit'              => '',
603
-        );
604
-    }
605
-
606
-
607
-    /**
608
-     * The below methods aren't used by this class currently
609
-     */
610
-    protected function _add_screen_options()
611
-    {
612
-    }
613
-
614
-
615
-    protected function _add_feature_pointers()
616
-    {
617
-    }
618
-
619
-
620
-    public function admin_init()
621
-    {
622
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
623
-            'click "Update Registration Questions" to save your changes',
624
-            'event_espresso'
625
-        );
626
-    }
627
-
628
-
629
-    public function admin_notices()
630
-    {
631
-    }
632
-
633
-
634
-    public function admin_footer_scripts()
635
-    {
636
-    }
637
-
638
-
639
-    /**
640
-     *        get list of registration statuses
641
-     *
642
-     * @access private
643
-     * @return void
644
-     * @throws EE_Error
645
-     */
646
-    private function _get_registration_status_array()
647
-    {
648
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
649
-    }
650
-
651
-
652
-    protected function _add_screen_options_default()
653
-    {
654
-        $this->_per_page_screen_option();
655
-    }
656
-
657
-
658
-    protected function _add_screen_options_contact_list()
659
-    {
660
-        $page_title              = $this->_admin_page_title;
661
-        $this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
662
-        $this->_per_page_screen_option();
663
-        $this->_admin_page_title = $page_title;
664
-    }
665
-
666
-
667
-    public function load_scripts_styles()
668
-    {
669
-        //style
670
-        wp_register_style(
671
-            'espresso_reg',
672
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
673
-            array('ee-admin-css'),
674
-            EVENT_ESPRESSO_VERSION
675
-        );
676
-        wp_enqueue_style('espresso_reg');
677
-        //script
678
-        wp_register_script(
679
-            'espresso_reg',
680
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
681
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
682
-            EVENT_ESPRESSO_VERSION,
683
-            true
684
-        );
685
-        wp_enqueue_script('espresso_reg');
686
-    }
687
-
688
-
689
-    public function load_scripts_styles_edit_attendee()
690
-    {
691
-        //stuff to only show up on our attendee edit details page.
692
-        $attendee_details_translations = array(
693
-            'att_publish_text' => sprintf(
694
-                esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
695
-                $this->_cpt_model_obj->get_datetime('ATT_created')
696
-            ),
697
-        );
698
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
699
-        wp_enqueue_script('jquery-validate');
700
-    }
701
-
702
-
703
-    public function load_scripts_styles_view_registration()
704
-    {
705
-        //styles
706
-        wp_enqueue_style('espresso-ui-theme');
707
-        //scripts
708
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
709
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
710
-    }
711
-
712
-
713
-    public function load_scripts_styles_contact_list()
714
-    {
715
-        wp_dequeue_style('espresso_reg');
716
-        wp_register_style(
717
-            'espresso_att',
718
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
719
-            array('ee-admin-css'),
720
-            EVENT_ESPRESSO_VERSION
721
-        );
722
-        wp_enqueue_style('espresso_att');
723
-    }
724
-
725
-
726
-    public function load_scripts_styles_new_registration()
727
-    {
728
-        wp_register_script(
729
-            'ee-spco-for-admin',
730
-            REG_ASSETS_URL . 'spco_for_admin.js',
731
-            array('underscore', 'jquery'),
732
-            EVENT_ESPRESSO_VERSION,
733
-            true
734
-        );
735
-        wp_enqueue_script('ee-spco-for-admin');
736
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
737
-        EE_Form_Section_Proper::wp_enqueue_scripts();
738
-        EED_Ticket_Selector::load_tckt_slctr_assets();
739
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
740
-    }
741
-
742
-
743
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
744
-    {
745
-        add_filter('FHEE_load_EE_messages', '__return_true');
746
-    }
747
-
748
-
749
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
750
-    {
751
-        add_filter('FHEE_load_EE_messages', '__return_true');
752
-    }
753
-
754
-
755
-    protected function _set_list_table_views_default()
756
-    {
757
-        //for notification related bulk actions we need to make sure only active messengers have an option.
758
-        EED_Messages::set_autoloaders();
759
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
760
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
761
-        $active_mts               = $message_resource_manager->list_of_active_message_types();
762
-        //key= bulk_action_slug, value= message type.
763
-        $match_array = array(
764
-            'approve_registrations'    => 'registration',
765
-            'decline_registrations'    => 'declined_registration',
766
-            'pending_registrations'    => 'pending_approval',
767
-            'no_approve_registrations' => 'not_approved_registration',
768
-            'cancel_registrations'     => 'cancelled_registration',
769
-        );
770
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
771
-            'ee_send_message',
772
-            'batch_send_messages'
773
-        );
774
-        /** setup reg status bulk actions **/
775
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
776
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
777
-                $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
778
-                    'Approve and Notify Registrations',
779
-                    'event_espresso'
780
-                );
781
-        }
782
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
783
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
784
-                $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
785
-                    'Decline and Notify Registrations',
786
-                    'event_espresso'
787
-                );
788
-        }
789
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
790
-            'Set Registrations to Pending Payment',
791
-            'event_espresso'
792
-        );
793
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
794
-                $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
795
-                    'Set Registrations to Pending Payment and Notify',
796
-                    'event_espresso'
797
-                );
798
-        }
799
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
800
-            'Set Registrations to Not Approved',
801
-            'event_espresso'
802
-        );
803
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
804
-                $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
805
-                    'Set Registrations to Not Approved and Notify',
806
-                    'event_espresso'
807
-                );
808
-        }
809
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
810
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
811
-                $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
812
-                    'Cancel Registrations and Notify',
813
-                    'event_espresso'
814
-                );
815
-        }
816
-        $def_reg_status_actions = apply_filters(
817
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
818
-            $def_reg_status_actions,
819
-            $active_mts,
820
-            $can_send
821
-        );
822
-
823
-        $this->_views = array(
824
-            'all'   => array(
825
-                'slug'        => 'all',
826
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
827
-                'count'       => 0,
828
-                'bulk_action' => array_merge($def_reg_status_actions, array(
829
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
830
-                )),
831
-            ),
832
-            'month' => array(
833
-                'slug'        => 'month',
834
-                'label'       => esc_html__('This Month', 'event_espresso'),
835
-                'count'       => 0,
836
-                'bulk_action' => array_merge($def_reg_status_actions, array(
837
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
838
-                )),
839
-            ),
840
-            'today' => array(
841
-                'slug'        => 'today',
842
-                'label'       => sprintf(
843
-                    esc_html__('Today - %s', 'event_espresso'),
844
-                    date('M d, Y', current_time('timestamp'))
845
-                ),
846
-                'count'       => 0,
847
-                'bulk_action' => array_merge($def_reg_status_actions, array(
848
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
849
-                )),
850
-            ),
851
-        );
852
-        if (EE_Registry::instance()->CAP->current_user_can(
853
-            'ee_delete_registrations',
854
-            'espresso_registrations_delete_registration'
855
-        )) {
856
-            $this->_views['incomplete'] = array(
857
-                'slug'        => 'incomplete',
858
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
859
-                'count'       => 0,
860
-                'bulk_action' => array(
861
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
862
-                ),
863
-            );
864
-            $this->_views['trash']      = array(
865
-                'slug'        => 'trash',
866
-                'label'       => esc_html__('Trash', 'event_espresso'),
867
-                'count'       => 0,
868
-                'bulk_action' => array(
869
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
870
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
871
-                ),
872
-            );
873
-        }
874
-    }
875
-
876
-
877
-    protected function _set_list_table_views_contact_list()
878
-    {
879
-        $this->_views = array(
880
-            'in_use' => array(
881
-                'slug'        => 'in_use',
882
-                'label'       => esc_html__('In Use', 'event_espresso'),
883
-                'count'       => 0,
884
-                'bulk_action' => array(
885
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
886
-                ),
887
-            ),
888
-        );
889
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_contacts',
890
-            'espresso_registrations_trash_attendees')
891
-        ) {
892
-            $this->_views['trash'] = array(
893
-                'slug'        => 'trash',
894
-                'label'       => esc_html__('Trash', 'event_espresso'),
895
-                'count'       => 0,
896
-                'bulk_action' => array(
897
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
-                ),
899
-            );
900
-        }
901
-    }
902
-
903
-
904
-    protected function _registration_legend_items()
905
-    {
906
-        $fc_items = array(
907
-            'star-icon'        => array(
908
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
-            ),
911
-            'view_details'     => array(
912
-                'class' => 'dashicons dashicons-clipboard',
913
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
-            ),
915
-            'edit_attendee'    => array(
916
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
-            ),
919
-            'view_transaction' => array(
920
-                'class' => 'dashicons dashicons-cart',
921
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
-            ),
923
-            'view_invoice'     => array(
924
-                'class' => 'dashicons dashicons-media-spreadsheet',
925
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
-            ),
927
-        );
928
-        if (EE_Registry::instance()->CAP->current_user_can(
929
-            'ee_send_message',
930
-            'espresso_registrations_resend_registration'
931
-        )) {
932
-            $fc_items['resend_registration'] = array(
933
-                'class' => 'dashicons dashicons-email-alt',
934
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
-            );
936
-        } else {
937
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
-        }
939
-        if (EE_Registry::instance()->CAP->current_user_can(
940
-            'ee_read_global_messages',
941
-            'view_filtered_messages'
942
-        )) {
943
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
-                $fc_items['view_related_messages'] = array(
946
-                    'class' => $related_for_icon['css_class'],
947
-                    'desc'  => $related_for_icon['label'],
948
-                );
949
-            }
950
-        }
951
-        $sc_items = array(
952
-            'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
-                'desc'  => EEH_Template::pretty_status(
955
-                    EEM_Registration::status_id_approved,
956
-                    false,
957
-                    'sentence'
958
-                ),
959
-            ),
960
-            'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
-                'desc'  => EEH_Template::pretty_status(
963
-                    EEM_Registration::status_id_pending_payment,
964
-                    false,
965
-                    'sentence'
966
-                ),
967
-            ),
968
-            'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
-                'desc'  => EEH_Template::pretty_status(
971
-                    EEM_Registration::status_id_wait_list,
972
-                    false,
973
-                    'sentence'
974
-                ),
975
-            ),
976
-            'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
-                'desc'  => EEH_Template::pretty_status(
979
-                    EEM_Registration::status_id_incomplete,
980
-                    false,
981
-                    'sentence'
982
-                ),
983
-            ),
984
-            'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
-                'desc'  => EEH_Template::pretty_status(
987
-                    EEM_Registration::status_id_not_approved,
988
-                    false,
989
-                    'sentence'
990
-                ),
991
-            ),
992
-            'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
-                'desc'  => EEH_Template::pretty_status(
995
-                    EEM_Registration::status_id_declined,
996
-                    false,
997
-                    'sentence'
998
-                ),
999
-            ),
1000
-            'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
-                'desc'  => EEH_Template::pretty_status(
1003
-                    EEM_Registration::status_id_cancelled,
1004
-                    false,
1005
-                    'sentence'
1006
-                ),
1007
-            ),
1008
-        );
1009
-        return array_merge($fc_items, $sc_items);
1010
-    }
1011
-
1012
-
1013
-
1014
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1015
-    /**
1016
-     * @throws \EE_Error
1017
-     */
1018
-    protected function _registrations_overview_list_table()
1019
-    {
1020
-        $this->_template_args['admin_page_header'] = '';
1021
-        $EVT_ID                                    = ! empty($this->_req_data['event_id'])
1022
-            ? absint($this->_req_data['event_id'])
1023
-            : 0;
1024
-        $ATT_ID = !empty($this->_req_data['ATT_ID'])
1025
-            ? absint($this->_req_data['ATT_ID'])
1026
-            : 0;
1027
-        if ($ATT_ID) {
1028
-            $attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
-            if ($attendee instanceof EE_Attendee) {
1030
-                $this->_template_args['admin_page_header'] = sprintf(
1031
-                    esc_html__(
1032
-                        '%1$s Viewing registrations for %2$s%3$s',
1033
-                        'event_espresso'
1034
-                    ),
1035
-                    '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
-                        array(
1038
-                            'action' => 'edit_attendee',
1039
-                            'post' => $ATT_ID
1040
-                        ),
1041
-                        REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1043
-                    '</h3>'
1044
-                );
1045
-            }
1046
-        }
1047
-        if ($EVT_ID) {
1048
-            if (EE_Registry::instance()->CAP->current_user_can(
1049
-                'ee_edit_registrations',
1050
-                'espresso_registrations_new_registration',
1051
-                $EVT_ID
1052
-            )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
-                    'new_registration',
1055
-                    'add-registrant',
1056
-                    array('event_id' => $EVT_ID),
1057
-                    'add-new-h2'
1058
-                );
1059
-            }
1060
-            $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
-            if ($event instanceof EE_Event) {
1062
-                $this->_template_args['admin_page_header'] = sprintf(
1063
-                    esc_html__(
1064
-                        '%s Viewing registrations for the event: %s%s',
1065
-                        'event_espresso'
1066
-                    ),
1067
-                    '<h3 style="line-height:1.5em;">',
1068
-                    '<br /><a href="'
1069
-                        . EE_Admin_Page::add_query_args_and_nonce(
1070
-                            array(
1071
-                                'action' => 'edit',
1072
-                                'post'   => $event->ID(),
1073
-                            ),
1074
-                            EVENTS_ADMIN_URL
1075
-                        )
1076
-                        . '">&nbsp;'
1077
-                        . $event->get('EVT_name')
1078
-                        . '&nbsp;</a>&nbsp;',
1079
-                    '</h3>'
1080
-                );
1081
-            }
1082
-            $DTT_ID   = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
-            if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
-                $this->_template_args['admin_page_header'] = substr(
1086
-                    $this->_template_args['admin_page_header'],
1087
-                    0,
1088
-                    -5
1089
-                );
1090
-                $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
-                $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
-                $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
-                $this->_template_args['admin_page_header'] .= '</span></h3>';
1095
-            }
1096
-        }
1097
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
-        $this->display_admin_list_table_page_with_no_sidebar();
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * This sets the _registration property for the registration details screen
1104
-     *
1105
-     * @access private
1106
-     * @return bool
1107
-     * @throws EE_Error
1108
-     * @throws InvalidArgumentException
1109
-     * @throws InvalidDataTypeException
1110
-     * @throws InvalidInterfaceException
1111
-     */
1112
-    private function _set_registration_object()
1113
-    {
1114
-        //get out if we've already set the object
1115
-        if ($this->_registration instanceof EE_Registration) {
1116
-            return true;
1117
-        }
1118
-        $REG    = EEM_Registration::instance();
1119
-        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
-        if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
-            return true;
1122
-        } else {
1123
-            $error_msg = sprintf(
1124
-                esc_html__(
1125
-                    'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
-                    'event_espresso'
1127
-                ),
1128
-                $REG_ID
1129
-            );
1130
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            $this->_registration = null;
1132
-            return false;
1133
-        }
1134
-    }
1135
-
1136
-
1137
-    /**
1138
-     * Used to retrieve registrations for the list table.
1139
-     *
1140
-     * @param int  $per_page
1141
-     * @param bool $count
1142
-     * @param bool $this_month
1143
-     * @param bool $today
1144
-     * @return EE_Registration[]|int
1145
-     * @throws EE_Error
1146
-     * @throws InvalidArgumentException
1147
-     * @throws InvalidDataTypeException
1148
-     * @throws InvalidInterfaceException
1149
-     */
1150
-    public function get_registrations(
1151
-        $per_page = 10,
1152
-        $count = false,
1153
-        $this_month = false,
1154
-        $today = false
1155
-    ) {
1156
-        if ($this_month) {
1157
-            $this->_req_data['status'] = 'month';
1158
-        }
1159
-        if ($today) {
1160
-            $this->_req_data['status'] = 'today';
1161
-        }
1162
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
-        /**
1164
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1166
-         * @see EEM_Base::get_all()
1167
-         */
1168
-        $query_params['group_by'] = '';
1169
-
1170
-        return $count
1171
-            ? EEM_Registration::instance()->count($query_params)
1172
-            /** @type EE_Registration[] */
1173
-            : EEM_Registration::instance()->get_all($query_params);
1174
-    }
1175
-
1176
-
1177
-    /**
1178
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1179
-     * Note: this listens to values on the request for some of the query parameters.
1180
-     *
1181
-     * @param array $request
1182
-     * @param int   $per_page
1183
-     * @param bool  $count
1184
-     * @return array
1185
-     * @throws EE_Error
1186
-     */
1187
-    protected function _get_registration_query_parameters(
1188
-        $request = array(),
1189
-        $per_page = 10,
1190
-        $count = false
1191
-    ) {
1192
-
1193
-        $query_params = array(
1194
-            0                          => $this->_get_where_conditions_for_registrations_query(
1195
-                $request
1196
-            ),
1197
-            'caps'                     => EEM_Registration::caps_read_admin,
1198
-            'default_where_conditions' => 'this_model_only',
1199
-        );
1200
-        if (! $count) {
1201
-            $query_params = array_merge(
1202
-                $query_params,
1203
-                $this->_get_orderby_for_registrations_query(),
1204
-                $this->_get_limit($per_page)
1205
-            );
1206
-        }
1207
-
1208
-        return $query_params;
1209
-    }
1210
-
1211
-
1212
-    /**
1213
-     * This will add ATT_ID to the provided $where array for EE model query parameters.
1214
-     *
1215
-     * @param array $request usually the same as $this->_req_data but not necessarily
1216
-     * @return array
1217
-     */
1218
-    protected function addAttendeeIdToWhereConditions(array $request)
1219
-    {
1220
-        $where = array();
1221
-        if (! empty($request['ATT_ID'])) {
1222
-            $where['ATT_ID'] = absint($request['ATT_ID']);
1223
-        }
1224
-        return $where;
1225
-    }
1226
-
1227
-
1228
-    /**
1229
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1230
-     *
1231
-     * @param array $request usually the same as $this->_req_data but not necessarily
1232
-     * @return array
1233
-     */
1234
-    protected function _add_event_id_to_where_conditions(array $request)
1235
-    {
1236
-        $where = array();
1237
-        if (! empty($request['event_id'])) {
1238
-            $where['EVT_ID'] = absint($request['event_id']);
1239
-        }
1240
-        return $where;
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1246
-     *
1247
-     * @param array $request usually the same as $this->_req_data but not necessarily
1248
-     * @return array
1249
-     */
1250
-    protected function _add_category_id_to_where_conditions(array $request)
1251
-    {
1252
-        $where = array();
1253
-        if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1254
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1255
-        }
1256
-        return $where;
1257
-    }
1258
-
1259
-
1260
-    /**
1261
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1262
-     *
1263
-     * @param array $request usually the same as $this->_req_data but not necessarily
1264
-     * @return array
1265
-     */
1266
-    protected function _add_datetime_id_to_where_conditions(array $request)
1267
-    {
1268
-        $where = array();
1269
-        if (! empty($request['datetime_id'])) {
1270
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1271
-        }
1272
-        if (! empty($request['DTT_ID'])) {
1273
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1274
-        }
1275
-        return $where;
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * Adds the correct registration status to the where conditions for the registrations query.
1281
-     *
1282
-     * @param array $request usually the same as $this->_req_data but not necessarily
1283
-     * @return array
1284
-     */
1285
-    protected function _add_registration_status_to_where_conditions(array $request)
1286
-    {
1287
-        $where = array();
1288
-        $view = EEH_Array::is_set($request, 'status', '');
1289
-        $registration_status = ! empty($request['_reg_status'])
1290
-            ? sanitize_text_field($request['_reg_status'])
1291
-            : '';
1292
-
1293
-        /*
33
+	/**
34
+	 * @var EE_Registration
35
+	 */
36
+	private $_registration;
37
+
38
+	/**
39
+	 * @var EE_Event
40
+	 */
41
+	private $_reg_event;
42
+
43
+	/**
44
+	 * @var EE_Session
45
+	 */
46
+	private $_session;
47
+
48
+	private static $_reg_status;
49
+
50
+	/**
51
+	 * Form for displaying the custom questions for this registration.
52
+	 * This gets used a few times throughout the request so its best to cache it
53
+	 *
54
+	 * @var EE_Registration_Custom_Questions_Form
55
+	 */
56
+	protected $_reg_custom_questions_form = null;
57
+
58
+
59
+	/**
60
+	 *        constructor
61
+	 *
62
+	 * @Constructor
63
+	 * @access public
64
+	 * @param bool $routing
65
+	 * @return Registrations_Admin_Page
66
+	 */
67
+	public function __construct($routing = true)
68
+	{
69
+		parent::__construct($routing);
70
+		add_action('wp_loaded', array($this, 'wp_loaded'));
71
+	}
72
+
73
+
74
+	public function wp_loaded()
75
+	{
76
+		// when adding a new registration...
77
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
78
+			EE_System::do_not_cache();
79
+			if (! isset($this->_req_data['processing_registration'])
80
+				 || absint($this->_req_data['processing_registration']) !== 1
81
+			) {
82
+				// and it's NOT the attendee information reg step
83
+				// force cookie expiration by setting time to last week
84
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
85
+				// and update the global
86
+				$_COOKIE['ee_registration_added'] = 0;
87
+			}
88
+		}
89
+	}
90
+
91
+
92
+	protected function _init_page_props()
93
+	{
94
+		$this->page_slug        = REG_PG_SLUG;
95
+		$this->_admin_base_url  = REG_ADMIN_URL;
96
+		$this->_admin_base_path = REG_ADMIN;
97
+		$this->page_label       = esc_html__('Registrations', 'event_espresso');
98
+		$this->_cpt_routes      = array(
99
+			'add_new_attendee' => 'espresso_attendees',
100
+			'edit_attendee'    => 'espresso_attendees',
101
+			'insert_attendee'  => 'espresso_attendees',
102
+			'update_attendee'  => 'espresso_attendees',
103
+		);
104
+		$this->_cpt_model_names = array(
105
+			'add_new_attendee' => 'EEM_Attendee',
106
+			'edit_attendee'    => 'EEM_Attendee',
107
+		);
108
+		$this->_cpt_edit_routes = array(
109
+			'espresso_attendees' => 'edit_attendee',
110
+		);
111
+		$this->_pagenow_map     = array(
112
+			'add_new_attendee' => 'post-new.php',
113
+			'edit_attendee'    => 'post.php',
114
+			'trash'            => 'post.php',
115
+		);
116
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
117
+		//add filters so that the comment urls don't take users to a confusing 404 page
118
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
119
+	}
120
+
121
+
122
+	public function clear_comment_link($link, $comment, $args)
123
+	{
124
+		//gotta make sure this only happens on this route
125
+		$post_type = get_post_type($comment->comment_post_ID);
126
+		if ($post_type === 'espresso_attendees') {
127
+			return '#commentsdiv';
128
+		}
129
+		return $link;
130
+	}
131
+
132
+
133
+	protected function _ajax_hooks()
134
+	{
135
+		//todo: all hooks for registrations ajax goes in here
136
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
137
+	}
138
+
139
+
140
+	protected function _define_page_props()
141
+	{
142
+		$this->_admin_page_title = $this->page_label;
143
+		$this->_labels           = array(
144
+			'buttons'                      => array(
145
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
146
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
147
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
148
+				'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
149
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
150
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
151
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
152
+				'contact_list_export' => esc_html__("Export Data", "event_espresso"),
153
+			),
154
+			'publishbox'                   => array(
155
+				'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
156
+				'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
157
+			),
158
+			'hide_add_button_on_cpt_route' => array(
159
+				'edit_attendee' => true,
160
+			),
161
+		);
162
+	}
163
+
164
+
165
+	/**
166
+	 *        grab url requests and route them
167
+	 *
168
+	 * @access private
169
+	 * @return void
170
+	 */
171
+	public function _set_page_routes()
172
+	{
173
+		$this->_get_registration_status_array();
174
+		$reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
175
+			? $this->_req_data['_REG_ID'] : 0;
176
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
177
+			? $this->_req_data['reg_status_change_form']['REG_ID']
178
+			: $reg_id;
179
+		$att_id             = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
180
+			? $this->_req_data['ATT_ID'] : 0;
181
+		$att_id             = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
182
+			? $this->_req_data['post']
183
+			: $att_id;
184
+		$this->_page_routes = array(
185
+			'default'                            => array(
186
+				'func'       => '_registrations_overview_list_table',
187
+				'capability' => 'ee_read_registrations',
188
+			),
189
+			'view_registration'                  => array(
190
+				'func'       => '_registration_details',
191
+				'capability' => 'ee_read_registration',
192
+				'obj_id'     => $reg_id,
193
+			),
194
+			'edit_registration'                  => array(
195
+				'func'               => '_update_attendee_registration_form',
196
+				'noheader'           => true,
197
+				'headers_sent_route' => 'view_registration',
198
+				'capability'         => 'ee_edit_registration',
199
+				'obj_id'             => $reg_id,
200
+				'_REG_ID'            => $reg_id,
201
+			),
202
+			'trash_registrations'                => array(
203
+				'func'       => '_trash_or_restore_registrations',
204
+				'args'       => array('trash' => true),
205
+				'noheader'   => true,
206
+				'capability' => 'ee_delete_registrations',
207
+			),
208
+			'restore_registrations'              => array(
209
+				'func'       => '_trash_or_restore_registrations',
210
+				'args'       => array('trash' => false),
211
+				'noheader'   => true,
212
+				'capability' => 'ee_delete_registrations',
213
+			),
214
+			'delete_registrations'               => array(
215
+				'func'       => '_delete_registrations',
216
+				'noheader'   => true,
217
+				'capability' => 'ee_delete_registrations',
218
+			),
219
+			'new_registration'                   => array(
220
+				'func'       => 'new_registration',
221
+				'capability' => 'ee_edit_registrations',
222
+			),
223
+			'process_reg_step'                   => array(
224
+				'func'       => 'process_reg_step',
225
+				'noheader'   => true,
226
+				'capability' => 'ee_edit_registrations',
227
+			),
228
+			'redirect_to_txn'                    => array(
229
+				'func'       => 'redirect_to_txn',
230
+				'noheader'   => true,
231
+				'capability' => 'ee_edit_registrations',
232
+			),
233
+			'change_reg_status'                  => array(
234
+				'func'       => '_change_reg_status',
235
+				'noheader'   => true,
236
+				'capability' => 'ee_edit_registration',
237
+				'obj_id'     => $reg_id,
238
+			),
239
+			'approve_registration'               => array(
240
+				'func'       => 'approve_registration',
241
+				'noheader'   => true,
242
+				'capability' => 'ee_edit_registration',
243
+				'obj_id'     => $reg_id,
244
+			),
245
+			'approve_and_notify_registration'    => array(
246
+				'func'       => 'approve_registration',
247
+				'noheader'   => true,
248
+				'args'       => array(true),
249
+				'capability' => 'ee_edit_registration',
250
+				'obj_id'     => $reg_id,
251
+			),
252
+			'approve_registrations'               => array(
253
+				'func'       => 'bulk_action_on_registrations',
254
+				'noheader'   => true,
255
+				'capability' => 'ee_edit_registrations',
256
+				'args' => array('approve')
257
+			),
258
+			'approve_and_notify_registrations'               => array(
259
+				'func'       => 'bulk_action_on_registrations',
260
+				'noheader'   => true,
261
+				'capability' => 'ee_edit_registrations',
262
+				'args' => array('approve', true)
263
+			),
264
+			'decline_registration'               => array(
265
+				'func'       => 'decline_registration',
266
+				'noheader'   => true,
267
+				'capability' => 'ee_edit_registration',
268
+				'obj_id'     => $reg_id,
269
+			),
270
+			'decline_and_notify_registration'    => array(
271
+				'func'       => 'decline_registration',
272
+				'noheader'   => true,
273
+				'args'       => array(true),
274
+				'capability' => 'ee_edit_registration',
275
+				'obj_id'     => $reg_id,
276
+			),
277
+			'decline_registrations'               => array(
278
+				'func'       => 'bulk_action_on_registrations',
279
+				'noheader'   => true,
280
+				'capability' => 'ee_edit_registrations',
281
+				'args' => array('decline')
282
+			),
283
+			'decline_and_notify_registrations'    => array(
284
+				'func'       => 'bulk_action_on_registrations',
285
+				'noheader'   => true,
286
+				'capability' => 'ee_edit_registrations',
287
+				'args' => array('decline', true)
288
+			),
289
+			'pending_registration'               => array(
290
+				'func'       => 'pending_registration',
291
+				'noheader'   => true,
292
+				'capability' => 'ee_edit_registration',
293
+				'obj_id'     => $reg_id,
294
+			),
295
+			'pending_and_notify_registration'    => array(
296
+				'func'       => 'pending_registration',
297
+				'noheader'   => true,
298
+				'args'       => array(true),
299
+				'capability' => 'ee_edit_registration',
300
+				'obj_id'     => $reg_id,
301
+			),
302
+			'pending_registrations'               => array(
303
+				'func'       => 'bulk_action_on_registrations',
304
+				'noheader'   => true,
305
+				'capability' => 'ee_edit_registrations',
306
+				'args' => array('pending')
307
+			),
308
+			'pending_and_notify_registrations'    => array(
309
+				'func'       => 'bulk_action_on_registrations',
310
+				'noheader'   => true,
311
+				'capability' => 'ee_edit_registrations',
312
+				'args' => array('pending', true)
313
+			),
314
+			'no_approve_registration'            => array(
315
+				'func'       => 'not_approve_registration',
316
+				'noheader'   => true,
317
+				'capability' => 'ee_edit_registration',
318
+				'obj_id'     => $reg_id,
319
+			),
320
+			'no_approve_and_notify_registration' => array(
321
+				'func'       => 'not_approve_registration',
322
+				'noheader'   => true,
323
+				'args'       => array(true),
324
+				'capability' => 'ee_edit_registration',
325
+				'obj_id'     => $reg_id,
326
+			),
327
+			'no_approve_registrations'            => array(
328
+				'func'       => 'bulk_action_on_registrations',
329
+				'noheader'   => true,
330
+				'capability' => 'ee_edit_registrations',
331
+				'args' => array('not_approve')
332
+			),
333
+			'no_approve_and_notify_registrations' => array(
334
+				'func'       => 'bulk_action_on_registrations',
335
+				'noheader'   => true,
336
+				'capability' => 'ee_edit_registrations',
337
+				'args' => array('not_approve', true)
338
+			),
339
+			'cancel_registration'                => array(
340
+				'func'       => 'cancel_registration',
341
+				'noheader'   => true,
342
+				'capability' => 'ee_edit_registration',
343
+				'obj_id'     => $reg_id,
344
+			),
345
+			'cancel_and_notify_registration'     => array(
346
+				'func'       => 'cancel_registration',
347
+				'noheader'   => true,
348
+				'args'       => array(true),
349
+				'capability' => 'ee_edit_registration',
350
+				'obj_id'     => $reg_id,
351
+			),
352
+			'cancel_registrations'                => array(
353
+				'func'       => 'bulk_action_on_registrations',
354
+				'noheader'   => true,
355
+				'capability' => 'ee_edit_registrations',
356
+				'args' => array('cancel')
357
+			),
358
+			'cancel_and_notify_registrations'     => array(
359
+				'func'       => 'bulk_action_on_registrations',
360
+				'noheader'   => true,
361
+				'capability' => 'ee_edit_registrations',
362
+				'args' => array('cancel', true)
363
+			),
364
+			'wait_list_registration' => array(
365
+				'func'       => 'wait_list_registration',
366
+				'noheader'   => true,
367
+				'capability' => 'ee_edit_registration',
368
+				'obj_id'     => $reg_id,
369
+			),
370
+			'wait_list_and_notify_registration' => array(
371
+				'func'       => 'wait_list_registration',
372
+				'noheader'   => true,
373
+				'args'       => array(true),
374
+				'capability' => 'ee_edit_registration',
375
+				'obj_id'     => $reg_id,
376
+			),
377
+			'contact_list'                       => array(
378
+				'func'       => '_attendee_contact_list_table',
379
+				'capability' => 'ee_read_contacts',
380
+			),
381
+			'add_new_attendee'                   => array(
382
+				'func' => '_create_new_cpt_item',
383
+				'args' => array(
384
+					'new_attendee' => true,
385
+					'capability'   => 'ee_edit_contacts',
386
+				),
387
+			),
388
+			'edit_attendee'                      => array(
389
+				'func'       => '_edit_cpt_item',
390
+				'capability' => 'ee_edit_contacts',
391
+				'obj_id'     => $att_id,
392
+			),
393
+			'duplicate_attendee'                 => array(
394
+				'func'       => '_duplicate_attendee',
395
+				'noheader'   => true,
396
+				'capability' => 'ee_edit_contacts',
397
+				'obj_id'     => $att_id,
398
+			),
399
+			'insert_attendee'                    => array(
400
+				'func'       => '_insert_or_update_attendee',
401
+				'args'       => array(
402
+					'new_attendee' => true,
403
+				),
404
+				'noheader'   => true,
405
+				'capability' => 'ee_edit_contacts',
406
+			),
407
+			'update_attendee'                    => array(
408
+				'func'       => '_insert_or_update_attendee',
409
+				'args'       => array(
410
+					'new_attendee' => false,
411
+				),
412
+				'noheader'   => true,
413
+				'capability' => 'ee_edit_contacts',
414
+				'obj_id'     => $att_id,
415
+			),
416
+			'trash_attendees' => array(
417
+				'func' => '_trash_or_restore_attendees',
418
+				'args' => array(
419
+					'trash' => 'true'
420
+				),
421
+				'noheader' => true,
422
+				'capability' => 'ee_delete_contacts'
423
+			),
424
+			'trash_attendee'                    => array(
425
+				'func'       => '_trash_or_restore_attendees',
426
+				'args'       => array(
427
+					'trash' => true,
428
+				),
429
+				'noheader'   => true,
430
+				'capability' => 'ee_delete_contacts',
431
+				'obj_id'     => $att_id,
432
+			),
433
+			'restore_attendees'                  => array(
434
+				'func'       => '_trash_or_restore_attendees',
435
+				'args'       => array(
436
+					'trash' => false,
437
+				),
438
+				'noheader'   => true,
439
+				'capability' => 'ee_delete_contacts',
440
+				'obj_id'     => $att_id,
441
+			),
442
+			'resend_registration'                => array(
443
+				'func'       => '_resend_registration',
444
+				'noheader'   => true,
445
+				'capability' => 'ee_send_message',
446
+			),
447
+			'registrations_report'               => array(
448
+				'func'       => '_registrations_report',
449
+				'noheader'   => true,
450
+				'capability' => 'ee_read_registrations',
451
+			),
452
+			'contact_list_export'                => array(
453
+				'func'       => '_contact_list_export',
454
+				'noheader'   => true,
455
+				'capability' => 'export',
456
+			),
457
+			'contact_list_report'                => array(
458
+				'func'       => '_contact_list_report',
459
+				'noheader'   => true,
460
+				'capability' => 'ee_read_contacts',
461
+			),
462
+		);
463
+	}
464
+
465
+
466
+	protected function _set_page_config()
467
+	{
468
+		$this->_page_config = array(
469
+			'default'           => array(
470
+				'nav'           => array(
471
+					'label' => esc_html__('Overview', 'event_espresso'),
472
+					'order' => 5,
473
+				),
474
+				'help_tabs'     => array(
475
+					'registrations_overview_help_tab'                       => array(
476
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
477
+						'filename' => 'registrations_overview',
478
+					),
479
+					'registrations_overview_table_column_headings_help_tab' => array(
480
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
481
+						'filename' => 'registrations_overview_table_column_headings',
482
+					),
483
+					'registrations_overview_filters_help_tab'               => array(
484
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
485
+						'filename' => 'registrations_overview_filters',
486
+					),
487
+					'registrations_overview_views_help_tab'                 => array(
488
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
489
+						'filename' => 'registrations_overview_views',
490
+					),
491
+					'registrations_regoverview_other_help_tab'              => array(
492
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
493
+						'filename' => 'registrations_overview_other',
494
+					),
495
+				),
496
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
497
+				'qtips'         => array('Registration_List_Table_Tips'),
498
+				'list_table'    => 'EE_Registrations_List_Table',
499
+				'require_nonce' => false,
500
+			),
501
+			'view_registration' => array(
502
+				'nav'           => array(
503
+					'label'      => esc_html__('REG Details', 'event_espresso'),
504
+					'order'      => 15,
505
+					'url'        => isset($this->_req_data['_REG_ID'])
506
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
507
+						: $this->_admin_base_url,
508
+					'persistent' => false,
509
+				),
510
+				'help_tabs'     => array(
511
+					'registrations_details_help_tab'                    => array(
512
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
513
+						'filename' => 'registrations_details',
514
+					),
515
+					'registrations_details_table_help_tab'              => array(
516
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
517
+						'filename' => 'registrations_details_table',
518
+					),
519
+					'registrations_details_form_answers_help_tab'       => array(
520
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
521
+						'filename' => 'registrations_details_form_answers',
522
+					),
523
+					'registrations_details_registrant_details_help_tab' => array(
524
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
525
+						'filename' => 'registrations_details_registrant_details',
526
+					),
527
+				),
528
+				'help_tour'     => array('Registration_Details_Help_Tour'),
529
+				'metaboxes'     => array_merge(
530
+					$this->_default_espresso_metaboxes,
531
+					array('_registration_details_metaboxes')
532
+				),
533
+				'require_nonce' => false,
534
+			),
535
+			'new_registration'  => array(
536
+				'nav'           => array(
537
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
538
+					'url'        => '#',
539
+					'order'      => 15,
540
+					'persistent' => false,
541
+				),
542
+				'metaboxes'     => $this->_default_espresso_metaboxes,
543
+				'labels'        => array(
544
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
545
+				),
546
+				'require_nonce' => false,
547
+			),
548
+			'add_new_attendee'  => array(
549
+				'nav'           => array(
550
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
551
+					'order'      => 15,
552
+					'persistent' => false,
553
+				),
554
+				'metaboxes'     => array_merge(
555
+					$this->_default_espresso_metaboxes,
556
+					array('_publish_post_box', 'attendee_editor_metaboxes')
557
+				),
558
+				'require_nonce' => false,
559
+			),
560
+			'edit_attendee'     => array(
561
+				'nav'           => array(
562
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
563
+					'order'      => 15,
564
+					'persistent' => false,
565
+					'url'        => isset($this->_req_data['ATT_ID'])
566
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
567
+						: $this->_admin_base_url,
568
+				),
569
+				'metaboxes'     => array('attendee_editor_metaboxes'),
570
+				'require_nonce' => false,
571
+			),
572
+			'contact_list'      => array(
573
+				'nav'           => array(
574
+					'label' => esc_html__('Contact List', 'event_espresso'),
575
+					'order' => 20,
576
+				),
577
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
578
+				'help_tabs'     => array(
579
+					'registrations_contact_list_help_tab'                       => array(
580
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
581
+						'filename' => 'registrations_contact_list',
582
+					),
583
+					'registrations_contact-list_table_column_headings_help_tab' => array(
584
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
585
+						'filename' => 'registrations_contact_list_table_column_headings',
586
+					),
587
+					'registrations_contact_list_views_help_tab'                 => array(
588
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
589
+						'filename' => 'registrations_contact_list_views',
590
+					),
591
+					'registrations_contact_list_other_help_tab'                 => array(
592
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
593
+						'filename' => 'registrations_contact_list_other',
594
+					),
595
+				),
596
+				'help_tour'     => array('Contact_List_Help_Tour'),
597
+				'metaboxes'     => array(),
598
+				'require_nonce' => false,
599
+			),
600
+			//override default cpt routes
601
+			'create_new'        => '',
602
+			'edit'              => '',
603
+		);
604
+	}
605
+
606
+
607
+	/**
608
+	 * The below methods aren't used by this class currently
609
+	 */
610
+	protected function _add_screen_options()
611
+	{
612
+	}
613
+
614
+
615
+	protected function _add_feature_pointers()
616
+	{
617
+	}
618
+
619
+
620
+	public function admin_init()
621
+	{
622
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
623
+			'click "Update Registration Questions" to save your changes',
624
+			'event_espresso'
625
+		);
626
+	}
627
+
628
+
629
+	public function admin_notices()
630
+	{
631
+	}
632
+
633
+
634
+	public function admin_footer_scripts()
635
+	{
636
+	}
637
+
638
+
639
+	/**
640
+	 *        get list of registration statuses
641
+	 *
642
+	 * @access private
643
+	 * @return void
644
+	 * @throws EE_Error
645
+	 */
646
+	private function _get_registration_status_array()
647
+	{
648
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
649
+	}
650
+
651
+
652
+	protected function _add_screen_options_default()
653
+	{
654
+		$this->_per_page_screen_option();
655
+	}
656
+
657
+
658
+	protected function _add_screen_options_contact_list()
659
+	{
660
+		$page_title              = $this->_admin_page_title;
661
+		$this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
662
+		$this->_per_page_screen_option();
663
+		$this->_admin_page_title = $page_title;
664
+	}
665
+
666
+
667
+	public function load_scripts_styles()
668
+	{
669
+		//style
670
+		wp_register_style(
671
+			'espresso_reg',
672
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
673
+			array('ee-admin-css'),
674
+			EVENT_ESPRESSO_VERSION
675
+		);
676
+		wp_enqueue_style('espresso_reg');
677
+		//script
678
+		wp_register_script(
679
+			'espresso_reg',
680
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
681
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
682
+			EVENT_ESPRESSO_VERSION,
683
+			true
684
+		);
685
+		wp_enqueue_script('espresso_reg');
686
+	}
687
+
688
+
689
+	public function load_scripts_styles_edit_attendee()
690
+	{
691
+		//stuff to only show up on our attendee edit details page.
692
+		$attendee_details_translations = array(
693
+			'att_publish_text' => sprintf(
694
+				esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
695
+				$this->_cpt_model_obj->get_datetime('ATT_created')
696
+			),
697
+		);
698
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
699
+		wp_enqueue_script('jquery-validate');
700
+	}
701
+
702
+
703
+	public function load_scripts_styles_view_registration()
704
+	{
705
+		//styles
706
+		wp_enqueue_style('espresso-ui-theme');
707
+		//scripts
708
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
709
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
710
+	}
711
+
712
+
713
+	public function load_scripts_styles_contact_list()
714
+	{
715
+		wp_dequeue_style('espresso_reg');
716
+		wp_register_style(
717
+			'espresso_att',
718
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
719
+			array('ee-admin-css'),
720
+			EVENT_ESPRESSO_VERSION
721
+		);
722
+		wp_enqueue_style('espresso_att');
723
+	}
724
+
725
+
726
+	public function load_scripts_styles_new_registration()
727
+	{
728
+		wp_register_script(
729
+			'ee-spco-for-admin',
730
+			REG_ASSETS_URL . 'spco_for_admin.js',
731
+			array('underscore', 'jquery'),
732
+			EVENT_ESPRESSO_VERSION,
733
+			true
734
+		);
735
+		wp_enqueue_script('ee-spco-for-admin');
736
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
737
+		EE_Form_Section_Proper::wp_enqueue_scripts();
738
+		EED_Ticket_Selector::load_tckt_slctr_assets();
739
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
740
+	}
741
+
742
+
743
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
744
+	{
745
+		add_filter('FHEE_load_EE_messages', '__return_true');
746
+	}
747
+
748
+
749
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
750
+	{
751
+		add_filter('FHEE_load_EE_messages', '__return_true');
752
+	}
753
+
754
+
755
+	protected function _set_list_table_views_default()
756
+	{
757
+		//for notification related bulk actions we need to make sure only active messengers have an option.
758
+		EED_Messages::set_autoloaders();
759
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
760
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
761
+		$active_mts               = $message_resource_manager->list_of_active_message_types();
762
+		//key= bulk_action_slug, value= message type.
763
+		$match_array = array(
764
+			'approve_registrations'    => 'registration',
765
+			'decline_registrations'    => 'declined_registration',
766
+			'pending_registrations'    => 'pending_approval',
767
+			'no_approve_registrations' => 'not_approved_registration',
768
+			'cancel_registrations'     => 'cancelled_registration',
769
+		);
770
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
771
+			'ee_send_message',
772
+			'batch_send_messages'
773
+		);
774
+		/** setup reg status bulk actions **/
775
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
776
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
777
+				$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
778
+					'Approve and Notify Registrations',
779
+					'event_espresso'
780
+				);
781
+		}
782
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
783
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
784
+				$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
785
+					'Decline and Notify Registrations',
786
+					'event_espresso'
787
+				);
788
+		}
789
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
790
+			'Set Registrations to Pending Payment',
791
+			'event_espresso'
792
+		);
793
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
794
+				$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
795
+					'Set Registrations to Pending Payment and Notify',
796
+					'event_espresso'
797
+				);
798
+		}
799
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
800
+			'Set Registrations to Not Approved',
801
+			'event_espresso'
802
+		);
803
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
804
+				$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
805
+					'Set Registrations to Not Approved and Notify',
806
+					'event_espresso'
807
+				);
808
+		}
809
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
810
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
811
+				$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
812
+					'Cancel Registrations and Notify',
813
+					'event_espresso'
814
+				);
815
+		}
816
+		$def_reg_status_actions = apply_filters(
817
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
818
+			$def_reg_status_actions,
819
+			$active_mts,
820
+			$can_send
821
+		);
822
+
823
+		$this->_views = array(
824
+			'all'   => array(
825
+				'slug'        => 'all',
826
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
827
+				'count'       => 0,
828
+				'bulk_action' => array_merge($def_reg_status_actions, array(
829
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
830
+				)),
831
+			),
832
+			'month' => array(
833
+				'slug'        => 'month',
834
+				'label'       => esc_html__('This Month', 'event_espresso'),
835
+				'count'       => 0,
836
+				'bulk_action' => array_merge($def_reg_status_actions, array(
837
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
838
+				)),
839
+			),
840
+			'today' => array(
841
+				'slug'        => 'today',
842
+				'label'       => sprintf(
843
+					esc_html__('Today - %s', 'event_espresso'),
844
+					date('M d, Y', current_time('timestamp'))
845
+				),
846
+				'count'       => 0,
847
+				'bulk_action' => array_merge($def_reg_status_actions, array(
848
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
849
+				)),
850
+			),
851
+		);
852
+		if (EE_Registry::instance()->CAP->current_user_can(
853
+			'ee_delete_registrations',
854
+			'espresso_registrations_delete_registration'
855
+		)) {
856
+			$this->_views['incomplete'] = array(
857
+				'slug'        => 'incomplete',
858
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
859
+				'count'       => 0,
860
+				'bulk_action' => array(
861
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
862
+				),
863
+			);
864
+			$this->_views['trash']      = array(
865
+				'slug'        => 'trash',
866
+				'label'       => esc_html__('Trash', 'event_espresso'),
867
+				'count'       => 0,
868
+				'bulk_action' => array(
869
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
870
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
871
+				),
872
+			);
873
+		}
874
+	}
875
+
876
+
877
+	protected function _set_list_table_views_contact_list()
878
+	{
879
+		$this->_views = array(
880
+			'in_use' => array(
881
+				'slug'        => 'in_use',
882
+				'label'       => esc_html__('In Use', 'event_espresso'),
883
+				'count'       => 0,
884
+				'bulk_action' => array(
885
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
886
+				),
887
+			),
888
+		);
889
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_contacts',
890
+			'espresso_registrations_trash_attendees')
891
+		) {
892
+			$this->_views['trash'] = array(
893
+				'slug'        => 'trash',
894
+				'label'       => esc_html__('Trash', 'event_espresso'),
895
+				'count'       => 0,
896
+				'bulk_action' => array(
897
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
+				),
899
+			);
900
+		}
901
+	}
902
+
903
+
904
+	protected function _registration_legend_items()
905
+	{
906
+		$fc_items = array(
907
+			'star-icon'        => array(
908
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
+			),
911
+			'view_details'     => array(
912
+				'class' => 'dashicons dashicons-clipboard',
913
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
+			),
915
+			'edit_attendee'    => array(
916
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
+			),
919
+			'view_transaction' => array(
920
+				'class' => 'dashicons dashicons-cart',
921
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
+			),
923
+			'view_invoice'     => array(
924
+				'class' => 'dashicons dashicons-media-spreadsheet',
925
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
+			),
927
+		);
928
+		if (EE_Registry::instance()->CAP->current_user_can(
929
+			'ee_send_message',
930
+			'espresso_registrations_resend_registration'
931
+		)) {
932
+			$fc_items['resend_registration'] = array(
933
+				'class' => 'dashicons dashicons-email-alt',
934
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
+			);
936
+		} else {
937
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
+		}
939
+		if (EE_Registry::instance()->CAP->current_user_can(
940
+			'ee_read_global_messages',
941
+			'view_filtered_messages'
942
+		)) {
943
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
+				$fc_items['view_related_messages'] = array(
946
+					'class' => $related_for_icon['css_class'],
947
+					'desc'  => $related_for_icon['label'],
948
+				);
949
+			}
950
+		}
951
+		$sc_items = array(
952
+			'approved_status'   => array(
953
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
+				'desc'  => EEH_Template::pretty_status(
955
+					EEM_Registration::status_id_approved,
956
+					false,
957
+					'sentence'
958
+				),
959
+			),
960
+			'pending_status'    => array(
961
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
+				'desc'  => EEH_Template::pretty_status(
963
+					EEM_Registration::status_id_pending_payment,
964
+					false,
965
+					'sentence'
966
+				),
967
+			),
968
+			'wait_list'         => array(
969
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
+				'desc'  => EEH_Template::pretty_status(
971
+					EEM_Registration::status_id_wait_list,
972
+					false,
973
+					'sentence'
974
+				),
975
+			),
976
+			'incomplete_status' => array(
977
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
+				'desc'  => EEH_Template::pretty_status(
979
+					EEM_Registration::status_id_incomplete,
980
+					false,
981
+					'sentence'
982
+				),
983
+			),
984
+			'not_approved'      => array(
985
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
+				'desc'  => EEH_Template::pretty_status(
987
+					EEM_Registration::status_id_not_approved,
988
+					false,
989
+					'sentence'
990
+				),
991
+			),
992
+			'declined_status'   => array(
993
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
+				'desc'  => EEH_Template::pretty_status(
995
+					EEM_Registration::status_id_declined,
996
+					false,
997
+					'sentence'
998
+				),
999
+			),
1000
+			'cancelled_status'  => array(
1001
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
+				'desc'  => EEH_Template::pretty_status(
1003
+					EEM_Registration::status_id_cancelled,
1004
+					false,
1005
+					'sentence'
1006
+				),
1007
+			),
1008
+		);
1009
+		return array_merge($fc_items, $sc_items);
1010
+	}
1011
+
1012
+
1013
+
1014
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1015
+	/**
1016
+	 * @throws \EE_Error
1017
+	 */
1018
+	protected function _registrations_overview_list_table()
1019
+	{
1020
+		$this->_template_args['admin_page_header'] = '';
1021
+		$EVT_ID                                    = ! empty($this->_req_data['event_id'])
1022
+			? absint($this->_req_data['event_id'])
1023
+			: 0;
1024
+		$ATT_ID = !empty($this->_req_data['ATT_ID'])
1025
+			? absint($this->_req_data['ATT_ID'])
1026
+			: 0;
1027
+		if ($ATT_ID) {
1028
+			$attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
+			if ($attendee instanceof EE_Attendee) {
1030
+				$this->_template_args['admin_page_header'] = sprintf(
1031
+					esc_html__(
1032
+						'%1$s Viewing registrations for %2$s%3$s',
1033
+						'event_espresso'
1034
+					),
1035
+					'<h3 style="line-height:1.5em;">',
1036
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
+						array(
1038
+							'action' => 'edit_attendee',
1039
+							'post' => $ATT_ID
1040
+						),
1041
+						REG_ADMIN_URL
1042
+					) . '">' . $attendee->full_name() . '</a>',
1043
+					'</h3>'
1044
+				);
1045
+			}
1046
+		}
1047
+		if ($EVT_ID) {
1048
+			if (EE_Registry::instance()->CAP->current_user_can(
1049
+				'ee_edit_registrations',
1050
+				'espresso_registrations_new_registration',
1051
+				$EVT_ID
1052
+			)) {
1053
+				$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
+					'new_registration',
1055
+					'add-registrant',
1056
+					array('event_id' => $EVT_ID),
1057
+					'add-new-h2'
1058
+				);
1059
+			}
1060
+			$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
+			if ($event instanceof EE_Event) {
1062
+				$this->_template_args['admin_page_header'] = sprintf(
1063
+					esc_html__(
1064
+						'%s Viewing registrations for the event: %s%s',
1065
+						'event_espresso'
1066
+					),
1067
+					'<h3 style="line-height:1.5em;">',
1068
+					'<br /><a href="'
1069
+						. EE_Admin_Page::add_query_args_and_nonce(
1070
+							array(
1071
+								'action' => 'edit',
1072
+								'post'   => $event->ID(),
1073
+							),
1074
+							EVENTS_ADMIN_URL
1075
+						)
1076
+						. '">&nbsp;'
1077
+						. $event->get('EVT_name')
1078
+						. '&nbsp;</a>&nbsp;',
1079
+					'</h3>'
1080
+				);
1081
+			}
1082
+			$DTT_ID   = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
+			if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
+				$this->_template_args['admin_page_header'] = substr(
1086
+					$this->_template_args['admin_page_header'],
1087
+					0,
1088
+					-5
1089
+				);
1090
+				$this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
+				$this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
+				$this->_template_args['admin_page_header'] .= $datetime->name();
1093
+				$this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
+				$this->_template_args['admin_page_header'] .= '</span></h3>';
1095
+			}
1096
+		}
1097
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
+		$this->display_admin_list_table_page_with_no_sidebar();
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * This sets the _registration property for the registration details screen
1104
+	 *
1105
+	 * @access private
1106
+	 * @return bool
1107
+	 * @throws EE_Error
1108
+	 * @throws InvalidArgumentException
1109
+	 * @throws InvalidDataTypeException
1110
+	 * @throws InvalidInterfaceException
1111
+	 */
1112
+	private function _set_registration_object()
1113
+	{
1114
+		//get out if we've already set the object
1115
+		if ($this->_registration instanceof EE_Registration) {
1116
+			return true;
1117
+		}
1118
+		$REG    = EEM_Registration::instance();
1119
+		$REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
+		if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
+			return true;
1122
+		} else {
1123
+			$error_msg = sprintf(
1124
+				esc_html__(
1125
+					'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
+					'event_espresso'
1127
+				),
1128
+				$REG_ID
1129
+			);
1130
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			$this->_registration = null;
1132
+			return false;
1133
+		}
1134
+	}
1135
+
1136
+
1137
+	/**
1138
+	 * Used to retrieve registrations for the list table.
1139
+	 *
1140
+	 * @param int  $per_page
1141
+	 * @param bool $count
1142
+	 * @param bool $this_month
1143
+	 * @param bool $today
1144
+	 * @return EE_Registration[]|int
1145
+	 * @throws EE_Error
1146
+	 * @throws InvalidArgumentException
1147
+	 * @throws InvalidDataTypeException
1148
+	 * @throws InvalidInterfaceException
1149
+	 */
1150
+	public function get_registrations(
1151
+		$per_page = 10,
1152
+		$count = false,
1153
+		$this_month = false,
1154
+		$today = false
1155
+	) {
1156
+		if ($this_month) {
1157
+			$this->_req_data['status'] = 'month';
1158
+		}
1159
+		if ($today) {
1160
+			$this->_req_data['status'] = 'today';
1161
+		}
1162
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
+		/**
1164
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1166
+		 * @see EEM_Base::get_all()
1167
+		 */
1168
+		$query_params['group_by'] = '';
1169
+
1170
+		return $count
1171
+			? EEM_Registration::instance()->count($query_params)
1172
+			/** @type EE_Registration[] */
1173
+			: EEM_Registration::instance()->get_all($query_params);
1174
+	}
1175
+
1176
+
1177
+	/**
1178
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1179
+	 * Note: this listens to values on the request for some of the query parameters.
1180
+	 *
1181
+	 * @param array $request
1182
+	 * @param int   $per_page
1183
+	 * @param bool  $count
1184
+	 * @return array
1185
+	 * @throws EE_Error
1186
+	 */
1187
+	protected function _get_registration_query_parameters(
1188
+		$request = array(),
1189
+		$per_page = 10,
1190
+		$count = false
1191
+	) {
1192
+
1193
+		$query_params = array(
1194
+			0                          => $this->_get_where_conditions_for_registrations_query(
1195
+				$request
1196
+			),
1197
+			'caps'                     => EEM_Registration::caps_read_admin,
1198
+			'default_where_conditions' => 'this_model_only',
1199
+		);
1200
+		if (! $count) {
1201
+			$query_params = array_merge(
1202
+				$query_params,
1203
+				$this->_get_orderby_for_registrations_query(),
1204
+				$this->_get_limit($per_page)
1205
+			);
1206
+		}
1207
+
1208
+		return $query_params;
1209
+	}
1210
+
1211
+
1212
+	/**
1213
+	 * This will add ATT_ID to the provided $where array for EE model query parameters.
1214
+	 *
1215
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1216
+	 * @return array
1217
+	 */
1218
+	protected function addAttendeeIdToWhereConditions(array $request)
1219
+	{
1220
+		$where = array();
1221
+		if (! empty($request['ATT_ID'])) {
1222
+			$where['ATT_ID'] = absint($request['ATT_ID']);
1223
+		}
1224
+		return $where;
1225
+	}
1226
+
1227
+
1228
+	/**
1229
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1230
+	 *
1231
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1232
+	 * @return array
1233
+	 */
1234
+	protected function _add_event_id_to_where_conditions(array $request)
1235
+	{
1236
+		$where = array();
1237
+		if (! empty($request['event_id'])) {
1238
+			$where['EVT_ID'] = absint($request['event_id']);
1239
+		}
1240
+		return $where;
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1246
+	 *
1247
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1248
+	 * @return array
1249
+	 */
1250
+	protected function _add_category_id_to_where_conditions(array $request)
1251
+	{
1252
+		$where = array();
1253
+		if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1254
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1255
+		}
1256
+		return $where;
1257
+	}
1258
+
1259
+
1260
+	/**
1261
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1262
+	 *
1263
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1264
+	 * @return array
1265
+	 */
1266
+	protected function _add_datetime_id_to_where_conditions(array $request)
1267
+	{
1268
+		$where = array();
1269
+		if (! empty($request['datetime_id'])) {
1270
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1271
+		}
1272
+		if (! empty($request['DTT_ID'])) {
1273
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1274
+		}
1275
+		return $where;
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * Adds the correct registration status to the where conditions for the registrations query.
1281
+	 *
1282
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1283
+	 * @return array
1284
+	 */
1285
+	protected function _add_registration_status_to_where_conditions(array $request)
1286
+	{
1287
+		$where = array();
1288
+		$view = EEH_Array::is_set($request, 'status', '');
1289
+		$registration_status = ! empty($request['_reg_status'])
1290
+			? sanitize_text_field($request['_reg_status'])
1291
+			: '';
1292
+
1293
+		/*
1294 1294
          * If filtering by registration status, then we show registrations matching that status.
1295 1295
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1296 1296
          * UNLESS viewing trashed registrations.
1297 1297
          */
1298
-        if (! empty($registration_status)) {
1299
-            $where['STS_ID'] = $registration_status;
1300
-        } else {
1301
-            //make sure we exclude incomplete registrations, but only if not trashed.
1302
-            if ($view === 'trash') {
1303
-                $where['REG_deleted'] = true;
1304
-            } elseif ($view === 'incomplete') {
1305
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1306
-            } else {
1307
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1308
-            }
1309
-        }
1310
-        return $where;
1311
-    }
1312
-
1313
-
1314
-    /**
1315
-     * Adds any provided date restraints to the where conditions for the registrations query.
1316
-     *
1317
-     * @param array $request usually the same as $this->_req_data but not necessarily
1318
-     * @return array
1319
-     * @throws EE_Error
1320
-     * @throws InvalidArgumentException
1321
-     * @throws InvalidDataTypeException
1322
-     * @throws InvalidInterfaceException
1323
-     */
1324
-    protected function _add_date_to_where_conditions(array $request)
1325
-    {
1326
-        $where = array();
1327
-        $view = EEH_Array::is_set($request, 'status', '');
1328
-        $month_range             = ! empty($request['month_range'])
1329
-            ? sanitize_text_field($request['month_range'])
1330
-            : '';
1331
-        $retrieve_for_today      = $view === 'today';
1332
-        $retrieve_for_this_month = $view === 'month';
1333
-
1334
-        if ($retrieve_for_today) {
1335
-            $now               = date('Y-m-d', current_time('timestamp'));
1336
-            $where['REG_date'] = array(
1337
-                'BETWEEN',
1338
-                array(
1339
-                    EEM_Registration::instance()->convert_datetime_for_query(
1340
-                        'REG_date',
1341
-                        $now . ' 00:00:00',
1342
-                        'Y-m-d H:i:s'
1343
-                    ),
1344
-                    EEM_Registration::instance()->convert_datetime_for_query(
1345
-                        'REG_date',
1346
-                        $now . ' 23:59:59',
1347
-                        'Y-m-d H:i:s'
1348
-                    ),
1349
-                ),
1350
-            );
1351
-        } elseif ($retrieve_for_this_month) {
1352
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1353
-            $days_this_month        = date('t', current_time('timestamp'));
1354
-            $where['REG_date']      = array(
1355
-                'BETWEEN',
1356
-                array(
1357
-                    EEM_Registration::instance()->convert_datetime_for_query(
1358
-                        'REG_date',
1359
-                        $current_year_and_month . '-01 00:00:00',
1360
-                        'Y-m-d H:i:s'
1361
-                    ),
1362
-                    EEM_Registration::instance()->convert_datetime_for_query(
1363
-                        'REG_date',
1364
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1365
-                        'Y-m-d H:i:s'
1366
-                    ),
1367
-                ),
1368
-            );
1369
-        } elseif ($month_range) {
1370
-            $pieces          = explode(' ', $month_range, 3);
1371
-            $month_requested = ! empty($pieces[0])
1372
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1373
-                : '';
1374
-            $year_requested  = ! empty($pieces[1])
1375
-                ? $pieces[1]
1376
-                : '';
1377
-            //if there is not a month or year then we can't go further
1378
-            if ($month_requested && $year_requested) {
1379
-                $days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1380
-                $where['REG_date'] = array(
1381
-                    'BETWEEN',
1382
-                    array(
1383
-                        EEM_Registration::instance()->convert_datetime_for_query(
1384
-                            'REG_date',
1385
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1386
-                            'Y-m-d H:i:s'
1387
-                        ),
1388
-                        EEM_Registration::instance()->convert_datetime_for_query(
1389
-                            'REG_date',
1390
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1391
-                            'Y-m-d H:i:s'
1392
-                        ),
1393
-                    ),
1394
-                );
1395
-            }
1396
-        }
1397
-        return $where;
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * Adds any provided search restraints to the where conditions for the registrations query
1403
-     *
1404
-     * @param array $request usually the same as $this->_req_data but not necessarily
1405
-     * @return array
1406
-     */
1407
-    protected function _add_search_to_where_conditions(array $request)
1408
-    {
1409
-        $where = array();
1410
-        if (! empty($request['s'])) {
1411
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1412
-            $where['OR*search_conditions'] = array(
1413
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1414
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1415
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1416
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1417
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1418
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1419
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1420
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1421
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1422
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1423
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1424
-                'REG_final_price'                         => array('LIKE', $search_string),
1425
-                'REG_code'                                => array('LIKE', $search_string),
1426
-                'REG_count'                               => array('LIKE', $search_string),
1427
-                'REG_group_size'                          => array('LIKE', $search_string),
1428
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1429
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1430
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1431
-            );
1432
-        }
1433
-        return $where;
1434
-    }
1435
-
1436
-
1437
-    /**
1438
-     * Sets up the where conditions for the registrations query.
1439
-     *
1440
-     * @param array $request
1441
-     * @return array
1442
-     * @throws EE_Error
1443
-     */
1444
-    protected function _get_where_conditions_for_registrations_query($request)
1445
-    {
1446
-        return apply_filters(
1447
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1448
-            array_merge(
1449
-                $this->addAttendeeIdToWhereConditions($request),
1450
-                $this->_add_event_id_to_where_conditions($request),
1451
-                $this->_add_category_id_to_where_conditions($request),
1452
-                $this->_add_datetime_id_to_where_conditions($request),
1453
-                $this->_add_registration_status_to_where_conditions($request),
1454
-                $this->_add_date_to_where_conditions($request),
1455
-                $this->_add_search_to_where_conditions($request)
1456
-            ),
1457
-            $request
1458
-        );
1459
-    }
1460
-
1461
-
1462
-    /**
1463
-     * Sets up the orderby for the registrations query.
1464
-     *
1465
-     * @return array
1466
-     */
1467
-    protected function _get_orderby_for_registrations_query()
1468
-    {
1469
-        $orderby_field = ! empty($this->_req_data['orderby'])
1470
-            ? sanitize_text_field($this->_req_data['orderby'])
1471
-            : '';
1472
-        switch ($orderby_field) {
1473
-            case '_REG_ID':
1474
-                $orderby = array('REG_ID');
1475
-                break;
1476
-            case '_Reg_status':
1477
-                $orderby = array('STS_ID');
1478
-                break;
1479
-            case 'ATT_fname':
1480
-                $orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1481
-                break;
1482
-            case 'ATT_lname':
1483
-                $orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1484
-                break;
1485
-            case 'event_name':
1486
-                $orderby = array('Event.EVT_name');
1487
-                break;
1488
-            case 'DTT_EVT_start':
1489
-                $orderby = array('Event.Datetime.DTT_EVT_start');
1490
-                break;
1491
-            default: //'REG_date'
1492
-                $orderby = array('REG_date');
1493
-        }
1494
-
1495
-        //order
1496
-        $order = ! empty($this->_req_data['order'])
1497
-            ? sanitize_text_field($this->_req_data['order'])
1498
-            : 'DESC';
1499
-        $orderby = array_combine(
1500
-            $orderby,
1501
-            array_fill(0, count($orderby), $order)
1502
-        );
1503
-        //because there are many registrations with the same date, define
1504
-        //a secondary way to order them, otherwise MySQL seems to be a bit random
1505
-        if (empty($orderby['REG_ID'])) {
1506
-            $orderby['REG_ID'] = $order;
1507
-        }
1508
-        return array('order_by' => $orderby);
1509
-    }
1510
-
1511
-
1512
-    /**
1513
-     * Sets up the limit for the registrations query.
1514
-     *
1515
-     * @param $per_page
1516
-     * @return array
1517
-     */
1518
-    protected function _get_limit($per_page)
1519
-    {
1520
-        $current_page = ! empty($this->_req_data['paged'])
1521
-            ? absint($this->_req_data['paged'])
1522
-            : 1;
1523
-        $per_page     = ! empty($this->_req_data['perpage'])
1524
-            ? $this->_req_data['perpage']
1525
-            : $per_page;
1526
-
1527
-        //-1 means return all results so get out if that's set.
1528
-        if ((int)$per_page === -1) {
1529
-            return array();
1530
-        }
1531
-        $per_page = absint($per_page);
1532
-        $offset   = ($current_page - 1) * $per_page;
1533
-        return array('limit' => array($offset, $per_page));
1534
-    }
1535
-
1536
-
1537
-    public function get_registration_status_array()
1538
-    {
1539
-        return self::$_reg_status;
1540
-    }
1541
-
1542
-
1543
-
1544
-
1545
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1546
-    /**
1547
-     *        generates HTML for the View Registration Details Admin page
1548
-     *
1549
-     * @access protected
1550
-     * @return void
1551
-     * @throws DomainException
1552
-     * @throws EE_Error
1553
-     * @throws InvalidArgumentException
1554
-     * @throws InvalidDataTypeException
1555
-     * @throws InvalidInterfaceException
1556
-     * @throws EntityNotFoundException
1557
-     */
1558
-    protected function _registration_details()
1559
-    {
1560
-        $this->_template_args = array();
1561
-        $this->_set_registration_object();
1562
-        if (is_object($this->_registration)) {
1563
-            $transaction                                   = $this->_registration->transaction()
1564
-                ? $this->_registration->transaction()
1565
-                : EE_Transaction::new_instance();
1566
-            $this->_session                                = $transaction->session_data();
1567
-            $event_id                                      = $this->_registration->event_ID();
1568
-            $this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1569
-            $this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1570
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1571
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1572
-            $this->_template_args['grand_total']           = $transaction->total();
1573
-            $this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1574
-            // link back to overview
1575
-            $this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1576
-            $this->_template_args['registration']                = $this->_registration;
1577
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1578
-                array(
1579
-                    'action'   => 'default',
1580
-                    'event_id' => $event_id,
1581
-                ),
1582
-                REG_ADMIN_URL
1583
-            );
1584
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1585
-                array(
1586
-                    'action' => 'default',
1587
-                    'EVT_ID' => $event_id,
1588
-                    'page'   => 'espresso_transactions',
1589
-                ),
1590
-                admin_url('admin.php')
1591
-            );
1592
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1593
-                array(
1594
-                    'page'   => 'espresso_events',
1595
-                    'action' => 'edit',
1596
-                    'post'   => $event_id,
1597
-                ),
1598
-                admin_url('admin.php')
1599
-            );
1600
-            //next and previous links
1601
-            $next_reg                                      = $this->_registration->next(
1602
-                null,
1603
-                array(),
1604
-                'REG_ID'
1605
-            );
1606
-            $this->_template_args['next_registration']     = $next_reg
1607
-                ? $this->_next_link(
1608
-                    EE_Admin_Page::add_query_args_and_nonce(
1609
-                        array(
1610
-                            'action'  => 'view_registration',
1611
-                            '_REG_ID' => $next_reg['REG_ID'],
1612
-                        ),
1613
-                        REG_ADMIN_URL
1614
-                    ),
1615
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1616
-                )
1617
-                : '';
1618
-            $previous_reg                                  = $this->_registration->previous(
1619
-                null,
1620
-                array(),
1621
-                'REG_ID'
1622
-            );
1623
-            $this->_template_args['previous_registration'] = $previous_reg
1624
-                ? $this->_previous_link(
1625
-                    EE_Admin_Page::add_query_args_and_nonce(
1626
-                        array(
1627
-                            'action'  => 'view_registration',
1628
-                            '_REG_ID' => $previous_reg['REG_ID'],
1629
-                        ),
1630
-                        REG_ADMIN_URL
1631
-                    ),
1632
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1633
-                )
1634
-                : '';
1635
-            // grab header
1636
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1637
-            $this->_template_args['REG_ID']            = $this->_registration->ID();
1638
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1639
-                $template_path,
1640
-                $this->_template_args,
1641
-                true
1642
-            );
1643
-        } else {
1644
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1645
-        }
1646
-        // the details template wrapper
1647
-        $this->display_admin_page_with_sidebar();
1648
-    }
1649
-
1650
-
1651
-    protected function _registration_details_metaboxes()
1652
-    {
1653
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1654
-        $this->_set_registration_object();
1655
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1656
-        add_meta_box('edit-reg-status-mbox', esc_html__('Registration Status', 'event_espresso'),
1657
-            array($this, 'set_reg_status_buttons_metabox'), $this->wp_page_slug, 'normal', 'high');
1658
-        add_meta_box('edit-reg-details-mbox', esc_html__('Registration Details', 'event_espresso'),
1659
-            array($this, '_reg_details_meta_box'), $this->wp_page_slug, 'normal', 'high');
1660
-        if ($attendee instanceof EE_Attendee
1661
-            && EE_Registry::instance()->CAP->current_user_can(
1662
-                'ee_edit_registration',
1663
-                'edit-reg-questions-mbox',
1664
-                $this->_registration->ID()
1665
-            )
1666
-        ) {
1667
-            add_meta_box(
1668
-                'edit-reg-questions-mbox',
1669
-                esc_html__('Registration Form Answers', 'event_espresso'),
1670
-                array($this, '_reg_questions_meta_box'),
1671
-                $this->wp_page_slug,
1672
-                'normal',
1673
-                'high'
1674
-            );
1675
-        }
1676
-        add_meta_box(
1677
-            'edit-reg-registrant-mbox',
1678
-            esc_html__('Contact Details', 'event_espresso'),
1679
-            array($this, '_reg_registrant_side_meta_box'),
1680
-            $this->wp_page_slug,
1681
-            'side',
1682
-            'high'
1683
-        );
1684
-        if ($this->_registration->group_size() > 1) {
1685
-            add_meta_box(
1686
-                'edit-reg-attendees-mbox',
1687
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1688
-                array($this, '_reg_attendees_meta_box'),
1689
-                $this->wp_page_slug,
1690
-                'normal',
1691
-                'high'
1692
-            );
1693
-        }
1694
-    }
1695
-
1696
-
1697
-    /**
1698
-     * set_reg_status_buttons_metabox
1699
-     *
1700
-     * @access protected
1701
-     * @return string
1702
-     * @throws \EE_Error
1703
-     */
1704
-    public function set_reg_status_buttons_metabox()
1705
-    {
1706
-        $this->_set_registration_object();
1707
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1708
-        echo $change_reg_status_form->form_open(
1709
-            self::add_query_args_and_nonce(
1710
-                array(
1711
-                    'action' => 'change_reg_status',
1712
-                ),
1713
-                REG_ADMIN_URL
1714
-            )
1715
-        );
1716
-        echo $change_reg_status_form->get_html();
1717
-        echo $change_reg_status_form->form_close();
1718
-    }
1719
-
1720
-
1721
-    /**
1722
-     * @return EE_Form_Section_Proper
1723
-     * @throws EE_Error
1724
-     * @throws InvalidArgumentException
1725
-     * @throws InvalidDataTypeException
1726
-     * @throws InvalidInterfaceException
1727
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1728
-     */
1729
-    protected function _generate_reg_status_change_form()
1730
-    {
1731
-        return new EE_Form_Section_Proper(array(
1732
-            'name'            => 'reg_status_change_form',
1733
-            'html_id'         => 'reg-status-change-form',
1734
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1735
-            'subsections'     => array(
1736
-                'return'             => new EE_Hidden_Input(array(
1737
-                    'name'    => 'return',
1738
-                    'default' => 'view_registration',
1739
-                )),
1740
-                'REG_ID'             => new EE_Hidden_Input(array(
1741
-                    'name'    => 'REG_ID',
1742
-                    'default' => $this->_registration->ID(),
1743
-                )),
1744
-                'current_status'     => new EE_Form_Section_HTML(
1745
-                    EEH_HTML::tr(
1746
-                        EEH_HTML::th(
1747
-                            EEH_HTML::label(
1748
-                                EEH_HTML::strong(esc_html__('Current Registration Status', 'event_espresso')
1749
-                                )
1750
-                            )
1751
-                        )
1752
-                        . EEH_HTML::td(
1753
-                            EEH_HTML::strong(
1754
-                                $this->_registration->pretty_status(),
1755
-                                '',
1756
-                                'status-' . $this->_registration->status_ID(),
1757
-                                'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1758
-                            )
1759
-                        )
1760
-                    )
1761
-                ),
1762
-                'reg_status'         => new EE_Select_Input(
1763
-                    $this->_get_reg_statuses(),
1764
-                    array(
1765
-                        'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1766
-                        'default'         => $this->_registration->status_ID(),
1767
-                    )
1768
-                ),
1769
-                'send_notifications' => new EE_Yes_No_Input(
1770
-                    array(
1771
-                        'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1772
-                        'default'         => false,
1773
-                        'html_help_text'  => esc_html__(
1774
-                            'If set to "Yes", then the related messages will be sent to the registrant.',
1775
-                            'event_espresso'
1776
-                        ),
1777
-                    )
1778
-                ),
1779
-                'submit'             => new EE_Submit_Input(
1780
-                    array(
1781
-                        'html_class'      => 'button-primary',
1782
-                        'html_label_text' => '&nbsp;',
1783
-                        'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1784
-                    )
1785
-                ),
1786
-            ),
1787
-        ));
1788
-    }
1789
-
1790
-
1791
-    /**
1792
-     * Returns an array of all the buttons for the various statuses and switch status actions
1793
-     *
1794
-     * @return array
1795
-     * @throws EE_Error
1796
-     * @throws InvalidArgumentException
1797
-     * @throws InvalidDataTypeException
1798
-     * @throws InvalidInterfaceException
1799
-     * @throws EntityNotFoundException
1800
-     */
1801
-    protected function _get_reg_statuses()
1802
-    {
1803
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1804
-        unset ($reg_status_array[EEM_Registration::status_id_incomplete]);
1805
-        // get current reg status
1806
-        $current_status = $this->_registration->status_ID();
1807
-        // is registration for free event? This will determine whether to display the pending payment option
1808
-        if (
1809
-            $current_status !== EEM_Registration::status_id_pending_payment
1810
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1811
-        ) {
1812
-            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1813
-        }
1814
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1815
-    }
1816
-
1817
-
1818
-    /**
1819
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1820
-     *
1821
-     * @param bool $status REG status given for changing registrations to.
1822
-     * @param bool $notify Whether to send messages notifications or not.
1823
-     * @return array (array with reg_id(s) updated and whether update was successful.
1824
-     * @throws EE_Error
1825
-     * @throws InvalidArgumentException
1826
-     * @throws InvalidDataTypeException
1827
-     * @throws InvalidInterfaceException
1828
-     * @throws ReflectionException
1829
-     * @throws RuntimeException
1830
-     * @throws EntityNotFoundException
1831
-     */
1832
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1833
-    {
1834
-        if (isset($this->_req_data['reg_status_change_form'])) {
1835
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1836
-                ? (array)$this->_req_data['reg_status_change_form']['REG_ID']
1837
-                : array();
1838
-        } else {
1839
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1840
-                ? (array)$this->_req_data['_REG_ID']
1841
-                : array();
1842
-        }
1843
-        // sanitize $REG_IDs
1844
-        $REG_IDs = array_map('absint', $REG_IDs);
1845
-        // and remove empty entries
1846
-        $REG_IDs = array_filter($REG_IDs);
1847
-
1848
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1849
-
1850
-        /**
1851
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1852
-         * Currently this value is used downstream by the _process_resend_registration method.
1853
-         *
1854
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1855
-         * @param bool                     $status           The status registrations were changed to.
1856
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1857
-         * @param Registrations_Admin_Page $admin_page_object
1858
-         */
1859
-        $this->_req_data['_REG_ID'] = apply_filters(
1860
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1861
-            $result['REG_ID'],
1862
-            $status,
1863
-            $result['success'],
1864
-            $this
1865
-        );
1866
-
1867
-        //notify?
1868
-        if ($notify
1869
-            && $result['success']
1870
-            && ! empty($this->_req_data['_REG_ID'])
1871
-            && EE_Registry::instance()->CAP->current_user_can(
1872
-                'ee_send_message',
1873
-                'espresso_registrations_resend_registration'
1874
-            )
1875
-        ) {
1876
-            $this->_process_resend_registration();
1877
-        }
1878
-        return $result;
1879
-    }
1880
-
1881
-
1882
-    /**
1883
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1884
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1885
-     *
1886
-     * @param array  $REG_IDs
1887
-     * @param string $status
1888
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1889
-     *                        slug sent with setting the registration status.
1890
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1891
-     * @throws EE_Error
1892
-     * @throws InvalidArgumentException
1893
-     * @throws InvalidDataTypeException
1894
-     * @throws InvalidInterfaceException
1895
-     * @throws ReflectionException
1896
-     * @throws RuntimeException
1897
-     * @throws EntityNotFoundException
1898
-     */
1899
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1900
-    {
1901
-        $success = false;
1902
-        // typecast $REG_IDs
1903
-        $REG_IDs = (array)$REG_IDs;
1904
-        if ( ! empty($REG_IDs)) {
1905
-            $success = true;
1906
-            // set default status if none is passed
1907
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1908
-            $status_context = $notify
1909
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1910
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1911
-            //loop through REG_ID's and change status
1912
-            foreach ($REG_IDs as $REG_ID) {
1913
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1914
-                if ($registration instanceof EE_Registration) {
1915
-                    $registration->set_status(
1916
-                        $status,
1917
-                        false,
1918
-                        new Context(
1919
-                            $status_context,
1920
-                            esc_html__(
1921
-                                'Manually triggered status change on a Registration Admin Page route.',
1922
-                                'event_espresso'
1923
-                            )
1924
-                        )
1925
-                    );
1926
-                    $result = $registration->save();
1927
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1928
-                    $success = $result !== false ? $success : false;
1929
-                }
1930
-            }
1931
-        }
1932
-
1933
-        //return $success and processed registrations
1934
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1935
-    }
1936
-
1937
-
1938
-    /**
1939
-     * Common logic for setting up success message and redirecting to appropriate route
1940
-     *
1941
-     * @param  string $STS_ID status id for the registration changed to
1942
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1943
-     * @return void
1944
-     * @throws EE_Error
1945
-     */
1946
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1947
-    {
1948
-        $result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1949
-            : array('success' => false);
1950
-        $success = isset($result['success']) && $result['success'];
1951
-        //setup success message
1952
-        if ($success) {
1953
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1954
-                $msg = sprintf(esc_html__('Registration status has been set to %s', 'event_espresso'),
1955
-                    EEH_Template::pretty_status($STS_ID, false, 'lower'));
1956
-            } else {
1957
-                $msg = sprintf(esc_html__('Registrations have been set to %s.', 'event_espresso'),
1958
-                    EEH_Template::pretty_status($STS_ID, false, 'lower'));
1959
-            }
1960
-            EE_Error::add_success($msg);
1961
-        } else {
1962
-            EE_Error::add_error(
1963
-                esc_html__(
1964
-                    'Something went wrong, and the status was not changed',
1965
-                    'event_espresso'
1966
-                ), __FILE__, __LINE__, __FUNCTION__
1967
-            );
1968
-        }
1969
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1970
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1971
-        } else {
1972
-            $route = array('action' => 'default');
1973
-        }
1974
-        //unset nonces
1975
-        foreach ($this->_req_data as $ref => $value) {
1976
-            if (strpos($ref, 'nonce') !== false) {
1977
-                unset($this->_req_data[$ref]);
1978
-                continue;
1979
-            }
1980
-            $value                 = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
1981
-            $this->_req_data[$ref] = $value;
1982
-        }
1983
-        //merge request vars so that the reloaded list table contains any existing filter query params
1984
-        $route = array_merge($this->_req_data, $route);
1985
-        $this->_redirect_after_action($success, '', '', $route, true);
1986
-    }
1987
-
1988
-
1989
-    /**
1990
-     * incoming reg status change from reg details page.
1991
-     *
1992
-     * @return void
1993
-     */
1994
-    protected function _change_reg_status()
1995
-    {
1996
-        $this->_req_data['return'] = 'view_registration';
1997
-        //set notify based on whether the send notifications toggle is set or not
1998
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1999
-        //$notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2000
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2001
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2002
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2003
-            case EEM_Registration::status_id_approved :
2004
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence') :
2005
-                $this->approve_registration($notify);
2006
-                break;
2007
-            case EEM_Registration::status_id_pending_payment :
2008
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence') :
2009
-                $this->pending_registration($notify);
2010
-                break;
2011
-            case EEM_Registration::status_id_not_approved :
2012
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence') :
2013
-                $this->not_approve_registration($notify);
2014
-                break;
2015
-            case EEM_Registration::status_id_declined :
2016
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence') :
2017
-                $this->decline_registration($notify);
2018
-                break;
2019
-            case EEM_Registration::status_id_cancelled :
2020
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence') :
2021
-                $this->cancel_registration($notify);
2022
-                break;
2023
-            case EEM_Registration::status_id_wait_list :
2024
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence') :
2025
-                $this->wait_list_registration($notify);
2026
-                break;
2027
-            case EEM_Registration::status_id_incomplete :
2028
-            default :
2029
-                $result['success'] = false;
2030
-                unset($this->_req_data['return']);
2031
-                $this->_reg_status_change_return('', false);
2032
-                break;
2033
-        }
2034
-    }
2035
-
2036
-
2037
-    /**
2038
-     * Callback for bulk action routes.
2039
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2040
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
2041
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2042
-     * when an action is happening on just a single registration).
2043
-     * @param      $action
2044
-     * @param bool $notify
2045
-     */
2046
-    protected function bulk_action_on_registrations($action, $notify = false) {
2047
-        do_action(
2048
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2049
-            $this,
2050
-            $action,
2051
-            $notify
2052
-        );
2053
-        $method = $action . '_registration';
2054
-        if (method_exists($this, $method)) {
2055
-            $this->$method($notify);
2056
-        }
2057
-    }
2058
-
2059
-
2060
-    /**
2061
-     * approve_registration
2062
-     *
2063
-     * @access protected
2064
-     * @param bool $notify whether or not to notify the registrant about their approval.
2065
-     * @return void
2066
-     */
2067
-    protected function approve_registration($notify = false)
2068
-    {
2069
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2070
-    }
2071
-
2072
-
2073
-    /**
2074
-     *        decline_registration
2075
-     *
2076
-     * @access protected
2077
-     * @param bool $notify whether or not to notify the registrant about their status change.
2078
-     * @return void
2079
-     */
2080
-    protected function decline_registration($notify = false)
2081
-    {
2082
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2083
-    }
2084
-
2085
-
2086
-    /**
2087
-     *        cancel_registration
2088
-     *
2089
-     * @access protected
2090
-     * @param bool $notify whether or not to notify the registrant about their status change.
2091
-     * @return void
2092
-     */
2093
-    protected function cancel_registration($notify = false)
2094
-    {
2095
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2096
-    }
2097
-
2098
-
2099
-    /**
2100
-     *        not_approve_registration
2101
-     *
2102
-     * @access protected
2103
-     * @param bool $notify whether or not to notify the registrant about their status change.
2104
-     * @return void
2105
-     */
2106
-    protected function not_approve_registration($notify = false)
2107
-    {
2108
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2109
-    }
2110
-
2111
-
2112
-    /**
2113
-     *        decline_registration
2114
-     *
2115
-     * @access protected
2116
-     * @param bool $notify whether or not to notify the registrant about their status change.
2117
-     * @return void
2118
-     */
2119
-    protected function pending_registration($notify = false)
2120
-    {
2121
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2122
-    }
2123
-
2124
-
2125
-    /**
2126
-     * waitlist_registration
2127
-     *
2128
-     * @access protected
2129
-     * @param bool $notify whether or not to notify the registrant about their status change.
2130
-     * @return void
2131
-     */
2132
-    protected function wait_list_registration($notify = false)
2133
-    {
2134
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2135
-    }
2136
-
2137
-
2138
-    /**
2139
-     *        generates HTML for the Registration main meta box
2140
-     *
2141
-     * @access public
2142
-     * @return void
2143
-     * @throws DomainException
2144
-     * @throws EE_Error
2145
-     * @throws InvalidArgumentException
2146
-     * @throws InvalidDataTypeException
2147
-     * @throws InvalidInterfaceException
2148
-     * @throws ReflectionException
2149
-     * @throws EntityNotFoundException
2150
-     */
2151
-    public function _reg_details_meta_box()
2152
-    {
2153
-        EEH_Autoloader::register_line_item_display_autoloaders();
2154
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2155
-        EE_Registry::instance()->load_helper('Line_Item');
2156
-        $transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
2157
-            : EE_Transaction::new_instance();
2158
-        $this->_session = $transaction->session_data();
2159
-        $filters        = new EE_Line_Item_Filter_Collection();
2160
-        //$filters->add( new EE_Non_Zero_Line_Item_Filter() );
2161
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2162
-        $line_item_filter_processor              = new EE_Line_Item_Filter_Processor($filters,
2163
-            $transaction->total_line_item());
2164
-        $filtered_line_item_tree                 = $line_item_filter_processor->process();
2165
-        $line_item_display                       = new EE_Line_Item_Display('reg_admin_table',
2166
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy');
2167
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2168
-            $filtered_line_item_tree,
2169
-            array('EE_Registration' => $this->_registration)
2170
-        );
2171
-        $attendee                                = $this->_registration->attendee();
2172
-        if (EE_Registry::instance()->CAP->current_user_can(
2173
-            'ee_read_transaction',
2174
-            'espresso_transactions_view_transaction'
2175
-        )) {
2176
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2177
-                EE_Admin_Page::add_query_args_and_nonce(
2178
-                    array(
2179
-                        'action' => 'view_transaction',
2180
-                        'TXN_ID' => $transaction->ID(),
2181
-                    ),
2182
-                    TXN_ADMIN_URL
2183
-                ),
2184
-                esc_html__(' View Transaction', 'event_espresso'),
2185
-                'button secondary-button right',
2186
-                'dashicons dashicons-cart'
2187
-            );
2188
-        } else {
2189
-            $this->_template_args['view_transaction_button'] = '';
2190
-        }
2191
-        if ($attendee instanceof EE_Attendee
2192
-            && EE_Registry::instance()->CAP->current_user_can(
2193
-                'ee_send_message',
2194
-                'espresso_registrations_resend_registration'
2195
-            )
2196
-        ) {
2197
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2198
-                EE_Admin_Page::add_query_args_and_nonce(
2199
-                    array(
2200
-                        'action'      => 'resend_registration',
2201
-                        '_REG_ID'     => $this->_registration->ID(),
2202
-                        'redirect_to' => 'view_registration',
2203
-                    ),
2204
-                    REG_ADMIN_URL
2205
-                ),
2206
-                esc_html__(' Resend Registration', 'event_espresso'),
2207
-                'button secondary-button right',
2208
-                'dashicons dashicons-email-alt'
2209
-            );
2210
-        } else {
2211
-            $this->_template_args['resend_registration_button'] = '';
2212
-        }
2213
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2214
-        $payment                               = $transaction->get_first_related('Payment');
2215
-        $payment                               = ! $payment instanceof EE_Payment
2216
-            ? EE_Payment::new_instance()
2217
-            : $payment;
2218
-        $payment_method                        = $payment->get_first_related('Payment_Method');
2219
-        $payment_method                        = ! $payment_method instanceof EE_Payment_Method
2220
-            ? EE_Payment_Method::new_instance()
2221
-            : $payment_method;
2222
-        $reg_details                           = array(
2223
-            'payment_method'       => $payment_method->name(),
2224
-            'response_msg'         => $payment->gateway_response(),
2225
-            'registration_id'      => $this->_registration->get('REG_code'),
2226
-            'registration_session' => $this->_registration->session_ID(),
2227
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2228
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2229
-        );
2230
-        if (isset($reg_details['registration_id'])) {
2231
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2232
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2233
-                'Registration ID',
2234
-                'event_espresso'
2235
-            );
2236
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2237
-        }
2238
-        if (isset($reg_details['payment_method'])) {
2239
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2240
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2241
-                'Most Recent Payment Method',
2242
-                'event_espresso'
2243
-            );
2244
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2245
-            $this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2246
-            $this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2247
-                'Payment method response',
2248
-                'event_espresso'
2249
-            );
2250
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2251
-        }
2252
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2253
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2254
-            'Registration Session',
2255
-            'event_espresso'
2256
-        );
2257
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2258
-        $this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2259
-        $this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2260
-            'Registration placed from IP',
2261
-            'event_espresso'
2262
-        );
2263
-        $this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2264
-        $this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2265
-        $this->_template_args['reg_details']['user_agent']['label']           = esc_html__('Registrant User Agent',
2266
-            'event_espresso');
2267
-        $this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2268
-        $this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2269
-            array(
2270
-                'action'   => 'default',
2271
-                'event_id' => $this->_registration->event_ID(),
2272
-            ),
2273
-            REG_ADMIN_URL
2274
-        );
2275
-        $this->_template_args['REG_ID']                                       = $this->_registration->ID();
2276
-        $this->_template_args['event_id']                                     = $this->_registration->event_ID();
2277
-        $template_path                                                        =
2278
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2279
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2280
-    }
2281
-
2282
-
2283
-    /**
2284
-     * generates HTML for the Registration Questions meta box.
2285
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2286
-     * otherwise uses new forms system
2287
-     *
2288
-     * @access public
2289
-     * @return void
2290
-     * @throws DomainException
2291
-     * @throws EE_Error
2292
-     */
2293
-    public function _reg_questions_meta_box()
2294
-    {
2295
-        //allow someone to override this method entirely
2296
-        if (apply_filters('FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default', true, $this,
2297
-            $this->_registration)) {
2298
-            $form                                              = $this->_get_reg_custom_questions_form(
2299
-                $this->_registration->ID()
2300
-            );
2301
-            $this->_template_args['att_questions']             = count($form->subforms()) > 0
2302
-                ? $form->get_html_and_js()
2303
-                : '';
2304
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2305
-            $this->_template_args['REG_ID']                    = $this->_registration->ID();
2306
-            $template_path                                     =
2307
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2308
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2309
-        }
2310
-    }
2311
-
2312
-
2313
-    /**
2314
-     * form_before_question_group
2315
-     *
2316
-     * @deprecated    as of 4.8.32.rc.000
2317
-     * @access        public
2318
-     * @param        string $output
2319
-     * @return        string
2320
-     */
2321
-    public function form_before_question_group($output)
2322
-    {
2323
-        EE_Error::doing_it_wrong(
2324
-            __CLASS__ . '::' . __FUNCTION__,
2325
-            esc_html__(
2326
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2327
-                'event_espresso'
2328
-            ),
2329
-            '4.8.32.rc.000'
2330
-        );
2331
-        return '
1298
+		if (! empty($registration_status)) {
1299
+			$where['STS_ID'] = $registration_status;
1300
+		} else {
1301
+			//make sure we exclude incomplete registrations, but only if not trashed.
1302
+			if ($view === 'trash') {
1303
+				$where['REG_deleted'] = true;
1304
+			} elseif ($view === 'incomplete') {
1305
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1306
+			} else {
1307
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1308
+			}
1309
+		}
1310
+		return $where;
1311
+	}
1312
+
1313
+
1314
+	/**
1315
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1316
+	 *
1317
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1318
+	 * @return array
1319
+	 * @throws EE_Error
1320
+	 * @throws InvalidArgumentException
1321
+	 * @throws InvalidDataTypeException
1322
+	 * @throws InvalidInterfaceException
1323
+	 */
1324
+	protected function _add_date_to_where_conditions(array $request)
1325
+	{
1326
+		$where = array();
1327
+		$view = EEH_Array::is_set($request, 'status', '');
1328
+		$month_range             = ! empty($request['month_range'])
1329
+			? sanitize_text_field($request['month_range'])
1330
+			: '';
1331
+		$retrieve_for_today      = $view === 'today';
1332
+		$retrieve_for_this_month = $view === 'month';
1333
+
1334
+		if ($retrieve_for_today) {
1335
+			$now               = date('Y-m-d', current_time('timestamp'));
1336
+			$where['REG_date'] = array(
1337
+				'BETWEEN',
1338
+				array(
1339
+					EEM_Registration::instance()->convert_datetime_for_query(
1340
+						'REG_date',
1341
+						$now . ' 00:00:00',
1342
+						'Y-m-d H:i:s'
1343
+					),
1344
+					EEM_Registration::instance()->convert_datetime_for_query(
1345
+						'REG_date',
1346
+						$now . ' 23:59:59',
1347
+						'Y-m-d H:i:s'
1348
+					),
1349
+				),
1350
+			);
1351
+		} elseif ($retrieve_for_this_month) {
1352
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1353
+			$days_this_month        = date('t', current_time('timestamp'));
1354
+			$where['REG_date']      = array(
1355
+				'BETWEEN',
1356
+				array(
1357
+					EEM_Registration::instance()->convert_datetime_for_query(
1358
+						'REG_date',
1359
+						$current_year_and_month . '-01 00:00:00',
1360
+						'Y-m-d H:i:s'
1361
+					),
1362
+					EEM_Registration::instance()->convert_datetime_for_query(
1363
+						'REG_date',
1364
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1365
+						'Y-m-d H:i:s'
1366
+					),
1367
+				),
1368
+			);
1369
+		} elseif ($month_range) {
1370
+			$pieces          = explode(' ', $month_range, 3);
1371
+			$month_requested = ! empty($pieces[0])
1372
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1373
+				: '';
1374
+			$year_requested  = ! empty($pieces[1])
1375
+				? $pieces[1]
1376
+				: '';
1377
+			//if there is not a month or year then we can't go further
1378
+			if ($month_requested && $year_requested) {
1379
+				$days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1380
+				$where['REG_date'] = array(
1381
+					'BETWEEN',
1382
+					array(
1383
+						EEM_Registration::instance()->convert_datetime_for_query(
1384
+							'REG_date',
1385
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1386
+							'Y-m-d H:i:s'
1387
+						),
1388
+						EEM_Registration::instance()->convert_datetime_for_query(
1389
+							'REG_date',
1390
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1391
+							'Y-m-d H:i:s'
1392
+						),
1393
+					),
1394
+				);
1395
+			}
1396
+		}
1397
+		return $where;
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * Adds any provided search restraints to the where conditions for the registrations query
1403
+	 *
1404
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1405
+	 * @return array
1406
+	 */
1407
+	protected function _add_search_to_where_conditions(array $request)
1408
+	{
1409
+		$where = array();
1410
+		if (! empty($request['s'])) {
1411
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1412
+			$where['OR*search_conditions'] = array(
1413
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1414
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1415
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1416
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1417
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1418
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1419
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1420
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1421
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1422
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1423
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1424
+				'REG_final_price'                         => array('LIKE', $search_string),
1425
+				'REG_code'                                => array('LIKE', $search_string),
1426
+				'REG_count'                               => array('LIKE', $search_string),
1427
+				'REG_group_size'                          => array('LIKE', $search_string),
1428
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1429
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1430
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1431
+			);
1432
+		}
1433
+		return $where;
1434
+	}
1435
+
1436
+
1437
+	/**
1438
+	 * Sets up the where conditions for the registrations query.
1439
+	 *
1440
+	 * @param array $request
1441
+	 * @return array
1442
+	 * @throws EE_Error
1443
+	 */
1444
+	protected function _get_where_conditions_for_registrations_query($request)
1445
+	{
1446
+		return apply_filters(
1447
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1448
+			array_merge(
1449
+				$this->addAttendeeIdToWhereConditions($request),
1450
+				$this->_add_event_id_to_where_conditions($request),
1451
+				$this->_add_category_id_to_where_conditions($request),
1452
+				$this->_add_datetime_id_to_where_conditions($request),
1453
+				$this->_add_registration_status_to_where_conditions($request),
1454
+				$this->_add_date_to_where_conditions($request),
1455
+				$this->_add_search_to_where_conditions($request)
1456
+			),
1457
+			$request
1458
+		);
1459
+	}
1460
+
1461
+
1462
+	/**
1463
+	 * Sets up the orderby for the registrations query.
1464
+	 *
1465
+	 * @return array
1466
+	 */
1467
+	protected function _get_orderby_for_registrations_query()
1468
+	{
1469
+		$orderby_field = ! empty($this->_req_data['orderby'])
1470
+			? sanitize_text_field($this->_req_data['orderby'])
1471
+			: '';
1472
+		switch ($orderby_field) {
1473
+			case '_REG_ID':
1474
+				$orderby = array('REG_ID');
1475
+				break;
1476
+			case '_Reg_status':
1477
+				$orderby = array('STS_ID');
1478
+				break;
1479
+			case 'ATT_fname':
1480
+				$orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1481
+				break;
1482
+			case 'ATT_lname':
1483
+				$orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1484
+				break;
1485
+			case 'event_name':
1486
+				$orderby = array('Event.EVT_name');
1487
+				break;
1488
+			case 'DTT_EVT_start':
1489
+				$orderby = array('Event.Datetime.DTT_EVT_start');
1490
+				break;
1491
+			default: //'REG_date'
1492
+				$orderby = array('REG_date');
1493
+		}
1494
+
1495
+		//order
1496
+		$order = ! empty($this->_req_data['order'])
1497
+			? sanitize_text_field($this->_req_data['order'])
1498
+			: 'DESC';
1499
+		$orderby = array_combine(
1500
+			$orderby,
1501
+			array_fill(0, count($orderby), $order)
1502
+		);
1503
+		//because there are many registrations with the same date, define
1504
+		//a secondary way to order them, otherwise MySQL seems to be a bit random
1505
+		if (empty($orderby['REG_ID'])) {
1506
+			$orderby['REG_ID'] = $order;
1507
+		}
1508
+		return array('order_by' => $orderby);
1509
+	}
1510
+
1511
+
1512
+	/**
1513
+	 * Sets up the limit for the registrations query.
1514
+	 *
1515
+	 * @param $per_page
1516
+	 * @return array
1517
+	 */
1518
+	protected function _get_limit($per_page)
1519
+	{
1520
+		$current_page = ! empty($this->_req_data['paged'])
1521
+			? absint($this->_req_data['paged'])
1522
+			: 1;
1523
+		$per_page     = ! empty($this->_req_data['perpage'])
1524
+			? $this->_req_data['perpage']
1525
+			: $per_page;
1526
+
1527
+		//-1 means return all results so get out if that's set.
1528
+		if ((int)$per_page === -1) {
1529
+			return array();
1530
+		}
1531
+		$per_page = absint($per_page);
1532
+		$offset   = ($current_page - 1) * $per_page;
1533
+		return array('limit' => array($offset, $per_page));
1534
+	}
1535
+
1536
+
1537
+	public function get_registration_status_array()
1538
+	{
1539
+		return self::$_reg_status;
1540
+	}
1541
+
1542
+
1543
+
1544
+
1545
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1546
+	/**
1547
+	 *        generates HTML for the View Registration Details Admin page
1548
+	 *
1549
+	 * @access protected
1550
+	 * @return void
1551
+	 * @throws DomainException
1552
+	 * @throws EE_Error
1553
+	 * @throws InvalidArgumentException
1554
+	 * @throws InvalidDataTypeException
1555
+	 * @throws InvalidInterfaceException
1556
+	 * @throws EntityNotFoundException
1557
+	 */
1558
+	protected function _registration_details()
1559
+	{
1560
+		$this->_template_args = array();
1561
+		$this->_set_registration_object();
1562
+		if (is_object($this->_registration)) {
1563
+			$transaction                                   = $this->_registration->transaction()
1564
+				? $this->_registration->transaction()
1565
+				: EE_Transaction::new_instance();
1566
+			$this->_session                                = $transaction->session_data();
1567
+			$event_id                                      = $this->_registration->event_ID();
1568
+			$this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1569
+			$this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1570
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1571
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1572
+			$this->_template_args['grand_total']           = $transaction->total();
1573
+			$this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1574
+			// link back to overview
1575
+			$this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1576
+			$this->_template_args['registration']                = $this->_registration;
1577
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1578
+				array(
1579
+					'action'   => 'default',
1580
+					'event_id' => $event_id,
1581
+				),
1582
+				REG_ADMIN_URL
1583
+			);
1584
+			$this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1585
+				array(
1586
+					'action' => 'default',
1587
+					'EVT_ID' => $event_id,
1588
+					'page'   => 'espresso_transactions',
1589
+				),
1590
+				admin_url('admin.php')
1591
+			);
1592
+			$this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1593
+				array(
1594
+					'page'   => 'espresso_events',
1595
+					'action' => 'edit',
1596
+					'post'   => $event_id,
1597
+				),
1598
+				admin_url('admin.php')
1599
+			);
1600
+			//next and previous links
1601
+			$next_reg                                      = $this->_registration->next(
1602
+				null,
1603
+				array(),
1604
+				'REG_ID'
1605
+			);
1606
+			$this->_template_args['next_registration']     = $next_reg
1607
+				? $this->_next_link(
1608
+					EE_Admin_Page::add_query_args_and_nonce(
1609
+						array(
1610
+							'action'  => 'view_registration',
1611
+							'_REG_ID' => $next_reg['REG_ID'],
1612
+						),
1613
+						REG_ADMIN_URL
1614
+					),
1615
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1616
+				)
1617
+				: '';
1618
+			$previous_reg                                  = $this->_registration->previous(
1619
+				null,
1620
+				array(),
1621
+				'REG_ID'
1622
+			);
1623
+			$this->_template_args['previous_registration'] = $previous_reg
1624
+				? $this->_previous_link(
1625
+					EE_Admin_Page::add_query_args_and_nonce(
1626
+						array(
1627
+							'action'  => 'view_registration',
1628
+							'_REG_ID' => $previous_reg['REG_ID'],
1629
+						),
1630
+						REG_ADMIN_URL
1631
+					),
1632
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1633
+				)
1634
+				: '';
1635
+			// grab header
1636
+			$template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1637
+			$this->_template_args['REG_ID']            = $this->_registration->ID();
1638
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1639
+				$template_path,
1640
+				$this->_template_args,
1641
+				true
1642
+			);
1643
+		} else {
1644
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1645
+		}
1646
+		// the details template wrapper
1647
+		$this->display_admin_page_with_sidebar();
1648
+	}
1649
+
1650
+
1651
+	protected function _registration_details_metaboxes()
1652
+	{
1653
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1654
+		$this->_set_registration_object();
1655
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1656
+		add_meta_box('edit-reg-status-mbox', esc_html__('Registration Status', 'event_espresso'),
1657
+			array($this, 'set_reg_status_buttons_metabox'), $this->wp_page_slug, 'normal', 'high');
1658
+		add_meta_box('edit-reg-details-mbox', esc_html__('Registration Details', 'event_espresso'),
1659
+			array($this, '_reg_details_meta_box'), $this->wp_page_slug, 'normal', 'high');
1660
+		if ($attendee instanceof EE_Attendee
1661
+			&& EE_Registry::instance()->CAP->current_user_can(
1662
+				'ee_edit_registration',
1663
+				'edit-reg-questions-mbox',
1664
+				$this->_registration->ID()
1665
+			)
1666
+		) {
1667
+			add_meta_box(
1668
+				'edit-reg-questions-mbox',
1669
+				esc_html__('Registration Form Answers', 'event_espresso'),
1670
+				array($this, '_reg_questions_meta_box'),
1671
+				$this->wp_page_slug,
1672
+				'normal',
1673
+				'high'
1674
+			);
1675
+		}
1676
+		add_meta_box(
1677
+			'edit-reg-registrant-mbox',
1678
+			esc_html__('Contact Details', 'event_espresso'),
1679
+			array($this, '_reg_registrant_side_meta_box'),
1680
+			$this->wp_page_slug,
1681
+			'side',
1682
+			'high'
1683
+		);
1684
+		if ($this->_registration->group_size() > 1) {
1685
+			add_meta_box(
1686
+				'edit-reg-attendees-mbox',
1687
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1688
+				array($this, '_reg_attendees_meta_box'),
1689
+				$this->wp_page_slug,
1690
+				'normal',
1691
+				'high'
1692
+			);
1693
+		}
1694
+	}
1695
+
1696
+
1697
+	/**
1698
+	 * set_reg_status_buttons_metabox
1699
+	 *
1700
+	 * @access protected
1701
+	 * @return string
1702
+	 * @throws \EE_Error
1703
+	 */
1704
+	public function set_reg_status_buttons_metabox()
1705
+	{
1706
+		$this->_set_registration_object();
1707
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1708
+		echo $change_reg_status_form->form_open(
1709
+			self::add_query_args_and_nonce(
1710
+				array(
1711
+					'action' => 'change_reg_status',
1712
+				),
1713
+				REG_ADMIN_URL
1714
+			)
1715
+		);
1716
+		echo $change_reg_status_form->get_html();
1717
+		echo $change_reg_status_form->form_close();
1718
+	}
1719
+
1720
+
1721
+	/**
1722
+	 * @return EE_Form_Section_Proper
1723
+	 * @throws EE_Error
1724
+	 * @throws InvalidArgumentException
1725
+	 * @throws InvalidDataTypeException
1726
+	 * @throws InvalidInterfaceException
1727
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1728
+	 */
1729
+	protected function _generate_reg_status_change_form()
1730
+	{
1731
+		return new EE_Form_Section_Proper(array(
1732
+			'name'            => 'reg_status_change_form',
1733
+			'html_id'         => 'reg-status-change-form',
1734
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1735
+			'subsections'     => array(
1736
+				'return'             => new EE_Hidden_Input(array(
1737
+					'name'    => 'return',
1738
+					'default' => 'view_registration',
1739
+				)),
1740
+				'REG_ID'             => new EE_Hidden_Input(array(
1741
+					'name'    => 'REG_ID',
1742
+					'default' => $this->_registration->ID(),
1743
+				)),
1744
+				'current_status'     => new EE_Form_Section_HTML(
1745
+					EEH_HTML::tr(
1746
+						EEH_HTML::th(
1747
+							EEH_HTML::label(
1748
+								EEH_HTML::strong(esc_html__('Current Registration Status', 'event_espresso')
1749
+								)
1750
+							)
1751
+						)
1752
+						. EEH_HTML::td(
1753
+							EEH_HTML::strong(
1754
+								$this->_registration->pretty_status(),
1755
+								'',
1756
+								'status-' . $this->_registration->status_ID(),
1757
+								'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1758
+							)
1759
+						)
1760
+					)
1761
+				),
1762
+				'reg_status'         => new EE_Select_Input(
1763
+					$this->_get_reg_statuses(),
1764
+					array(
1765
+						'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1766
+						'default'         => $this->_registration->status_ID(),
1767
+					)
1768
+				),
1769
+				'send_notifications' => new EE_Yes_No_Input(
1770
+					array(
1771
+						'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1772
+						'default'         => false,
1773
+						'html_help_text'  => esc_html__(
1774
+							'If set to "Yes", then the related messages will be sent to the registrant.',
1775
+							'event_espresso'
1776
+						),
1777
+					)
1778
+				),
1779
+				'submit'             => new EE_Submit_Input(
1780
+					array(
1781
+						'html_class'      => 'button-primary',
1782
+						'html_label_text' => '&nbsp;',
1783
+						'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1784
+					)
1785
+				),
1786
+			),
1787
+		));
1788
+	}
1789
+
1790
+
1791
+	/**
1792
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1793
+	 *
1794
+	 * @return array
1795
+	 * @throws EE_Error
1796
+	 * @throws InvalidArgumentException
1797
+	 * @throws InvalidDataTypeException
1798
+	 * @throws InvalidInterfaceException
1799
+	 * @throws EntityNotFoundException
1800
+	 */
1801
+	protected function _get_reg_statuses()
1802
+	{
1803
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1804
+		unset ($reg_status_array[EEM_Registration::status_id_incomplete]);
1805
+		// get current reg status
1806
+		$current_status = $this->_registration->status_ID();
1807
+		// is registration for free event? This will determine whether to display the pending payment option
1808
+		if (
1809
+			$current_status !== EEM_Registration::status_id_pending_payment
1810
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1811
+		) {
1812
+			unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1813
+		}
1814
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1815
+	}
1816
+
1817
+
1818
+	/**
1819
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1820
+	 *
1821
+	 * @param bool $status REG status given for changing registrations to.
1822
+	 * @param bool $notify Whether to send messages notifications or not.
1823
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1824
+	 * @throws EE_Error
1825
+	 * @throws InvalidArgumentException
1826
+	 * @throws InvalidDataTypeException
1827
+	 * @throws InvalidInterfaceException
1828
+	 * @throws ReflectionException
1829
+	 * @throws RuntimeException
1830
+	 * @throws EntityNotFoundException
1831
+	 */
1832
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1833
+	{
1834
+		if (isset($this->_req_data['reg_status_change_form'])) {
1835
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1836
+				? (array)$this->_req_data['reg_status_change_form']['REG_ID']
1837
+				: array();
1838
+		} else {
1839
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1840
+				? (array)$this->_req_data['_REG_ID']
1841
+				: array();
1842
+		}
1843
+		// sanitize $REG_IDs
1844
+		$REG_IDs = array_map('absint', $REG_IDs);
1845
+		// and remove empty entries
1846
+		$REG_IDs = array_filter($REG_IDs);
1847
+
1848
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1849
+
1850
+		/**
1851
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1852
+		 * Currently this value is used downstream by the _process_resend_registration method.
1853
+		 *
1854
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1855
+		 * @param bool                     $status           The status registrations were changed to.
1856
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1857
+		 * @param Registrations_Admin_Page $admin_page_object
1858
+		 */
1859
+		$this->_req_data['_REG_ID'] = apply_filters(
1860
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1861
+			$result['REG_ID'],
1862
+			$status,
1863
+			$result['success'],
1864
+			$this
1865
+		);
1866
+
1867
+		//notify?
1868
+		if ($notify
1869
+			&& $result['success']
1870
+			&& ! empty($this->_req_data['_REG_ID'])
1871
+			&& EE_Registry::instance()->CAP->current_user_can(
1872
+				'ee_send_message',
1873
+				'espresso_registrations_resend_registration'
1874
+			)
1875
+		) {
1876
+			$this->_process_resend_registration();
1877
+		}
1878
+		return $result;
1879
+	}
1880
+
1881
+
1882
+	/**
1883
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1884
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1885
+	 *
1886
+	 * @param array  $REG_IDs
1887
+	 * @param string $status
1888
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1889
+	 *                        slug sent with setting the registration status.
1890
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1891
+	 * @throws EE_Error
1892
+	 * @throws InvalidArgumentException
1893
+	 * @throws InvalidDataTypeException
1894
+	 * @throws InvalidInterfaceException
1895
+	 * @throws ReflectionException
1896
+	 * @throws RuntimeException
1897
+	 * @throws EntityNotFoundException
1898
+	 */
1899
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1900
+	{
1901
+		$success = false;
1902
+		// typecast $REG_IDs
1903
+		$REG_IDs = (array)$REG_IDs;
1904
+		if ( ! empty($REG_IDs)) {
1905
+			$success = true;
1906
+			// set default status if none is passed
1907
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1908
+			$status_context = $notify
1909
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1910
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1911
+			//loop through REG_ID's and change status
1912
+			foreach ($REG_IDs as $REG_ID) {
1913
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1914
+				if ($registration instanceof EE_Registration) {
1915
+					$registration->set_status(
1916
+						$status,
1917
+						false,
1918
+						new Context(
1919
+							$status_context,
1920
+							esc_html__(
1921
+								'Manually triggered status change on a Registration Admin Page route.',
1922
+								'event_espresso'
1923
+							)
1924
+						)
1925
+					);
1926
+					$result = $registration->save();
1927
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1928
+					$success = $result !== false ? $success : false;
1929
+				}
1930
+			}
1931
+		}
1932
+
1933
+		//return $success and processed registrations
1934
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1935
+	}
1936
+
1937
+
1938
+	/**
1939
+	 * Common logic for setting up success message and redirecting to appropriate route
1940
+	 *
1941
+	 * @param  string $STS_ID status id for the registration changed to
1942
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1943
+	 * @return void
1944
+	 * @throws EE_Error
1945
+	 */
1946
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1947
+	{
1948
+		$result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1949
+			: array('success' => false);
1950
+		$success = isset($result['success']) && $result['success'];
1951
+		//setup success message
1952
+		if ($success) {
1953
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1954
+				$msg = sprintf(esc_html__('Registration status has been set to %s', 'event_espresso'),
1955
+					EEH_Template::pretty_status($STS_ID, false, 'lower'));
1956
+			} else {
1957
+				$msg = sprintf(esc_html__('Registrations have been set to %s.', 'event_espresso'),
1958
+					EEH_Template::pretty_status($STS_ID, false, 'lower'));
1959
+			}
1960
+			EE_Error::add_success($msg);
1961
+		} else {
1962
+			EE_Error::add_error(
1963
+				esc_html__(
1964
+					'Something went wrong, and the status was not changed',
1965
+					'event_espresso'
1966
+				), __FILE__, __LINE__, __FUNCTION__
1967
+			);
1968
+		}
1969
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1970
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1971
+		} else {
1972
+			$route = array('action' => 'default');
1973
+		}
1974
+		//unset nonces
1975
+		foreach ($this->_req_data as $ref => $value) {
1976
+			if (strpos($ref, 'nonce') !== false) {
1977
+				unset($this->_req_data[$ref]);
1978
+				continue;
1979
+			}
1980
+			$value                 = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
1981
+			$this->_req_data[$ref] = $value;
1982
+		}
1983
+		//merge request vars so that the reloaded list table contains any existing filter query params
1984
+		$route = array_merge($this->_req_data, $route);
1985
+		$this->_redirect_after_action($success, '', '', $route, true);
1986
+	}
1987
+
1988
+
1989
+	/**
1990
+	 * incoming reg status change from reg details page.
1991
+	 *
1992
+	 * @return void
1993
+	 */
1994
+	protected function _change_reg_status()
1995
+	{
1996
+		$this->_req_data['return'] = 'view_registration';
1997
+		//set notify based on whether the send notifications toggle is set or not
1998
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1999
+		//$notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2000
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2001
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2002
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2003
+			case EEM_Registration::status_id_approved :
2004
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence') :
2005
+				$this->approve_registration($notify);
2006
+				break;
2007
+			case EEM_Registration::status_id_pending_payment :
2008
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence') :
2009
+				$this->pending_registration($notify);
2010
+				break;
2011
+			case EEM_Registration::status_id_not_approved :
2012
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence') :
2013
+				$this->not_approve_registration($notify);
2014
+				break;
2015
+			case EEM_Registration::status_id_declined :
2016
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence') :
2017
+				$this->decline_registration($notify);
2018
+				break;
2019
+			case EEM_Registration::status_id_cancelled :
2020
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence') :
2021
+				$this->cancel_registration($notify);
2022
+				break;
2023
+			case EEM_Registration::status_id_wait_list :
2024
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence') :
2025
+				$this->wait_list_registration($notify);
2026
+				break;
2027
+			case EEM_Registration::status_id_incomplete :
2028
+			default :
2029
+				$result['success'] = false;
2030
+				unset($this->_req_data['return']);
2031
+				$this->_reg_status_change_return('', false);
2032
+				break;
2033
+		}
2034
+	}
2035
+
2036
+
2037
+	/**
2038
+	 * Callback for bulk action routes.
2039
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2040
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
2041
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2042
+	 * when an action is happening on just a single registration).
2043
+	 * @param      $action
2044
+	 * @param bool $notify
2045
+	 */
2046
+	protected function bulk_action_on_registrations($action, $notify = false) {
2047
+		do_action(
2048
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2049
+			$this,
2050
+			$action,
2051
+			$notify
2052
+		);
2053
+		$method = $action . '_registration';
2054
+		if (method_exists($this, $method)) {
2055
+			$this->$method($notify);
2056
+		}
2057
+	}
2058
+
2059
+
2060
+	/**
2061
+	 * approve_registration
2062
+	 *
2063
+	 * @access protected
2064
+	 * @param bool $notify whether or not to notify the registrant about their approval.
2065
+	 * @return void
2066
+	 */
2067
+	protected function approve_registration($notify = false)
2068
+	{
2069
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2070
+	}
2071
+
2072
+
2073
+	/**
2074
+	 *        decline_registration
2075
+	 *
2076
+	 * @access protected
2077
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2078
+	 * @return void
2079
+	 */
2080
+	protected function decline_registration($notify = false)
2081
+	{
2082
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2083
+	}
2084
+
2085
+
2086
+	/**
2087
+	 *        cancel_registration
2088
+	 *
2089
+	 * @access protected
2090
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2091
+	 * @return void
2092
+	 */
2093
+	protected function cancel_registration($notify = false)
2094
+	{
2095
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2096
+	}
2097
+
2098
+
2099
+	/**
2100
+	 *        not_approve_registration
2101
+	 *
2102
+	 * @access protected
2103
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2104
+	 * @return void
2105
+	 */
2106
+	protected function not_approve_registration($notify = false)
2107
+	{
2108
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2109
+	}
2110
+
2111
+
2112
+	/**
2113
+	 *        decline_registration
2114
+	 *
2115
+	 * @access protected
2116
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2117
+	 * @return void
2118
+	 */
2119
+	protected function pending_registration($notify = false)
2120
+	{
2121
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2122
+	}
2123
+
2124
+
2125
+	/**
2126
+	 * waitlist_registration
2127
+	 *
2128
+	 * @access protected
2129
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2130
+	 * @return void
2131
+	 */
2132
+	protected function wait_list_registration($notify = false)
2133
+	{
2134
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2135
+	}
2136
+
2137
+
2138
+	/**
2139
+	 *        generates HTML for the Registration main meta box
2140
+	 *
2141
+	 * @access public
2142
+	 * @return void
2143
+	 * @throws DomainException
2144
+	 * @throws EE_Error
2145
+	 * @throws InvalidArgumentException
2146
+	 * @throws InvalidDataTypeException
2147
+	 * @throws InvalidInterfaceException
2148
+	 * @throws ReflectionException
2149
+	 * @throws EntityNotFoundException
2150
+	 */
2151
+	public function _reg_details_meta_box()
2152
+	{
2153
+		EEH_Autoloader::register_line_item_display_autoloaders();
2154
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2155
+		EE_Registry::instance()->load_helper('Line_Item');
2156
+		$transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
2157
+			: EE_Transaction::new_instance();
2158
+		$this->_session = $transaction->session_data();
2159
+		$filters        = new EE_Line_Item_Filter_Collection();
2160
+		//$filters->add( new EE_Non_Zero_Line_Item_Filter() );
2161
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2162
+		$line_item_filter_processor              = new EE_Line_Item_Filter_Processor($filters,
2163
+			$transaction->total_line_item());
2164
+		$filtered_line_item_tree                 = $line_item_filter_processor->process();
2165
+		$line_item_display                       = new EE_Line_Item_Display('reg_admin_table',
2166
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy');
2167
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2168
+			$filtered_line_item_tree,
2169
+			array('EE_Registration' => $this->_registration)
2170
+		);
2171
+		$attendee                                = $this->_registration->attendee();
2172
+		if (EE_Registry::instance()->CAP->current_user_can(
2173
+			'ee_read_transaction',
2174
+			'espresso_transactions_view_transaction'
2175
+		)) {
2176
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2177
+				EE_Admin_Page::add_query_args_and_nonce(
2178
+					array(
2179
+						'action' => 'view_transaction',
2180
+						'TXN_ID' => $transaction->ID(),
2181
+					),
2182
+					TXN_ADMIN_URL
2183
+				),
2184
+				esc_html__(' View Transaction', 'event_espresso'),
2185
+				'button secondary-button right',
2186
+				'dashicons dashicons-cart'
2187
+			);
2188
+		} else {
2189
+			$this->_template_args['view_transaction_button'] = '';
2190
+		}
2191
+		if ($attendee instanceof EE_Attendee
2192
+			&& EE_Registry::instance()->CAP->current_user_can(
2193
+				'ee_send_message',
2194
+				'espresso_registrations_resend_registration'
2195
+			)
2196
+		) {
2197
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2198
+				EE_Admin_Page::add_query_args_and_nonce(
2199
+					array(
2200
+						'action'      => 'resend_registration',
2201
+						'_REG_ID'     => $this->_registration->ID(),
2202
+						'redirect_to' => 'view_registration',
2203
+					),
2204
+					REG_ADMIN_URL
2205
+				),
2206
+				esc_html__(' Resend Registration', 'event_espresso'),
2207
+				'button secondary-button right',
2208
+				'dashicons dashicons-email-alt'
2209
+			);
2210
+		} else {
2211
+			$this->_template_args['resend_registration_button'] = '';
2212
+		}
2213
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2214
+		$payment                               = $transaction->get_first_related('Payment');
2215
+		$payment                               = ! $payment instanceof EE_Payment
2216
+			? EE_Payment::new_instance()
2217
+			: $payment;
2218
+		$payment_method                        = $payment->get_first_related('Payment_Method');
2219
+		$payment_method                        = ! $payment_method instanceof EE_Payment_Method
2220
+			? EE_Payment_Method::new_instance()
2221
+			: $payment_method;
2222
+		$reg_details                           = array(
2223
+			'payment_method'       => $payment_method->name(),
2224
+			'response_msg'         => $payment->gateway_response(),
2225
+			'registration_id'      => $this->_registration->get('REG_code'),
2226
+			'registration_session' => $this->_registration->session_ID(),
2227
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2228
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2229
+		);
2230
+		if (isset($reg_details['registration_id'])) {
2231
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2232
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2233
+				'Registration ID',
2234
+				'event_espresso'
2235
+			);
2236
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2237
+		}
2238
+		if (isset($reg_details['payment_method'])) {
2239
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2240
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2241
+				'Most Recent Payment Method',
2242
+				'event_espresso'
2243
+			);
2244
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2245
+			$this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2246
+			$this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2247
+				'Payment method response',
2248
+				'event_espresso'
2249
+			);
2250
+			$this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2251
+		}
2252
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2253
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2254
+			'Registration Session',
2255
+			'event_espresso'
2256
+		);
2257
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2258
+		$this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2259
+		$this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2260
+			'Registration placed from IP',
2261
+			'event_espresso'
2262
+		);
2263
+		$this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2264
+		$this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2265
+		$this->_template_args['reg_details']['user_agent']['label']           = esc_html__('Registrant User Agent',
2266
+			'event_espresso');
2267
+		$this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2268
+		$this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2269
+			array(
2270
+				'action'   => 'default',
2271
+				'event_id' => $this->_registration->event_ID(),
2272
+			),
2273
+			REG_ADMIN_URL
2274
+		);
2275
+		$this->_template_args['REG_ID']                                       = $this->_registration->ID();
2276
+		$this->_template_args['event_id']                                     = $this->_registration->event_ID();
2277
+		$template_path                                                        =
2278
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2279
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2280
+	}
2281
+
2282
+
2283
+	/**
2284
+	 * generates HTML for the Registration Questions meta box.
2285
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2286
+	 * otherwise uses new forms system
2287
+	 *
2288
+	 * @access public
2289
+	 * @return void
2290
+	 * @throws DomainException
2291
+	 * @throws EE_Error
2292
+	 */
2293
+	public function _reg_questions_meta_box()
2294
+	{
2295
+		//allow someone to override this method entirely
2296
+		if (apply_filters('FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default', true, $this,
2297
+			$this->_registration)) {
2298
+			$form                                              = $this->_get_reg_custom_questions_form(
2299
+				$this->_registration->ID()
2300
+			);
2301
+			$this->_template_args['att_questions']             = count($form->subforms()) > 0
2302
+				? $form->get_html_and_js()
2303
+				: '';
2304
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2305
+			$this->_template_args['REG_ID']                    = $this->_registration->ID();
2306
+			$template_path                                     =
2307
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2308
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2309
+		}
2310
+	}
2311
+
2312
+
2313
+	/**
2314
+	 * form_before_question_group
2315
+	 *
2316
+	 * @deprecated    as of 4.8.32.rc.000
2317
+	 * @access        public
2318
+	 * @param        string $output
2319
+	 * @return        string
2320
+	 */
2321
+	public function form_before_question_group($output)
2322
+	{
2323
+		EE_Error::doing_it_wrong(
2324
+			__CLASS__ . '::' . __FUNCTION__,
2325
+			esc_html__(
2326
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2327
+				'event_espresso'
2328
+			),
2329
+			'4.8.32.rc.000'
2330
+		);
2331
+		return '
2332 2332
 	<table class="form-table ee-width-100">
2333 2333
 		<tbody>
2334 2334
 			';
2335
-    }
2336
-
2337
-
2338
-    /**
2339
-     * form_after_question_group
2340
-     *
2341
-     * @deprecated    as of 4.8.32.rc.000
2342
-     * @access        public
2343
-     * @param        string $output
2344
-     * @return        string
2345
-     */
2346
-    public function form_after_question_group($output)
2347
-    {
2348
-        EE_Error::doing_it_wrong(
2349
-            __CLASS__ . '::' . __FUNCTION__,
2350
-            esc_html__(
2351
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2352
-                'event_espresso'
2353
-            ),
2354
-            '4.8.32.rc.000'
2355
-        );
2356
-        return '
2335
+	}
2336
+
2337
+
2338
+	/**
2339
+	 * form_after_question_group
2340
+	 *
2341
+	 * @deprecated    as of 4.8.32.rc.000
2342
+	 * @access        public
2343
+	 * @param        string $output
2344
+	 * @return        string
2345
+	 */
2346
+	public function form_after_question_group($output)
2347
+	{
2348
+		EE_Error::doing_it_wrong(
2349
+			__CLASS__ . '::' . __FUNCTION__,
2350
+			esc_html__(
2351
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2352
+				'event_espresso'
2353
+			),
2354
+			'4.8.32.rc.000'
2355
+		);
2356
+		return '
2357 2357
 			<tr class="hide-if-no-js">
2358 2358
 				<th> </th>
2359 2359
 				<td class="reg-admin-edit-attendee-question-td">
2360 2360
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2361
-               . esc_attr__('click to edit question', 'event_espresso')
2362
-               . '">
2361
+			   . esc_attr__('click to edit question', 'event_espresso')
2362
+			   . '">
2363 2363
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2364
-               . esc_html__('edit the above question group', 'event_espresso')
2365
-               . '</span>
2364
+			   . esc_html__('edit the above question group', 'event_espresso')
2365
+			   . '</span>
2366 2366
 						<div class="dashicons dashicons-edit"></div>
2367 2367
 					</a>
2368 2368
 				</td>
@@ -2370,579 +2370,579 @@  discard block
 block discarded – undo
2370 2370
 		</tbody>
2371 2371
 	</table>
2372 2372
 ';
2373
-    }
2374
-
2375
-
2376
-    /**
2377
-     * form_form_field_label_wrap
2378
-     *
2379
-     * @deprecated    as of 4.8.32.rc.000
2380
-     * @access        public
2381
-     * @param        string $label
2382
-     * @return        string
2383
-     */
2384
-    public function form_form_field_label_wrap($label)
2385
-    {
2386
-        EE_Error::doing_it_wrong(
2387
-            __CLASS__ . '::' . __FUNCTION__,
2388
-            esc_html__(
2389
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390
-                'event_espresso'
2391
-            ),
2392
-            '4.8.32.rc.000'
2393
-        );
2394
-        return '
2373
+	}
2374
+
2375
+
2376
+	/**
2377
+	 * form_form_field_label_wrap
2378
+	 *
2379
+	 * @deprecated    as of 4.8.32.rc.000
2380
+	 * @access        public
2381
+	 * @param        string $label
2382
+	 * @return        string
2383
+	 */
2384
+	public function form_form_field_label_wrap($label)
2385
+	{
2386
+		EE_Error::doing_it_wrong(
2387
+			__CLASS__ . '::' . __FUNCTION__,
2388
+			esc_html__(
2389
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390
+				'event_espresso'
2391
+			),
2392
+			'4.8.32.rc.000'
2393
+		);
2394
+		return '
2395 2395
 			<tr>
2396 2396
 				<th>
2397 2397
 					' . $label . '
2398 2398
 				</th>';
2399
-    }
2400
-
2401
-
2402
-    /**
2403
-     * form_form_field_input__wrap
2404
-     *
2405
-     * @deprecated    as of 4.8.32.rc.000
2406
-     * @access        public
2407
-     * @param        string $input
2408
-     * @return        string
2409
-     */
2410
-    public function form_form_field_input__wrap($input)
2411
-    {
2412
-        EE_Error::doing_it_wrong(
2413
-            __CLASS__ . '::' . __FUNCTION__,
2414
-            esc_html__(
2415
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2416
-                'event_espresso'
2417
-            ),
2418
-            '4.8.32.rc.000'
2419
-        );
2420
-        return '
2399
+	}
2400
+
2401
+
2402
+	/**
2403
+	 * form_form_field_input__wrap
2404
+	 *
2405
+	 * @deprecated    as of 4.8.32.rc.000
2406
+	 * @access        public
2407
+	 * @param        string $input
2408
+	 * @return        string
2409
+	 */
2410
+	public function form_form_field_input__wrap($input)
2411
+	{
2412
+		EE_Error::doing_it_wrong(
2413
+			__CLASS__ . '::' . __FUNCTION__,
2414
+			esc_html__(
2415
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2416
+				'event_espresso'
2417
+			),
2418
+			'4.8.32.rc.000'
2419
+		);
2420
+		return '
2421 2421
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2422 2422
 					' . $input . '
2423 2423
 				</td>
2424 2424
 			</tr>';
2425
-    }
2426
-
2427
-
2428
-    /**
2429
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2430
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2431
-     * to display the page
2432
-     *
2433
-     * @access protected
2434
-     * @return void
2435
-     * @throws EE_Error
2436
-     */
2437
-    protected function _update_attendee_registration_form()
2438
-    {
2439
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2440
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2441
-            $REG_ID  = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2442
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2443
-            if ($success) {
2444
-                $what  = esc_html__('Registration Form', 'event_espresso');
2445
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2446
-                    : array('action' => 'default');
2447
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2448
-            }
2449
-        }
2450
-    }
2451
-
2452
-
2453
-    /**
2454
-     * Gets the form for saving registrations custom questions (if done
2455
-     * previously retrieves the cached form object, which may have validation errors in it)
2456
-     *
2457
-     * @param int $REG_ID
2458
-     * @return EE_Registration_Custom_Questions_Form
2459
-     * @throws EE_Error
2460
-     * @throws InvalidArgumentException
2461
-     * @throws InvalidDataTypeException
2462
-     * @throws InvalidInterfaceException
2463
-     */
2464
-    protected function _get_reg_custom_questions_form($REG_ID)
2465
-    {
2466
-        if ( ! $this->_reg_custom_questions_form) {
2467
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2468
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2469
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2470
-            );
2471
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2472
-        }
2473
-        return $this->_reg_custom_questions_form;
2474
-    }
2475
-
2476
-
2477
-    /**
2478
-     * Saves
2479
-     *
2480
-     * @access private
2481
-     * @param bool $REG_ID
2482
-     * @return bool
2483
-     * @throws EE_Error
2484
-     * @throws InvalidArgumentException
2485
-     * @throws InvalidDataTypeException
2486
-     * @throws InvalidInterfaceException
2487
-     */
2488
-    private function _save_reg_custom_questions_form($REG_ID = false)
2489
-    {
2490
-        if ( ! $REG_ID) {
2491
-            EE_Error::add_error(
2492
-                esc_html__(
2493
-                    'An error occurred. No registration ID was received.', 'event_espresso'),
2494
-                __FILE__, __FUNCTION__, __LINE__
2495
-            );
2496
-        }
2497
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2498
-        $form->receive_form_submission($this->_req_data);
2499
-        $success = false;
2500
-        if ($form->is_valid()) {
2501
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2502
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2503
-                    $where_conditions    = array(
2504
-                        'QST_ID' => $question_id,
2505
-                        'REG_ID' => $REG_ID,
2506
-                    );
2507
-                    $possibly_new_values = array(
2508
-                        'ANS_value' => $input->normalized_value(),
2509
-                    );
2510
-                    $answer              = EEM_Answer::instance()->get_one(array($where_conditions));
2511
-                    if ($answer instanceof EE_Answer) {
2512
-                        $success = $answer->save($possibly_new_values);
2513
-                    } else {
2514
-                        //insert it then
2515
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2516
-                        $answer      = EE_Answer::new_instance($cols_n_vals);
2517
-                        $success     = $answer->save();
2518
-                    }
2519
-                }
2520
-            }
2521
-        } else {
2522
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2523
-        }
2524
-        return $success;
2525
-    }
2526
-
2527
-
2528
-    /**
2529
-     *        generates HTML for the Registration main meta box
2530
-     *
2531
-     * @access public
2532
-     * @return void
2533
-     * @throws DomainException
2534
-     * @throws EE_Error
2535
-     * @throws InvalidArgumentException
2536
-     * @throws InvalidDataTypeException
2537
-     * @throws InvalidInterfaceException
2538
-     */
2539
-    public function _reg_attendees_meta_box()
2540
-    {
2541
-        $REG = EEM_Registration::instance();
2542
-        //get all other registrations on this transaction, and cache
2543
-        //the attendees for them so we don't have to run another query using force_join
2544
-        $registrations                           = $REG->get_all(array(
2545
-            array(
2546
-                'TXN_ID' => $this->_registration->transaction_ID(),
2547
-                'REG_ID' => array('!=', $this->_registration->ID()),
2548
-            ),
2549
-            'force_join' => array('Attendee'),
2550
-        ));
2551
-        $this->_template_args['attendees']       = array();
2552
-        $this->_template_args['attendee_notice'] = '';
2553
-        if (empty($registrations)
2554
-            || (is_array($registrations)
2555
-                && ! EEH_Array::get_one_item_from_array($registrations))
2556
-        ) {
2557
-            EE_Error::add_error(
2558
-                esc_html__(
2559
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2560
-                    'event_espresso'
2561
-                ), __FILE__, __FUNCTION__, __LINE__
2562
-            );
2563
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2564
-        } else {
2565
-            $att_nmbr = 1;
2566
-            foreach ($registrations as $registration) {
2567
-                /* @var $registration EE_Registration */
2568
-                $attendee                                                    = $registration->attendee()
2569
-                    ? $registration->attendee()
2570
-                    : EEM_Attendee::instance()
2571
-                                  ->create_default_object();
2572
-                $this->_template_args['attendees'][$att_nmbr]['STS_ID']      = $registration->status_ID();
2573
-                $this->_template_args['attendees'][$att_nmbr]['fname']       = $attendee->fname();
2574
-                $this->_template_args['attendees'][$att_nmbr]['lname']       = $attendee->lname();
2575
-                $this->_template_args['attendees'][$att_nmbr]['email']       = $attendee->email();
2576
-                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2577
-                $this->_template_args['attendees'][$att_nmbr]['address']     = implode(
2578
-                    ', ',
2579
-                    $attendee->full_address_as_array()
2580
-                );
2581
-                $this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2582
-                    array(
2583
-                        'action' => 'edit_attendee',
2584
-                        'post'   => $attendee->ID(),
2585
-                    ),
2586
-                    REG_ADMIN_URL
2587
-                );
2588
-                $this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2589
-                $att_nmbr++;
2590
-            }
2591
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2592
-        }
2593
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2594
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2595
-    }
2596
-
2597
-
2598
-    /**
2599
-     *        generates HTML for the Edit Registration side meta box
2600
-     *
2601
-     * @access public
2602
-     * @return void
2603
-     * @throws DomainException
2604
-     * @throws EE_Error
2605
-     * @throws InvalidArgumentException
2606
-     * @throws InvalidDataTypeException
2607
-     * @throws InvalidInterfaceException
2608
-     */
2609
-    public function _reg_registrant_side_meta_box()
2610
-    {
2611
-        /*@var $attendee EE_Attendee */
2612
-        $att_check = $this->_registration->attendee();
2613
-        $attendee  = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2614
-        //now let's determine if this is not the primary registration.  If it isn't then we set the
2615
-        //primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2616
-        //primary registration object (that way we know if we need to show create button or not)
2617
-        if ( ! $this->_registration->is_primary_registrant()) {
2618
-            $primary_registration = $this->_registration->get_primary_registration();
2619
-            $primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2620
-                : null;
2621
-            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2622
-                //in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2623
-                //custom attendee object so let's not worry about the primary reg.
2624
-                $primary_registration = null;
2625
-            }
2626
-        } else {
2627
-            $primary_registration = null;
2628
-        }
2629
-        $this->_template_args['ATT_ID']            = $attendee->ID();
2630
-        $this->_template_args['fname']             = $attendee->fname();
2631
-        $this->_template_args['lname']             = $attendee->lname();
2632
-        $this->_template_args['email']             = $attendee->email();
2633
-        $this->_template_args['phone']             = $attendee->phone();
2634
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2635
-        //edit link
2636
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2637
-            'action' => 'edit_attendee',
2638
-            'post'   => $attendee->ID(),
2639
-        ), REG_ADMIN_URL);
2640
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2641
-        //create link
2642
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2643
-            ? EE_Admin_Page::add_query_args_and_nonce(array(
2644
-                'action'  => 'duplicate_attendee',
2645
-                '_REG_ID' => $this->_registration->ID(),
2646
-            ), REG_ADMIN_URL) : '';
2647
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2648
-        $this->_template_args['att_check']    = $att_check;
2649
-        $template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2650
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2651
-    }
2652
-
2653
-
2654
-    /**
2655
-     * trash or restore registrations
2656
-     *
2657
-     * @param  boolean $trash whether to archive or restore
2658
-     * @return void
2659
-     * @throws EE_Error
2660
-     * @throws InvalidArgumentException
2661
-     * @throws InvalidDataTypeException
2662
-     * @throws InvalidInterfaceException
2663
-     * @throws RuntimeException
2664
-     * @access protected
2665
-     */
2666
-    protected function _trash_or_restore_registrations($trash = true)
2667
-    {
2668
-        //if empty _REG_ID then get out because there's nothing to do
2669
-        if (empty($this->_req_data['_REG_ID'])) {
2670
-            EE_Error::add_error(
2671
-                sprintf(
2672
-                    esc_html__(
2673
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2674
-                        'event_espresso'
2675
-                    ),
2676
-                    $trash ? 'trash' : 'restore'
2677
-                ),
2678
-                __FILE__, __LINE__, __FUNCTION__
2679
-            );
2680
-            $this->_redirect_after_action(false, '', '', array(), true);
2681
-        }
2682
-        $success = 0;
2683
-        $overwrite_msgs = false;
2684
-        //Checkboxes
2685
-        if ( ! is_array($this->_req_data['_REG_ID'])) {
2686
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2687
-        }
2688
-        $reg_count = count($this->_req_data['_REG_ID']);
2689
-        // cycle thru checkboxes
2690
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2691
-            /** @var EE_Registration $REG */
2692
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2693
-            $payments = $REG->registration_payments();
2694
-            if (! empty($payments)) {
2695
-                $name = $REG->attendee() instanceof EE_Attendee
2696
-                    ? $REG->attendee()->full_name()
2697
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2698
-                $overwrite_msgs = true;
2699
-                EE_Error::add_error(
2700
-                    sprintf(
2701
-                        esc_html__(
2702
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2703
-                            'event_espresso'
2704
-                        ),
2705
-                        $name
2706
-                    ),
2707
-                    __FILE__, __FUNCTION__, __LINE__
2708
-                );
2709
-                //can't trash this registration because it has payments.
2710
-                continue;
2711
-            }
2712
-            $updated = $trash ? $REG->delete() : $REG->restore();
2713
-            if ($updated) {
2714
-                $success++;
2715
-            }
2716
-        }
2717
-        $this->_redirect_after_action(
2718
-            $success === $reg_count, // were ALL registrations affected?
2719
-            $success > 1
2720
-                ? esc_html__('Registrations', 'event_espresso')
2721
-                : esc_html__('Registration', 'event_espresso'),
2722
-            $trash
2723
-                ? esc_html__('moved to the trash', 'event_espresso')
2724
-                : esc_html__('restored', 'event_espresso'),
2725
-            array('action' => 'default'),
2726
-            $overwrite_msgs
2727
-        );
2728
-    }
2729
-
2730
-
2731
-    /**
2732
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2733
-     * registration but also.
2734
-     * 1. Removing relations to EE_Attendee
2735
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2736
-     * ALSO trashed.
2737
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2738
-     * 4. Removing relationships between all tickets and the related registrations
2739
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2740
-     * 6. Deleting permanently any related Checkins.
2741
-     *
2742
-     * @return void
2743
-     * @throws EE_Error
2744
-     * @throws InvalidArgumentException
2745
-     * @throws InvalidDataTypeException
2746
-     * @throws InvalidInterfaceException
2747
-     */
2748
-    protected function _delete_registrations()
2749
-    {
2750
-        $REG_MDL = EEM_Registration::instance();
2751
-        $success = 1;
2752
-        //Checkboxes
2753
-        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2754
-            // if array has more than one element than success message should be plural
2755
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2756
-            // cycle thru checkboxes
2757
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2758
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2759
-                if ( ! $REG instanceof EE_Registration) {
2760
-                    continue;
2761
-                }
2762
-                $deleted = $this->_delete_registration($REG);
2763
-                if ( ! $deleted) {
2764
-                    $success = 0;
2765
-                }
2766
-            }
2767
-        } else {
2768
-            // grab single id and delete
2769
-            $REG_ID  = $this->_req_data['_REG_ID'];
2770
-            $REG     = $REG_MDL->get_one_by_ID($REG_ID);
2771
-            $deleted = $this->_delete_registration($REG);
2772
-            if ( ! $deleted) {
2773
-                $success = 0;
2774
-            }
2775
-        }
2776
-        $what        = $success > 1
2777
-            ? esc_html__('Registrations', 'event_espresso')
2778
-            : esc_html__('Registration', 'event_espresso');
2779
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2780
-        $this->_redirect_after_action(
2781
-            $success,
2782
-            $what,
2783
-            $action_desc,
2784
-            array('action' => 'default'),
2785
-            true
2786
-        );
2787
-    }
2788
-
2789
-
2790
-    /**
2791
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2792
-     * models get affected.
2793
-     *
2794
-     * @param  EE_Registration $REG registration to be deleted permenantly
2795
-     * @return bool true = successful deletion, false = fail.
2796
-     * @throws EE_Error
2797
-     */
2798
-    protected function _delete_registration(EE_Registration $REG)
2799
-    {
2800
-        //first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2801
-        //registrations on the transaction that are NOT trashed.
2802
-        $TXN         = $REG->get_first_related('Transaction');
2803
-        $REGS        = $TXN->get_many_related('Registration');
2804
-        $all_trashed = true;
2805
-        foreach ($REGS as $registration) {
2806
-            if ( ! $registration->get('REG_deleted')) {
2807
-                $all_trashed = false;
2808
-            }
2809
-        }
2810
-        if ( ! $all_trashed) {
2811
-            EE_Error::add_error(
2812
-                esc_html__(
2813
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2814
-                    'event_espresso'
2815
-                ),
2816
-                __FILE__, __FUNCTION__, __LINE__
2817
-            );
2818
-            return false;
2819
-        }
2820
-        //k made it here so that means we can delete all the related transactions and their answers (but let's do them
2821
-        //separately from THIS one).
2822
-        foreach ($REGS as $registration) {
2823
-            //delete related answers
2824
-            $registration->delete_related_permanently('Answer');
2825
-            //remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2826
-            $attendee = $registration->get_first_related('Attendee');
2827
-            if ($attendee instanceof EE_Attendee) {
2828
-                $registration->_remove_relation_to($attendee, 'Attendee');
2829
-            }
2830
-            //now remove relationships to tickets on this registration.
2831
-            $registration->_remove_relations('Ticket');
2832
-            //now delete permanently the checkins related to this registration.
2833
-            $registration->delete_related_permanently('Checkin');
2834
-            if ($registration->ID() === $REG->ID()) {
2835
-                continue;
2836
-            } //we don't want to delete permanently the existing registration just yet.
2837
-            //remove relation to transaction for these registrations if NOT the existing registrations
2838
-            $registration->_remove_relations('Transaction');
2839
-            //delete permanently any related messages.
2840
-            $registration->delete_related_permanently('Message');
2841
-            //now delete this registration permanently
2842
-            $registration->delete_permanently();
2843
-        }
2844
-        //now all related registrations on the transaction are handled.  So let's just handle this registration itself
2845
-        // (the transaction and line items should be all that's left).
2846
-        // delete the line items related to the transaction for this registration.
2847
-        $TXN->delete_related_permanently('Line_Item');
2848
-        //we need to remove all the relationships on the transaction
2849
-        $TXN->delete_related_permanently('Payment');
2850
-        $TXN->delete_related_permanently('Extra_Meta');
2851
-        $TXN->delete_related_permanently('Message');
2852
-        //now we can delete this REG permanently (and the transaction of course)
2853
-        $REG->delete_related_permanently('Transaction');
2854
-        return $REG->delete_permanently();
2855
-    }
2856
-
2857
-
2858
-    /**
2859
-     *    generates HTML for the Register New Attendee Admin page
2860
-     *
2861
-     * @access private
2862
-     * @throws DomainException
2863
-     * @throws EE_Error
2864
-     */
2865
-    public function new_registration()
2866
-    {
2867
-        if ( ! $this->_set_reg_event()) {
2868
-            throw new EE_Error(
2869
-                esc_html__(
2870
-                    'Unable to continue with registering because there is no Event ID in the request',
2871
-                    'event_espresso'
2872
-                )
2873
-            );
2874
-        }
2875
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2876
-        // gotta start with a clean slate if we're not coming here via ajax
2877
-        if ( ! defined('DOING_AJAX')
2878
-             && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2879
-        ) {
2880
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2881
-        }
2882
-        $this->_template_args['event_name'] = '';
2883
-        // event name
2884
-        if ($this->_reg_event) {
2885
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2886
-            $edit_event_url                     = self::add_query_args_and_nonce(array(
2887
-                'action' => 'edit',
2888
-                'post'   => $this->_reg_event->ID(),
2889
-            ), EVENTS_ADMIN_URL);
2890
-            $edit_event_lnk                     = '<a href="'
2891
-                                                  . $edit_event_url
2892
-                                                  . '" title="'
2893
-                                                  . esc_attr__('Edit ', 'event_espresso')
2894
-                                                  . $this->_reg_event->name()
2895
-                                                  . '">'
2896
-                                                  . esc_html__('Edit Event', 'event_espresso')
2897
-                                                  . '</a>';
2898
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2899
-                                                   . $edit_event_lnk
2900
-                                                   . '</span>';
2901
-        }
2902
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2903
-        if (defined('DOING_AJAX')) {
2904
-            $this->_return_json();
2905
-        }
2906
-        // grab header
2907
-        $template_path                              =
2908
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2909
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2910
-            $this->_template_args, true);
2911
-        //$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2912
-        // the details template wrapper
2913
-        $this->display_admin_page_with_sidebar();
2914
-    }
2915
-
2916
-
2917
-    /**
2918
-     * This returns the content for a registration step
2919
-     *
2920
-     * @access protected
2921
-     * @return string html
2922
-     * @throws DomainException
2923
-     * @throws EE_Error
2924
-     * @throws InvalidArgumentException
2925
-     * @throws InvalidDataTypeException
2926
-     * @throws InvalidInterfaceException
2927
-     */
2928
-    protected function _get_registration_step_content()
2929
-    {
2930
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2931
-            $warning_msg = sprintf(
2932
-                esc_html__(
2933
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2934
-                    'event_espresso'
2935
-                ),
2936
-                '<br />',
2937
-                '<h3 class="important-notice">',
2938
-                '</h3>',
2939
-                '<div class="float-right">',
2940
-                '<span id="redirect_timer" class="important-notice">30</span>',
2941
-                '</div>',
2942
-                '<b>',
2943
-                '</b>'
2944
-            );
2945
-            return '
2425
+	}
2426
+
2427
+
2428
+	/**
2429
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2430
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2431
+	 * to display the page
2432
+	 *
2433
+	 * @access protected
2434
+	 * @return void
2435
+	 * @throws EE_Error
2436
+	 */
2437
+	protected function _update_attendee_registration_form()
2438
+	{
2439
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2440
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2441
+			$REG_ID  = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2442
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2443
+			if ($success) {
2444
+				$what  = esc_html__('Registration Form', 'event_espresso');
2445
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2446
+					: array('action' => 'default');
2447
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2448
+			}
2449
+		}
2450
+	}
2451
+
2452
+
2453
+	/**
2454
+	 * Gets the form for saving registrations custom questions (if done
2455
+	 * previously retrieves the cached form object, which may have validation errors in it)
2456
+	 *
2457
+	 * @param int $REG_ID
2458
+	 * @return EE_Registration_Custom_Questions_Form
2459
+	 * @throws EE_Error
2460
+	 * @throws InvalidArgumentException
2461
+	 * @throws InvalidDataTypeException
2462
+	 * @throws InvalidInterfaceException
2463
+	 */
2464
+	protected function _get_reg_custom_questions_form($REG_ID)
2465
+	{
2466
+		if ( ! $this->_reg_custom_questions_form) {
2467
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2468
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2469
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2470
+			);
2471
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2472
+		}
2473
+		return $this->_reg_custom_questions_form;
2474
+	}
2475
+
2476
+
2477
+	/**
2478
+	 * Saves
2479
+	 *
2480
+	 * @access private
2481
+	 * @param bool $REG_ID
2482
+	 * @return bool
2483
+	 * @throws EE_Error
2484
+	 * @throws InvalidArgumentException
2485
+	 * @throws InvalidDataTypeException
2486
+	 * @throws InvalidInterfaceException
2487
+	 */
2488
+	private function _save_reg_custom_questions_form($REG_ID = false)
2489
+	{
2490
+		if ( ! $REG_ID) {
2491
+			EE_Error::add_error(
2492
+				esc_html__(
2493
+					'An error occurred. No registration ID was received.', 'event_espresso'),
2494
+				__FILE__, __FUNCTION__, __LINE__
2495
+			);
2496
+		}
2497
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2498
+		$form->receive_form_submission($this->_req_data);
2499
+		$success = false;
2500
+		if ($form->is_valid()) {
2501
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2502
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2503
+					$where_conditions    = array(
2504
+						'QST_ID' => $question_id,
2505
+						'REG_ID' => $REG_ID,
2506
+					);
2507
+					$possibly_new_values = array(
2508
+						'ANS_value' => $input->normalized_value(),
2509
+					);
2510
+					$answer              = EEM_Answer::instance()->get_one(array($where_conditions));
2511
+					if ($answer instanceof EE_Answer) {
2512
+						$success = $answer->save($possibly_new_values);
2513
+					} else {
2514
+						//insert it then
2515
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2516
+						$answer      = EE_Answer::new_instance($cols_n_vals);
2517
+						$success     = $answer->save();
2518
+					}
2519
+				}
2520
+			}
2521
+		} else {
2522
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2523
+		}
2524
+		return $success;
2525
+	}
2526
+
2527
+
2528
+	/**
2529
+	 *        generates HTML for the Registration main meta box
2530
+	 *
2531
+	 * @access public
2532
+	 * @return void
2533
+	 * @throws DomainException
2534
+	 * @throws EE_Error
2535
+	 * @throws InvalidArgumentException
2536
+	 * @throws InvalidDataTypeException
2537
+	 * @throws InvalidInterfaceException
2538
+	 */
2539
+	public function _reg_attendees_meta_box()
2540
+	{
2541
+		$REG = EEM_Registration::instance();
2542
+		//get all other registrations on this transaction, and cache
2543
+		//the attendees for them so we don't have to run another query using force_join
2544
+		$registrations                           = $REG->get_all(array(
2545
+			array(
2546
+				'TXN_ID' => $this->_registration->transaction_ID(),
2547
+				'REG_ID' => array('!=', $this->_registration->ID()),
2548
+			),
2549
+			'force_join' => array('Attendee'),
2550
+		));
2551
+		$this->_template_args['attendees']       = array();
2552
+		$this->_template_args['attendee_notice'] = '';
2553
+		if (empty($registrations)
2554
+			|| (is_array($registrations)
2555
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2556
+		) {
2557
+			EE_Error::add_error(
2558
+				esc_html__(
2559
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2560
+					'event_espresso'
2561
+				), __FILE__, __FUNCTION__, __LINE__
2562
+			);
2563
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2564
+		} else {
2565
+			$att_nmbr = 1;
2566
+			foreach ($registrations as $registration) {
2567
+				/* @var $registration EE_Registration */
2568
+				$attendee                                                    = $registration->attendee()
2569
+					? $registration->attendee()
2570
+					: EEM_Attendee::instance()
2571
+								  ->create_default_object();
2572
+				$this->_template_args['attendees'][$att_nmbr]['STS_ID']      = $registration->status_ID();
2573
+				$this->_template_args['attendees'][$att_nmbr]['fname']       = $attendee->fname();
2574
+				$this->_template_args['attendees'][$att_nmbr]['lname']       = $attendee->lname();
2575
+				$this->_template_args['attendees'][$att_nmbr]['email']       = $attendee->email();
2576
+				$this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2577
+				$this->_template_args['attendees'][$att_nmbr]['address']     = implode(
2578
+					', ',
2579
+					$attendee->full_address_as_array()
2580
+				);
2581
+				$this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2582
+					array(
2583
+						'action' => 'edit_attendee',
2584
+						'post'   => $attendee->ID(),
2585
+					),
2586
+					REG_ADMIN_URL
2587
+				);
2588
+				$this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2589
+				$att_nmbr++;
2590
+			}
2591
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2592
+		}
2593
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2594
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2595
+	}
2596
+
2597
+
2598
+	/**
2599
+	 *        generates HTML for the Edit Registration side meta box
2600
+	 *
2601
+	 * @access public
2602
+	 * @return void
2603
+	 * @throws DomainException
2604
+	 * @throws EE_Error
2605
+	 * @throws InvalidArgumentException
2606
+	 * @throws InvalidDataTypeException
2607
+	 * @throws InvalidInterfaceException
2608
+	 */
2609
+	public function _reg_registrant_side_meta_box()
2610
+	{
2611
+		/*@var $attendee EE_Attendee */
2612
+		$att_check = $this->_registration->attendee();
2613
+		$attendee  = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2614
+		//now let's determine if this is not the primary registration.  If it isn't then we set the
2615
+		//primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2616
+		//primary registration object (that way we know if we need to show create button or not)
2617
+		if ( ! $this->_registration->is_primary_registrant()) {
2618
+			$primary_registration = $this->_registration->get_primary_registration();
2619
+			$primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2620
+				: null;
2621
+			if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2622
+				//in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2623
+				//custom attendee object so let's not worry about the primary reg.
2624
+				$primary_registration = null;
2625
+			}
2626
+		} else {
2627
+			$primary_registration = null;
2628
+		}
2629
+		$this->_template_args['ATT_ID']            = $attendee->ID();
2630
+		$this->_template_args['fname']             = $attendee->fname();
2631
+		$this->_template_args['lname']             = $attendee->lname();
2632
+		$this->_template_args['email']             = $attendee->email();
2633
+		$this->_template_args['phone']             = $attendee->phone();
2634
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2635
+		//edit link
2636
+		$this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2637
+			'action' => 'edit_attendee',
2638
+			'post'   => $attendee->ID(),
2639
+		), REG_ADMIN_URL);
2640
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2641
+		//create link
2642
+		$this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2643
+			? EE_Admin_Page::add_query_args_and_nonce(array(
2644
+				'action'  => 'duplicate_attendee',
2645
+				'_REG_ID' => $this->_registration->ID(),
2646
+			), REG_ADMIN_URL) : '';
2647
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2648
+		$this->_template_args['att_check']    = $att_check;
2649
+		$template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2650
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2651
+	}
2652
+
2653
+
2654
+	/**
2655
+	 * trash or restore registrations
2656
+	 *
2657
+	 * @param  boolean $trash whether to archive or restore
2658
+	 * @return void
2659
+	 * @throws EE_Error
2660
+	 * @throws InvalidArgumentException
2661
+	 * @throws InvalidDataTypeException
2662
+	 * @throws InvalidInterfaceException
2663
+	 * @throws RuntimeException
2664
+	 * @access protected
2665
+	 */
2666
+	protected function _trash_or_restore_registrations($trash = true)
2667
+	{
2668
+		//if empty _REG_ID then get out because there's nothing to do
2669
+		if (empty($this->_req_data['_REG_ID'])) {
2670
+			EE_Error::add_error(
2671
+				sprintf(
2672
+					esc_html__(
2673
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2674
+						'event_espresso'
2675
+					),
2676
+					$trash ? 'trash' : 'restore'
2677
+				),
2678
+				__FILE__, __LINE__, __FUNCTION__
2679
+			);
2680
+			$this->_redirect_after_action(false, '', '', array(), true);
2681
+		}
2682
+		$success = 0;
2683
+		$overwrite_msgs = false;
2684
+		//Checkboxes
2685
+		if ( ! is_array($this->_req_data['_REG_ID'])) {
2686
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2687
+		}
2688
+		$reg_count = count($this->_req_data['_REG_ID']);
2689
+		// cycle thru checkboxes
2690
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2691
+			/** @var EE_Registration $REG */
2692
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2693
+			$payments = $REG->registration_payments();
2694
+			if (! empty($payments)) {
2695
+				$name = $REG->attendee() instanceof EE_Attendee
2696
+					? $REG->attendee()->full_name()
2697
+					: esc_html__('Unknown Attendee', 'event_espresso');
2698
+				$overwrite_msgs = true;
2699
+				EE_Error::add_error(
2700
+					sprintf(
2701
+						esc_html__(
2702
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2703
+							'event_espresso'
2704
+						),
2705
+						$name
2706
+					),
2707
+					__FILE__, __FUNCTION__, __LINE__
2708
+				);
2709
+				//can't trash this registration because it has payments.
2710
+				continue;
2711
+			}
2712
+			$updated = $trash ? $REG->delete() : $REG->restore();
2713
+			if ($updated) {
2714
+				$success++;
2715
+			}
2716
+		}
2717
+		$this->_redirect_after_action(
2718
+			$success === $reg_count, // were ALL registrations affected?
2719
+			$success > 1
2720
+				? esc_html__('Registrations', 'event_espresso')
2721
+				: esc_html__('Registration', 'event_espresso'),
2722
+			$trash
2723
+				? esc_html__('moved to the trash', 'event_espresso')
2724
+				: esc_html__('restored', 'event_espresso'),
2725
+			array('action' => 'default'),
2726
+			$overwrite_msgs
2727
+		);
2728
+	}
2729
+
2730
+
2731
+	/**
2732
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2733
+	 * registration but also.
2734
+	 * 1. Removing relations to EE_Attendee
2735
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2736
+	 * ALSO trashed.
2737
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2738
+	 * 4. Removing relationships between all tickets and the related registrations
2739
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2740
+	 * 6. Deleting permanently any related Checkins.
2741
+	 *
2742
+	 * @return void
2743
+	 * @throws EE_Error
2744
+	 * @throws InvalidArgumentException
2745
+	 * @throws InvalidDataTypeException
2746
+	 * @throws InvalidInterfaceException
2747
+	 */
2748
+	protected function _delete_registrations()
2749
+	{
2750
+		$REG_MDL = EEM_Registration::instance();
2751
+		$success = 1;
2752
+		//Checkboxes
2753
+		if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2754
+			// if array has more than one element than success message should be plural
2755
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2756
+			// cycle thru checkboxes
2757
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2758
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2759
+				if ( ! $REG instanceof EE_Registration) {
2760
+					continue;
2761
+				}
2762
+				$deleted = $this->_delete_registration($REG);
2763
+				if ( ! $deleted) {
2764
+					$success = 0;
2765
+				}
2766
+			}
2767
+		} else {
2768
+			// grab single id and delete
2769
+			$REG_ID  = $this->_req_data['_REG_ID'];
2770
+			$REG     = $REG_MDL->get_one_by_ID($REG_ID);
2771
+			$deleted = $this->_delete_registration($REG);
2772
+			if ( ! $deleted) {
2773
+				$success = 0;
2774
+			}
2775
+		}
2776
+		$what        = $success > 1
2777
+			? esc_html__('Registrations', 'event_espresso')
2778
+			: esc_html__('Registration', 'event_espresso');
2779
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2780
+		$this->_redirect_after_action(
2781
+			$success,
2782
+			$what,
2783
+			$action_desc,
2784
+			array('action' => 'default'),
2785
+			true
2786
+		);
2787
+	}
2788
+
2789
+
2790
+	/**
2791
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2792
+	 * models get affected.
2793
+	 *
2794
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2795
+	 * @return bool true = successful deletion, false = fail.
2796
+	 * @throws EE_Error
2797
+	 */
2798
+	protected function _delete_registration(EE_Registration $REG)
2799
+	{
2800
+		//first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2801
+		//registrations on the transaction that are NOT trashed.
2802
+		$TXN         = $REG->get_first_related('Transaction');
2803
+		$REGS        = $TXN->get_many_related('Registration');
2804
+		$all_trashed = true;
2805
+		foreach ($REGS as $registration) {
2806
+			if ( ! $registration->get('REG_deleted')) {
2807
+				$all_trashed = false;
2808
+			}
2809
+		}
2810
+		if ( ! $all_trashed) {
2811
+			EE_Error::add_error(
2812
+				esc_html__(
2813
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2814
+					'event_espresso'
2815
+				),
2816
+				__FILE__, __FUNCTION__, __LINE__
2817
+			);
2818
+			return false;
2819
+		}
2820
+		//k made it here so that means we can delete all the related transactions and their answers (but let's do them
2821
+		//separately from THIS one).
2822
+		foreach ($REGS as $registration) {
2823
+			//delete related answers
2824
+			$registration->delete_related_permanently('Answer');
2825
+			//remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2826
+			$attendee = $registration->get_first_related('Attendee');
2827
+			if ($attendee instanceof EE_Attendee) {
2828
+				$registration->_remove_relation_to($attendee, 'Attendee');
2829
+			}
2830
+			//now remove relationships to tickets on this registration.
2831
+			$registration->_remove_relations('Ticket');
2832
+			//now delete permanently the checkins related to this registration.
2833
+			$registration->delete_related_permanently('Checkin');
2834
+			if ($registration->ID() === $REG->ID()) {
2835
+				continue;
2836
+			} //we don't want to delete permanently the existing registration just yet.
2837
+			//remove relation to transaction for these registrations if NOT the existing registrations
2838
+			$registration->_remove_relations('Transaction');
2839
+			//delete permanently any related messages.
2840
+			$registration->delete_related_permanently('Message');
2841
+			//now delete this registration permanently
2842
+			$registration->delete_permanently();
2843
+		}
2844
+		//now all related registrations on the transaction are handled.  So let's just handle this registration itself
2845
+		// (the transaction and line items should be all that's left).
2846
+		// delete the line items related to the transaction for this registration.
2847
+		$TXN->delete_related_permanently('Line_Item');
2848
+		//we need to remove all the relationships on the transaction
2849
+		$TXN->delete_related_permanently('Payment');
2850
+		$TXN->delete_related_permanently('Extra_Meta');
2851
+		$TXN->delete_related_permanently('Message');
2852
+		//now we can delete this REG permanently (and the transaction of course)
2853
+		$REG->delete_related_permanently('Transaction');
2854
+		return $REG->delete_permanently();
2855
+	}
2856
+
2857
+
2858
+	/**
2859
+	 *    generates HTML for the Register New Attendee Admin page
2860
+	 *
2861
+	 * @access private
2862
+	 * @throws DomainException
2863
+	 * @throws EE_Error
2864
+	 */
2865
+	public function new_registration()
2866
+	{
2867
+		if ( ! $this->_set_reg_event()) {
2868
+			throw new EE_Error(
2869
+				esc_html__(
2870
+					'Unable to continue with registering because there is no Event ID in the request',
2871
+					'event_espresso'
2872
+				)
2873
+			);
2874
+		}
2875
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2876
+		// gotta start with a clean slate if we're not coming here via ajax
2877
+		if ( ! defined('DOING_AJAX')
2878
+			 && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2879
+		) {
2880
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2881
+		}
2882
+		$this->_template_args['event_name'] = '';
2883
+		// event name
2884
+		if ($this->_reg_event) {
2885
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2886
+			$edit_event_url                     = self::add_query_args_and_nonce(array(
2887
+				'action' => 'edit',
2888
+				'post'   => $this->_reg_event->ID(),
2889
+			), EVENTS_ADMIN_URL);
2890
+			$edit_event_lnk                     = '<a href="'
2891
+												  . $edit_event_url
2892
+												  . '" title="'
2893
+												  . esc_attr__('Edit ', 'event_espresso')
2894
+												  . $this->_reg_event->name()
2895
+												  . '">'
2896
+												  . esc_html__('Edit Event', 'event_espresso')
2897
+												  . '</a>';
2898
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2899
+												   . $edit_event_lnk
2900
+												   . '</span>';
2901
+		}
2902
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2903
+		if (defined('DOING_AJAX')) {
2904
+			$this->_return_json();
2905
+		}
2906
+		// grab header
2907
+		$template_path                              =
2908
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2909
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2910
+			$this->_template_args, true);
2911
+		//$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2912
+		// the details template wrapper
2913
+		$this->display_admin_page_with_sidebar();
2914
+	}
2915
+
2916
+
2917
+	/**
2918
+	 * This returns the content for a registration step
2919
+	 *
2920
+	 * @access protected
2921
+	 * @return string html
2922
+	 * @throws DomainException
2923
+	 * @throws EE_Error
2924
+	 * @throws InvalidArgumentException
2925
+	 * @throws InvalidDataTypeException
2926
+	 * @throws InvalidInterfaceException
2927
+	 */
2928
+	protected function _get_registration_step_content()
2929
+	{
2930
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2931
+			$warning_msg = sprintf(
2932
+				esc_html__(
2933
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2934
+					'event_espresso'
2935
+				),
2936
+				'<br />',
2937
+				'<h3 class="important-notice">',
2938
+				'</h3>',
2939
+				'<div class="float-right">',
2940
+				'<span id="redirect_timer" class="important-notice">30</span>',
2941
+				'</div>',
2942
+				'<b>',
2943
+				'</b>'
2944
+			);
2945
+			return '
2946 2946
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2947 2947
 	<script >
2948 2948
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2955,841 +2955,841 @@  discard block
 block discarded – undo
2955 2955
 	        }
2956 2956
 	    }, 800 );
2957 2957
 	</script >';
2958
-        }
2959
-        $template_args = array(
2960
-            'title'                    => '',
2961
-            'content'                  => '',
2962
-            'step_button_text'         => '',
2963
-            'show_notification_toggle' => false,
2964
-        );
2965
-        //to indicate we're processing a new registration
2966
-        $hidden_fields = array(
2967
-            'processing_registration' => array(
2968
-                'type'  => 'hidden',
2969
-                'value' => 0,
2970
-            ),
2971
-            'event_id'                => array(
2972
-                'type'  => 'hidden',
2973
-                'value' => $this->_reg_event->ID(),
2974
-            ),
2975
-        );
2976
-        //if the cart is empty then we know we're at step one so we'll display ticket selector
2977
-        $cart = EE_Registry::instance()->SSN->cart();
2978
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2979
-        switch ($step) {
2980
-            case 'ticket' :
2981
-                $hidden_fields['processing_registration']['value'] = 1;
2982
-                $template_args['title']                            = esc_html__(
2983
-                    'Step One: Select the Ticket for this registration',
2984
-                    'event_espresso'
2985
-                );
2986
-                $template_args['content']                          =
2987
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2988
-                $template_args['step_button_text']                 = esc_html__(
2989
-                    'Add Tickets and Continue to Registrant Details',
2990
-                    'event_espresso'
2991
-                );
2992
-                $template_args['show_notification_toggle']         = false;
2993
-                break;
2994
-            case 'questions' :
2995
-                $hidden_fields['processing_registration']['value'] = 2;
2996
-                $template_args['title']                            = esc_html__(
2997
-                    'Step Two: Add Registrant Details for this Registration',
2998
-                    'event_espresso'
2999
-                );
3000
-                //in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3001
-                // properly by the first process_reg_step run.
3002
-                $template_args['content']                  =
3003
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
3004
-                $template_args['step_button_text']         = esc_html__(
3005
-                    'Save Registration and Continue to Details',
3006
-                    'event_espresso'
3007
-                );
3008
-                $template_args['show_notification_toggle'] = true;
3009
-                break;
3010
-        }
3011
-        //we come back to the process_registration_step route.
3012
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3013
-        return EEH_Template::display_template(
3014
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3015
-            $template_args,
3016
-            true
3017
-        );
3018
-    }
3019
-
3020
-
3021
-    /**
3022
-     *        set_reg_event
3023
-     *
3024
-     * @access private
3025
-     * @return bool
3026
-     * @throws EE_Error
3027
-     * @throws InvalidArgumentException
3028
-     * @throws InvalidDataTypeException
3029
-     * @throws InvalidInterfaceException
3030
-     */
3031
-    private function _set_reg_event()
3032
-    {
3033
-        if (is_object($this->_reg_event)) {
3034
-            return true;
3035
-        }
3036
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3037
-        if ( ! $EVT_ID) {
3038
-            return false;
3039
-        }
3040
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3041
-        return true;
3042
-    }
3043
-
3044
-
3045
-    /**
3046
-     * process_reg_step
3047
-     *
3048
-     * @access        public
3049
-     * @return string
3050
-     * @throws DomainException
3051
-     * @throws EE_Error
3052
-     * @throws InvalidArgumentException
3053
-     * @throws InvalidDataTypeException
3054
-     * @throws InvalidInterfaceException
3055
-     * @throws ReflectionException
3056
-     * @throws RuntimeException
3057
-     */
3058
-    public function process_reg_step()
3059
-    {
3060
-        EE_System::do_not_cache();
3061
-        $this->_set_reg_event();
3062
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3063
-        EE_Registry::instance()->REQ->set('uts', time());
3064
-        //what step are we on?
3065
-        $cart = EE_Registry::instance()->SSN->cart();
3066
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3067
-        //if doing ajax then we need to verify the nonce
3068
-        if (defined('DOING_AJAX')) {
3069
-            $nonce = isset($this->_req_data[$this->_req_nonce])
3070
-                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3071
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3072
-        }
3073
-        switch ($step) {
3074
-            case 'ticket' :
3075
-                //process ticket selection
3076
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3077
-                if ($success) {
3078
-                    EE_Error::add_success(
3079
-                        esc_html__(
3080
-                            'Tickets Selected. Now complete the registration.',
3081
-                            'event_espresso'
3082
-                        )
3083
-                    );
3084
-                } else {
3085
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3086
-                }
3087
-                if (defined('DOING_AJAX')) {
3088
-                    $this->new_registration(); //display next step
3089
-                } else {
3090
-                    $query_args = array(
3091
-                        'action'                  => 'new_registration',
3092
-                        'processing_registration' => 1,
3093
-                        'event_id'                => $this->_reg_event->ID(),
3094
-                        'uts'                     => time(),
3095
-                    );
3096
-                    $this->_redirect_after_action(
3097
-                        false,
3098
-                        '',
3099
-                        '',
3100
-                        $query_args,
3101
-                        true
3102
-                    );
3103
-                }
3104
-                break;
3105
-            case 'questions' :
3106
-                if (! isset(
3107
-                    $this->_req_data['txn_reg_status_change'],
3108
-                    $this->_req_data['txn_reg_status_change']['send_notifications'])
3109
-                ) {
3110
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3111
-                }
3112
-                //process registration
3113
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3114
-                if ($cart instanceof EE_Cart) {
3115
-                    $grand_total = $cart->get_cart_grand_total();
3116
-                    if ($grand_total instanceof EE_Line_Item) {
3117
-                        $grand_total->save_this_and_descendants_to_txn();
3118
-                    }
3119
-                }
3120
-                if ( ! $transaction instanceof EE_Transaction) {
3121
-                    $query_args = array(
3122
-                        'action'                  => 'new_registration',
3123
-                        'processing_registration' => 2,
3124
-                        'event_id'                => $this->_reg_event->ID(),
3125
-                        'uts'                     => time(),
3126
-                    );
3127
-                    if (defined('DOING_AJAX')) {
3128
-                        //display registration form again because there are errors (maybe validation?)
3129
-                        $this->new_registration();
3130
-                        return;
3131
-                    } else {
3132
-                        $this->_redirect_after_action(
3133
-                            false,
3134
-                            '',
3135
-                            '',
3136
-                            $query_args,
3137
-                            true
3138
-                        );
3139
-                        return;
3140
-                    }
3141
-                }
3142
-                // maybe update status, and make sure to save transaction if not done already
3143
-                if ( ! $transaction->update_status_based_on_total_paid()) {
3144
-                    $transaction->save();
3145
-                }
3146
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3147
-                $this->_req_data = array();
3148
-                $query_args      = array(
3149
-                    'action'        => 'redirect_to_txn',
3150
-                    'TXN_ID'        => $transaction->ID(),
3151
-                    'EVT_ID'        => $this->_reg_event->ID(),
3152
-                    'event_name'    => urlencode($this->_reg_event->name()),
3153
-                    'redirect_from' => 'new_registration',
3154
-                );
3155
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3156
-                break;
3157
-        }
3158
-        //what are you looking here for?  Should be nothing to do at this point.
3159
-    }
3160
-
3161
-
3162
-    /**
3163
-     * redirect_to_txn
3164
-     *
3165
-     * @access public
3166
-     * @return void
3167
-     * @throws EE_Error
3168
-     * @throws InvalidArgumentException
3169
-     * @throws InvalidDataTypeException
3170
-     * @throws InvalidInterfaceException
3171
-     */
3172
-    public function redirect_to_txn()
3173
-    {
3174
-        EE_System::do_not_cache();
3175
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3176
-        $query_args = array(
3177
-            'action' => 'view_transaction',
3178
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3179
-            'page'   => 'espresso_transactions',
3180
-        );
3181
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3182
-            $query_args['EVT_ID']        = $this->_req_data['EVT_ID'];
3183
-            $query_args['event_name']    = urlencode($this->_req_data['event_name']);
3184
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3185
-        }
3186
-        EE_Error::add_success(
3187
-            esc_html__(
3188
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3189
-                'event_espresso'
3190
-            )
3191
-        );
3192
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3193
-    }
3194
-
3195
-
3196
-    /**
3197
-     *        generates HTML for the Attendee Contact List
3198
-     *
3199
-     * @access protected
3200
-     * @return void
3201
-     */
3202
-    protected function _attendee_contact_list_table()
3203
-    {
3204
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3205
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3206
-        $this->display_admin_list_table_page_with_no_sidebar();
3207
-    }
3208
-
3209
-
3210
-    /**
3211
-     *        get_attendees
3212
-     *
3213
-     * @param      $per_page
3214
-     * @param bool $count whether to return count or data.
3215
-     * @param bool $trash
3216
-     * @return array
3217
-     * @throws EE_Error
3218
-     * @throws InvalidArgumentException
3219
-     * @throws InvalidDataTypeException
3220
-     * @throws InvalidInterfaceException
3221
-     * @access public
3222
-     */
3223
-    public function get_attendees($per_page, $count = false, $trash = false)
3224
-    {
3225
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3226
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3227
-        $ATT_MDL                    = EEM_Attendee::instance();
3228
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3229
-        switch ($this->_req_data['orderby']) {
3230
-            case 'ATT_ID':
3231
-                $orderby = 'ATT_ID';
3232
-                break;
3233
-            case 'ATT_fname':
3234
-                $orderby = 'ATT_fname';
3235
-                break;
3236
-            case 'ATT_email':
3237
-                $orderby = 'ATT_email';
3238
-                break;
3239
-            case 'ATT_city':
3240
-                $orderby = 'ATT_city';
3241
-                break;
3242
-            case 'STA_ID':
3243
-                $orderby = 'STA_ID';
3244
-                break;
3245
-            case 'CNT_ID':
3246
-                $orderby = 'CNT_ID';
3247
-                break;
3248
-            case 'Registration_Count':
3249
-                $orderby = 'Registration_Count';
3250
-                break;
3251
-            default:
3252
-                $orderby = 'ATT_lname';
3253
-        }
3254
-        $sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3255
-            ? $this->_req_data['order']
3256
-            : 'ASC';
3257
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3258
-            ? $this->_req_data['paged']
3259
-            : 1;
3260
-        $per_page     = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3261
-        $per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3262
-            ? $this->_req_data['perpage']
3263
-            : $per_page;
3264
-        $_where       = array();
3265
-        if ( ! empty($this->_req_data['s'])) {
3266
-            $sstr         = '%' . $this->_req_data['s'] . '%';
3267
-            $_where['OR'] = array(
3268
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3269
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3270
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3271
-                'ATT_fname'                         => array('LIKE', $sstr),
3272
-                'ATT_lname'                         => array('LIKE', $sstr),
3273
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3274
-                'ATT_email'                         => array('LIKE', $sstr),
3275
-                'ATT_address'                       => array('LIKE', $sstr),
3276
-                'ATT_address2'                      => array('LIKE', $sstr),
3277
-                'ATT_city'                          => array('LIKE', $sstr),
3278
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3279
-                'State.STA_name'                    => array('LIKE', $sstr),
3280
-                'ATT_phone'                         => array('LIKE', $sstr),
3281
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3282
-                'Registration.REG_code'             => array('LIKE', $sstr),
3283
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3284
-            );
3285
-        }
3286
-        $offset = ($current_page - 1) * $per_page;
3287
-        $limit  = $count ? null : array($offset, $per_page);
3288
-        $query_args = array(
3289
-            $_where,
3290
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3291
-            'limit' => $limit
3292
-        );
3293
-        if (! $count) {
3294
-            $query_args['order_by'] = array($orderby => $sort);
3295
-        }
3296
-        if ($trash) {
3297
-            $query_args[0]['status'] = array('!=', 'publish');
3298
-            $all_attendees    = $count
3299
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3300
-                : $ATT_MDL->get_all($query_args);
3301
-        } else {
3302
-            $query_args[0]['status'] = array('IN', array('publish'));
3303
-            $all_attendees    = $count
3304
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3305
-                : $ATT_MDL->get_all($query_args);
3306
-        }
3307
-        return $all_attendees;
3308
-    }
3309
-
3310
-
3311
-    /**
3312
-     * This is just taking care of resending the registration confirmation
3313
-     *
3314
-     * @access protected
3315
-     * @return void
3316
-     */
3317
-    protected function _resend_registration()
3318
-    {
3319
-        $this->_process_resend_registration();
3320
-        $query_args = isset($this->_req_data['redirect_to'])
3321
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3322
-            : array('action' => 'default');
3323
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3324
-    }
3325
-
3326
-    /**
3327
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3328
-     * to use when selecting registrations
3329
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3330
-     *                                                     the query parameters from the request
3331
-     * @return void ends the request with a redirect or download
3332
-     */
3333
-    public function _registrations_report_base( $method_name_for_getting_query_params )
3334
-    {
3335
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3336
-            wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3337
-                array(
3338
-                    'page'        => 'espresso_batch',
3339
-                    'batch'       => 'file',
3340
-                    'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3341
-                    'filters'     => urlencode(
3342
-                        serialize(
3343
-                            call_user_func(
3344
-                                array( $this, $method_name_for_getting_query_params ),
3345
-                                EEH_Array::is_set(
3346
-                                    $this->_req_data,
3347
-                                    'filters',
3348
-                                    array()
3349
-                                )
3350
-                            )
3351
-                        )
3352
-                ),
3353
-                'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3354
-                'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3355
-                'return_url'  => urlencode($this->_req_data['return_url']),
3356
-            )));
3357
-        } else {
3358
-            $new_request_args = array(
3359
-                'export' => 'report',
3360
-                'action' => 'registrations_report_for_event',
3361
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3362
-            );
3363
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3364
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3365
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3366
-                $EE_Export = EE_Export::instance($this->_req_data);
3367
-                $EE_Export->export();
3368
-            }
3369
-        }
3370
-    }
3371
-
3372
-
3373
-
3374
-    /**
3375
-     * Creates a registration report using only query parameters in the request
3376
-     * @return void
3377
-     */
3378
-    public function _registrations_report()
3379
-    {
3380
-        $this->_registrations_report_base('_get_registration_query_parameters');
3381
-    }
3382
-
3383
-
3384
-    public function _contact_list_export()
3385
-    {
3386
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3387
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3388
-            $EE_Export = EE_Export::instance($this->_req_data);
3389
-            $EE_Export->export_attendees();
3390
-        }
3391
-    }
3392
-
3393
-
3394
-    public function _contact_list_report()
3395
-    {
3396
-        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3397
-            wp_redirect(EE_Admin_Page::add_query_args_and_nonce(array(
3398
-                'page'        => 'espresso_batch',
3399
-                'batch'       => 'file',
3400
-                'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3401
-                'return_url'  => urlencode($this->_req_data['return_url']),
3402
-            )));
3403
-        } else {
3404
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3405
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3406
-                $EE_Export = EE_Export::instance($this->_req_data);
3407
-                $EE_Export->report_attendees();
3408
-            }
3409
-        }
3410
-    }
3411
-
3412
-
3413
-
3414
-
3415
-
3416
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3417
-    /**
3418
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3419
-     *
3420
-     * @return void
3421
-     * @throws EE_Error
3422
-     * @throws InvalidArgumentException
3423
-     * @throws InvalidDataTypeException
3424
-     * @throws InvalidInterfaceException
3425
-     */
3426
-    protected function _duplicate_attendee()
3427
-    {
3428
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3429
-        //verify we have necessary info
3430
-        if (empty($this->_req_data['_REG_ID'])) {
3431
-            EE_Error::add_error(
3432
-                esc_html__(
3433
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3434
-                    'event_espresso'
3435
-                ), __FILE__, __LINE__, __FUNCTION__
3436
-            );
3437
-            $query_args = array('action' => $action);
3438
-            $this->_redirect_after_action('', '', '', $query_args, true);
3439
-        }
3440
-        //okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3441
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3442
-        $attendee     = $registration->attendee();
3443
-        //remove relation of existing attendee on registration
3444
-        $registration->_remove_relation_to($attendee, 'Attendee');
3445
-        //new attendee
3446
-        $new_attendee = clone $attendee;
3447
-        $new_attendee->set('ATT_ID', 0);
3448
-        $new_attendee->save();
3449
-        //add new attendee to reg
3450
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3451
-        EE_Error::add_success(
3452
-            esc_html__(
3453
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3454
-                'event_espresso'
3455
-            )
3456
-        );
3457
-        //redirect to edit page for attendee
3458
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3459
-        $this->_redirect_after_action('', '', '', $query_args, true);
3460
-    }
3461
-
3462
-
3463
-    /**
3464
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3465
-     * @param int      $post_id
3466
-     * @param WP_POST $post
3467
-     * @throws DomainException
3468
-     * @throws EE_Error
3469
-     * @throws InvalidArgumentException
3470
-     * @throws InvalidDataTypeException
3471
-     * @throws InvalidInterfaceException
3472
-     * @throws LogicException
3473
-     * @throws InvalidFormSubmissionException
3474
-     */
3475
-    protected function _insert_update_cpt_item($post_id, $post)
3476
-    {
3477
-        $success  = true;
3478
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3479
-            ? EEM_Attendee::instance()->get_one_by_ID($post_id)
3480
-            : null;
3481
-        //for attendee updates
3482
-        if ($attendee instanceof EE_Attendee) {
3483
-            //note we should only be UPDATING attendees at this point.
3484
-            $updated_fields = array(
3485
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3486
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3487
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3488
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3489
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3490
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3491
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3492
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3493
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3494
-            );
3495
-            foreach ($updated_fields as $field => $value) {
3496
-                $attendee->set($field, $value);
3497
-            }
3498
-
3499
-            //process contact details metabox form handler (which will also save the attendee)
3500
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3501
-            $success = $contact_details_form->process($this->_req_data);
3502
-
3503
-            $attendee_update_callbacks = apply_filters(
3504
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3505
-                array()
3506
-            );
3507
-            foreach ($attendee_update_callbacks as $a_callback) {
3508
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3509
-                    throw new EE_Error(
3510
-                        sprintf(
3511
-                            esc_html__(
3512
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3513
-                                'event_espresso'
3514
-                            ),
3515
-                            $a_callback
3516
-                        )
3517
-                    );
3518
-                }
3519
-            }
3520
-        }
3521
-
3522
-        if ($success === false) {
3523
-            EE_Error::add_error(
3524
-                esc_html__(
3525
-                    'Something went wrong with updating the meta table data for the registration.',
3526
-                    'event_espresso'
3527
-                ),
3528
-                __FILE__, __FUNCTION__, __LINE__
3529
-            );
3530
-        }
3531
-    }
3532
-
3533
-
3534
-    public function trash_cpt_item($post_id)
3535
-    {
3536
-    }
3537
-
3538
-
3539
-    public function delete_cpt_item($post_id)
3540
-    {
3541
-    }
3542
-
3543
-
3544
-    public function restore_cpt_item($post_id)
3545
-    {
3546
-    }
3547
-
3548
-
3549
-    protected function _restore_cpt_item($post_id, $revision_id)
3550
-    {
3551
-    }
3552
-
3553
-
3554
-    public function attendee_editor_metaboxes()
3555
-    {
3556
-        $this->verify_cpt_object();
3557
-        remove_meta_box(
3558
-            'postexcerpt',
3559
-            esc_html__('Excerpt', 'event_espresso'),
3560
-            'post_excerpt_meta_box',
3561
-            $this->_cpt_routes[$this->_req_action],
3562
-            'normal',
3563
-            'core'
3564
-        );
3565
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3566
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3567
-            add_meta_box(
3568
-                'postexcerpt',
3569
-                esc_html__('Short Biography', 'event_espresso'),
3570
-                'post_excerpt_meta_box',
3571
-                $this->_cpt_routes[$this->_req_action],
3572
-                'normal'
3573
-            );
3574
-        }
3575
-        if (post_type_supports('espresso_attendees', 'comments')) {
3576
-            add_meta_box(
3577
-                'commentsdiv',
3578
-                esc_html__('Notes on the Contact', 'event_espresso'),
3579
-                'post_comment_meta_box',
3580
-                $this->_cpt_routes[$this->_req_action],
3581
-                'normal',
3582
-                'core'
3583
-            );
3584
-        }
3585
-        add_meta_box(
3586
-            'attendee_contact_info',
3587
-            esc_html__('Contact Info', 'event_espresso'),
3588
-            array($this, 'attendee_contact_info'),
3589
-            $this->_cpt_routes[$this->_req_action],
3590
-            'side',
3591
-            'core'
3592
-        );
3593
-        add_meta_box(
3594
-            'attendee_details_address',
3595
-            esc_html__('Address Details', 'event_espresso'),
3596
-            array($this, 'attendee_address_details'),
3597
-            $this->_cpt_routes[$this->_req_action],
3598
-            'normal',
3599
-            'core'
3600
-        );
3601
-        add_meta_box(
3602
-            'attendee_registrations',
3603
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3604
-            array($this, 'attendee_registrations_meta_box'),
3605
-            $this->_cpt_routes[$this->_req_action],
3606
-            'normal',
3607
-            'high'
3608
-        );
3609
-    }
3610
-
3611
-
3612
-    /**
3613
-     * Metabox for attendee contact info
3614
-     *
3615
-     * @param  WP_Post $post wp post object
3616
-     * @return string attendee contact info ( and form )
3617
-     * @throws EE_Error
3618
-     * @throws InvalidArgumentException
3619
-     * @throws InvalidDataTypeException
3620
-     * @throws InvalidInterfaceException
3621
-     * @throws LogicException
3622
-     * @throws DomainException
3623
-     */
3624
-    public function attendee_contact_info($post)
3625
-    {
3626
-        //get attendee object ( should already have it )
3627
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3628
-        $form->enqueueStylesAndScripts();
3629
-        echo $form->display();
3630
-    }
3631
-
3632
-
3633
-    /**
3634
-     * Return form handler for the contact details metabox
3635
-     *
3636
-     * @param EE_Attendee $attendee
3637
-     * @return AttendeeContactDetailsMetaboxFormHandler
3638
-     * @throws DomainException
3639
-     * @throws InvalidArgumentException
3640
-     * @throws InvalidDataTypeException
3641
-     * @throws InvalidInterfaceException
3642
-     */
3643
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3644
-    {
3645
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3646
-    }
3647
-
3648
-
3649
-    /**
3650
-     * Metabox for attendee details
3651
-     *
3652
-     * @param  WP_Post $post wp post object
3653
-     * @throws DomainException
3654
-     */
3655
-    public function attendee_address_details($post)
3656
-    {
3657
-        //get attendee object (should already have it)
3658
-        $this->_template_args['attendee']     = $this->_cpt_model_obj;
3659
-        $this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3660
-            new EE_Question_Form_Input(
3661
-                EE_Question::new_instance(
3662
-                    array(
3663
-                        'QST_ID'           => 0,
3664
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3665
-                        'QST_system'       => 'admin-state',
3666
-                    )
3667
-                ),
3668
-                EE_Answer::new_instance(
3669
-                    array(
3670
-                        'ANS_ID'    => 0,
3671
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3672
-                    )
3673
-                ),
3674
-                array(
3675
-                    'input_id'       => 'STA_ID',
3676
-                    'input_name'     => 'STA_ID',
3677
-                    'input_prefix'   => '',
3678
-                    'append_qstn_id' => false,
3679
-                )
3680
-            )
3681
-        );
3682
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3683
-            new EE_Question_Form_Input(
3684
-                EE_Question::new_instance(
3685
-                    array(
3686
-                        'QST_ID'           => 0,
3687
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3688
-                        'QST_system'       => 'admin-country',
3689
-                    )
3690
-                ),
3691
-                EE_Answer::new_instance(
3692
-                    array(
3693
-                        'ANS_ID'    => 0,
3694
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3695
-                    )
3696
-                ),
3697
-                array(
3698
-                    'input_id'       => 'CNT_ISO',
3699
-                    'input_name'     => 'CNT_ISO',
3700
-                    'input_prefix'   => '',
3701
-                    'append_qstn_id' => false,
3702
-                )
3703
-            )
3704
-        );
3705
-        $template                             =
3706
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3707
-        EEH_Template::display_template($template, $this->_template_args);
3708
-    }
3709
-
3710
-
3711
-    /**
3712
-     *        _attendee_details
3713
-     *
3714
-     * @access protected
3715
-     * @param $post
3716
-     * @return void
3717
-     * @throws DomainException
3718
-     * @throws EE_Error
3719
-     */
3720
-    public function attendee_registrations_meta_box($post)
3721
-    {
3722
-        $this->_template_args['attendee']      = $this->_cpt_model_obj;
3723
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3724
-        $template                              =
3725
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3726
-        EEH_Template::display_template($template, $this->_template_args);
3727
-    }
3728
-
3729
-
3730
-    /**
3731
-     * add in the form fields for the attendee edit
3732
-     *
3733
-     * @param  WP_Post $post wp post object
3734
-     * @return string html for new form.
3735
-     * @throws DomainException
3736
-     */
3737
-    public function after_title_form_fields($post)
3738
-    {
3739
-        if ($post->post_type == 'espresso_attendees') {
3740
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3741
-            $template_args['attendee'] = $this->_cpt_model_obj;
3742
-            EEH_Template::display_template($template, $template_args);
3743
-        }
3744
-    }
3745
-
3746
-
3747
-    /**
3748
-     *        _trash_or_restore_attendee
3749
-     *
3750
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3751
-     * @return void
3752
-     * @throws EE_Error
3753
-     * @throws InvalidArgumentException
3754
-     * @throws InvalidDataTypeException
3755
-     * @throws InvalidInterfaceException
3756
-     * @access protected
3757
-     */
3758
-    protected function _trash_or_restore_attendees($trash = true)
3759
-    {
3760
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3761
-        $ATT_MDL = EEM_Attendee::instance();
3762
-        $success = 1;
3763
-        //Checkboxes
3764
-        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3765
-            // if array has more than one element than success message should be plural
3766
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3767
-            // cycle thru checkboxes
3768
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3769
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3770
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3771
-                if ( ! $updated) {
3772
-                    $success = 0;
3773
-                }
3774
-            }
3775
-        } else {
3776
-            // grab single id and delete
3777
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3778
-            //get attendee
3779
-            $att     = $ATT_MDL->get_one_by_ID($ATT_ID);
3780
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3781
-            $updated = $att->save();
3782
-            if ( ! $updated) {
3783
-                $success = 0;
3784
-            }
3785
-        }
3786
-        $what        = $success > 1
3787
-            ? esc_html__('Contacts', 'event_espresso')
3788
-            : esc_html__('Contact', 'event_espresso');
3789
-        $action_desc = $trash
3790
-            ? esc_html__('moved to the trash', 'event_espresso')
3791
-            : esc_html__('restored', 'event_espresso');
3792
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3793
-    }
2958
+		}
2959
+		$template_args = array(
2960
+			'title'                    => '',
2961
+			'content'                  => '',
2962
+			'step_button_text'         => '',
2963
+			'show_notification_toggle' => false,
2964
+		);
2965
+		//to indicate we're processing a new registration
2966
+		$hidden_fields = array(
2967
+			'processing_registration' => array(
2968
+				'type'  => 'hidden',
2969
+				'value' => 0,
2970
+			),
2971
+			'event_id'                => array(
2972
+				'type'  => 'hidden',
2973
+				'value' => $this->_reg_event->ID(),
2974
+			),
2975
+		);
2976
+		//if the cart is empty then we know we're at step one so we'll display ticket selector
2977
+		$cart = EE_Registry::instance()->SSN->cart();
2978
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2979
+		switch ($step) {
2980
+			case 'ticket' :
2981
+				$hidden_fields['processing_registration']['value'] = 1;
2982
+				$template_args['title']                            = esc_html__(
2983
+					'Step One: Select the Ticket for this registration',
2984
+					'event_espresso'
2985
+				);
2986
+				$template_args['content']                          =
2987
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2988
+				$template_args['step_button_text']                 = esc_html__(
2989
+					'Add Tickets and Continue to Registrant Details',
2990
+					'event_espresso'
2991
+				);
2992
+				$template_args['show_notification_toggle']         = false;
2993
+				break;
2994
+			case 'questions' :
2995
+				$hidden_fields['processing_registration']['value'] = 2;
2996
+				$template_args['title']                            = esc_html__(
2997
+					'Step Two: Add Registrant Details for this Registration',
2998
+					'event_espresso'
2999
+				);
3000
+				//in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3001
+				// properly by the first process_reg_step run.
3002
+				$template_args['content']                  =
3003
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
3004
+				$template_args['step_button_text']         = esc_html__(
3005
+					'Save Registration and Continue to Details',
3006
+					'event_espresso'
3007
+				);
3008
+				$template_args['show_notification_toggle'] = true;
3009
+				break;
3010
+		}
3011
+		//we come back to the process_registration_step route.
3012
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3013
+		return EEH_Template::display_template(
3014
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3015
+			$template_args,
3016
+			true
3017
+		);
3018
+	}
3019
+
3020
+
3021
+	/**
3022
+	 *        set_reg_event
3023
+	 *
3024
+	 * @access private
3025
+	 * @return bool
3026
+	 * @throws EE_Error
3027
+	 * @throws InvalidArgumentException
3028
+	 * @throws InvalidDataTypeException
3029
+	 * @throws InvalidInterfaceException
3030
+	 */
3031
+	private function _set_reg_event()
3032
+	{
3033
+		if (is_object($this->_reg_event)) {
3034
+			return true;
3035
+		}
3036
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3037
+		if ( ! $EVT_ID) {
3038
+			return false;
3039
+		}
3040
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3041
+		return true;
3042
+	}
3043
+
3044
+
3045
+	/**
3046
+	 * process_reg_step
3047
+	 *
3048
+	 * @access        public
3049
+	 * @return string
3050
+	 * @throws DomainException
3051
+	 * @throws EE_Error
3052
+	 * @throws InvalidArgumentException
3053
+	 * @throws InvalidDataTypeException
3054
+	 * @throws InvalidInterfaceException
3055
+	 * @throws ReflectionException
3056
+	 * @throws RuntimeException
3057
+	 */
3058
+	public function process_reg_step()
3059
+	{
3060
+		EE_System::do_not_cache();
3061
+		$this->_set_reg_event();
3062
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3063
+		EE_Registry::instance()->REQ->set('uts', time());
3064
+		//what step are we on?
3065
+		$cart = EE_Registry::instance()->SSN->cart();
3066
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3067
+		//if doing ajax then we need to verify the nonce
3068
+		if (defined('DOING_AJAX')) {
3069
+			$nonce = isset($this->_req_data[$this->_req_nonce])
3070
+				? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3071
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3072
+		}
3073
+		switch ($step) {
3074
+			case 'ticket' :
3075
+				//process ticket selection
3076
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3077
+				if ($success) {
3078
+					EE_Error::add_success(
3079
+						esc_html__(
3080
+							'Tickets Selected. Now complete the registration.',
3081
+							'event_espresso'
3082
+						)
3083
+					);
3084
+				} else {
3085
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3086
+				}
3087
+				if (defined('DOING_AJAX')) {
3088
+					$this->new_registration(); //display next step
3089
+				} else {
3090
+					$query_args = array(
3091
+						'action'                  => 'new_registration',
3092
+						'processing_registration' => 1,
3093
+						'event_id'                => $this->_reg_event->ID(),
3094
+						'uts'                     => time(),
3095
+					);
3096
+					$this->_redirect_after_action(
3097
+						false,
3098
+						'',
3099
+						'',
3100
+						$query_args,
3101
+						true
3102
+					);
3103
+				}
3104
+				break;
3105
+			case 'questions' :
3106
+				if (! isset(
3107
+					$this->_req_data['txn_reg_status_change'],
3108
+					$this->_req_data['txn_reg_status_change']['send_notifications'])
3109
+				) {
3110
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3111
+				}
3112
+				//process registration
3113
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3114
+				if ($cart instanceof EE_Cart) {
3115
+					$grand_total = $cart->get_cart_grand_total();
3116
+					if ($grand_total instanceof EE_Line_Item) {
3117
+						$grand_total->save_this_and_descendants_to_txn();
3118
+					}
3119
+				}
3120
+				if ( ! $transaction instanceof EE_Transaction) {
3121
+					$query_args = array(
3122
+						'action'                  => 'new_registration',
3123
+						'processing_registration' => 2,
3124
+						'event_id'                => $this->_reg_event->ID(),
3125
+						'uts'                     => time(),
3126
+					);
3127
+					if (defined('DOING_AJAX')) {
3128
+						//display registration form again because there are errors (maybe validation?)
3129
+						$this->new_registration();
3130
+						return;
3131
+					} else {
3132
+						$this->_redirect_after_action(
3133
+							false,
3134
+							'',
3135
+							'',
3136
+							$query_args,
3137
+							true
3138
+						);
3139
+						return;
3140
+					}
3141
+				}
3142
+				// maybe update status, and make sure to save transaction if not done already
3143
+				if ( ! $transaction->update_status_based_on_total_paid()) {
3144
+					$transaction->save();
3145
+				}
3146
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3147
+				$this->_req_data = array();
3148
+				$query_args      = array(
3149
+					'action'        => 'redirect_to_txn',
3150
+					'TXN_ID'        => $transaction->ID(),
3151
+					'EVT_ID'        => $this->_reg_event->ID(),
3152
+					'event_name'    => urlencode($this->_reg_event->name()),
3153
+					'redirect_from' => 'new_registration',
3154
+				);
3155
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3156
+				break;
3157
+		}
3158
+		//what are you looking here for?  Should be nothing to do at this point.
3159
+	}
3160
+
3161
+
3162
+	/**
3163
+	 * redirect_to_txn
3164
+	 *
3165
+	 * @access public
3166
+	 * @return void
3167
+	 * @throws EE_Error
3168
+	 * @throws InvalidArgumentException
3169
+	 * @throws InvalidDataTypeException
3170
+	 * @throws InvalidInterfaceException
3171
+	 */
3172
+	public function redirect_to_txn()
3173
+	{
3174
+		EE_System::do_not_cache();
3175
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3176
+		$query_args = array(
3177
+			'action' => 'view_transaction',
3178
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3179
+			'page'   => 'espresso_transactions',
3180
+		);
3181
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3182
+			$query_args['EVT_ID']        = $this->_req_data['EVT_ID'];
3183
+			$query_args['event_name']    = urlencode($this->_req_data['event_name']);
3184
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3185
+		}
3186
+		EE_Error::add_success(
3187
+			esc_html__(
3188
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3189
+				'event_espresso'
3190
+			)
3191
+		);
3192
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3193
+	}
3194
+
3195
+
3196
+	/**
3197
+	 *        generates HTML for the Attendee Contact List
3198
+	 *
3199
+	 * @access protected
3200
+	 * @return void
3201
+	 */
3202
+	protected function _attendee_contact_list_table()
3203
+	{
3204
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3205
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3206
+		$this->display_admin_list_table_page_with_no_sidebar();
3207
+	}
3208
+
3209
+
3210
+	/**
3211
+	 *        get_attendees
3212
+	 *
3213
+	 * @param      $per_page
3214
+	 * @param bool $count whether to return count or data.
3215
+	 * @param bool $trash
3216
+	 * @return array
3217
+	 * @throws EE_Error
3218
+	 * @throws InvalidArgumentException
3219
+	 * @throws InvalidDataTypeException
3220
+	 * @throws InvalidInterfaceException
3221
+	 * @access public
3222
+	 */
3223
+	public function get_attendees($per_page, $count = false, $trash = false)
3224
+	{
3225
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3226
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3227
+		$ATT_MDL                    = EEM_Attendee::instance();
3228
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3229
+		switch ($this->_req_data['orderby']) {
3230
+			case 'ATT_ID':
3231
+				$orderby = 'ATT_ID';
3232
+				break;
3233
+			case 'ATT_fname':
3234
+				$orderby = 'ATT_fname';
3235
+				break;
3236
+			case 'ATT_email':
3237
+				$orderby = 'ATT_email';
3238
+				break;
3239
+			case 'ATT_city':
3240
+				$orderby = 'ATT_city';
3241
+				break;
3242
+			case 'STA_ID':
3243
+				$orderby = 'STA_ID';
3244
+				break;
3245
+			case 'CNT_ID':
3246
+				$orderby = 'CNT_ID';
3247
+				break;
3248
+			case 'Registration_Count':
3249
+				$orderby = 'Registration_Count';
3250
+				break;
3251
+			default:
3252
+				$orderby = 'ATT_lname';
3253
+		}
3254
+		$sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3255
+			? $this->_req_data['order']
3256
+			: 'ASC';
3257
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3258
+			? $this->_req_data['paged']
3259
+			: 1;
3260
+		$per_page     = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3261
+		$per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3262
+			? $this->_req_data['perpage']
3263
+			: $per_page;
3264
+		$_where       = array();
3265
+		if ( ! empty($this->_req_data['s'])) {
3266
+			$sstr         = '%' . $this->_req_data['s'] . '%';
3267
+			$_where['OR'] = array(
3268
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3269
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3270
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3271
+				'ATT_fname'                         => array('LIKE', $sstr),
3272
+				'ATT_lname'                         => array('LIKE', $sstr),
3273
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3274
+				'ATT_email'                         => array('LIKE', $sstr),
3275
+				'ATT_address'                       => array('LIKE', $sstr),
3276
+				'ATT_address2'                      => array('LIKE', $sstr),
3277
+				'ATT_city'                          => array('LIKE', $sstr),
3278
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3279
+				'State.STA_name'                    => array('LIKE', $sstr),
3280
+				'ATT_phone'                         => array('LIKE', $sstr),
3281
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3282
+				'Registration.REG_code'             => array('LIKE', $sstr),
3283
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3284
+			);
3285
+		}
3286
+		$offset = ($current_page - 1) * $per_page;
3287
+		$limit  = $count ? null : array($offset, $per_page);
3288
+		$query_args = array(
3289
+			$_where,
3290
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3291
+			'limit' => $limit
3292
+		);
3293
+		if (! $count) {
3294
+			$query_args['order_by'] = array($orderby => $sort);
3295
+		}
3296
+		if ($trash) {
3297
+			$query_args[0]['status'] = array('!=', 'publish');
3298
+			$all_attendees    = $count
3299
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3300
+				: $ATT_MDL->get_all($query_args);
3301
+		} else {
3302
+			$query_args[0]['status'] = array('IN', array('publish'));
3303
+			$all_attendees    = $count
3304
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3305
+				: $ATT_MDL->get_all($query_args);
3306
+		}
3307
+		return $all_attendees;
3308
+	}
3309
+
3310
+
3311
+	/**
3312
+	 * This is just taking care of resending the registration confirmation
3313
+	 *
3314
+	 * @access protected
3315
+	 * @return void
3316
+	 */
3317
+	protected function _resend_registration()
3318
+	{
3319
+		$this->_process_resend_registration();
3320
+		$query_args = isset($this->_req_data['redirect_to'])
3321
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3322
+			: array('action' => 'default');
3323
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3324
+	}
3325
+
3326
+	/**
3327
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3328
+	 * to use when selecting registrations
3329
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3330
+	 *                                                     the query parameters from the request
3331
+	 * @return void ends the request with a redirect or download
3332
+	 */
3333
+	public function _registrations_report_base( $method_name_for_getting_query_params )
3334
+	{
3335
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3336
+			wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3337
+				array(
3338
+					'page'        => 'espresso_batch',
3339
+					'batch'       => 'file',
3340
+					'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3341
+					'filters'     => urlencode(
3342
+						serialize(
3343
+							call_user_func(
3344
+								array( $this, $method_name_for_getting_query_params ),
3345
+								EEH_Array::is_set(
3346
+									$this->_req_data,
3347
+									'filters',
3348
+									array()
3349
+								)
3350
+							)
3351
+						)
3352
+				),
3353
+				'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3354
+				'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3355
+				'return_url'  => urlencode($this->_req_data['return_url']),
3356
+			)));
3357
+		} else {
3358
+			$new_request_args = array(
3359
+				'export' => 'report',
3360
+				'action' => 'registrations_report_for_event',
3361
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3362
+			);
3363
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3364
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3365
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3366
+				$EE_Export = EE_Export::instance($this->_req_data);
3367
+				$EE_Export->export();
3368
+			}
3369
+		}
3370
+	}
3371
+
3372
+
3373
+
3374
+	/**
3375
+	 * Creates a registration report using only query parameters in the request
3376
+	 * @return void
3377
+	 */
3378
+	public function _registrations_report()
3379
+	{
3380
+		$this->_registrations_report_base('_get_registration_query_parameters');
3381
+	}
3382
+
3383
+
3384
+	public function _contact_list_export()
3385
+	{
3386
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3387
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3388
+			$EE_Export = EE_Export::instance($this->_req_data);
3389
+			$EE_Export->export_attendees();
3390
+		}
3391
+	}
3392
+
3393
+
3394
+	public function _contact_list_report()
3395
+	{
3396
+		if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3397
+			wp_redirect(EE_Admin_Page::add_query_args_and_nonce(array(
3398
+				'page'        => 'espresso_batch',
3399
+				'batch'       => 'file',
3400
+				'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3401
+				'return_url'  => urlencode($this->_req_data['return_url']),
3402
+			)));
3403
+		} else {
3404
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3405
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3406
+				$EE_Export = EE_Export::instance($this->_req_data);
3407
+				$EE_Export->report_attendees();
3408
+			}
3409
+		}
3410
+	}
3411
+
3412
+
3413
+
3414
+
3415
+
3416
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3417
+	/**
3418
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3419
+	 *
3420
+	 * @return void
3421
+	 * @throws EE_Error
3422
+	 * @throws InvalidArgumentException
3423
+	 * @throws InvalidDataTypeException
3424
+	 * @throws InvalidInterfaceException
3425
+	 */
3426
+	protected function _duplicate_attendee()
3427
+	{
3428
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3429
+		//verify we have necessary info
3430
+		if (empty($this->_req_data['_REG_ID'])) {
3431
+			EE_Error::add_error(
3432
+				esc_html__(
3433
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3434
+					'event_espresso'
3435
+				), __FILE__, __LINE__, __FUNCTION__
3436
+			);
3437
+			$query_args = array('action' => $action);
3438
+			$this->_redirect_after_action('', '', '', $query_args, true);
3439
+		}
3440
+		//okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3441
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3442
+		$attendee     = $registration->attendee();
3443
+		//remove relation of existing attendee on registration
3444
+		$registration->_remove_relation_to($attendee, 'Attendee');
3445
+		//new attendee
3446
+		$new_attendee = clone $attendee;
3447
+		$new_attendee->set('ATT_ID', 0);
3448
+		$new_attendee->save();
3449
+		//add new attendee to reg
3450
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3451
+		EE_Error::add_success(
3452
+			esc_html__(
3453
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3454
+				'event_espresso'
3455
+			)
3456
+		);
3457
+		//redirect to edit page for attendee
3458
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3459
+		$this->_redirect_after_action('', '', '', $query_args, true);
3460
+	}
3461
+
3462
+
3463
+	/**
3464
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3465
+	 * @param int      $post_id
3466
+	 * @param WP_POST $post
3467
+	 * @throws DomainException
3468
+	 * @throws EE_Error
3469
+	 * @throws InvalidArgumentException
3470
+	 * @throws InvalidDataTypeException
3471
+	 * @throws InvalidInterfaceException
3472
+	 * @throws LogicException
3473
+	 * @throws InvalidFormSubmissionException
3474
+	 */
3475
+	protected function _insert_update_cpt_item($post_id, $post)
3476
+	{
3477
+		$success  = true;
3478
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3479
+			? EEM_Attendee::instance()->get_one_by_ID($post_id)
3480
+			: null;
3481
+		//for attendee updates
3482
+		if ($attendee instanceof EE_Attendee) {
3483
+			//note we should only be UPDATING attendees at this point.
3484
+			$updated_fields = array(
3485
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3486
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3487
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3488
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3489
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3490
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3491
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3492
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3493
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3494
+			);
3495
+			foreach ($updated_fields as $field => $value) {
3496
+				$attendee->set($field, $value);
3497
+			}
3498
+
3499
+			//process contact details metabox form handler (which will also save the attendee)
3500
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3501
+			$success = $contact_details_form->process($this->_req_data);
3502
+
3503
+			$attendee_update_callbacks = apply_filters(
3504
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3505
+				array()
3506
+			);
3507
+			foreach ($attendee_update_callbacks as $a_callback) {
3508
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3509
+					throw new EE_Error(
3510
+						sprintf(
3511
+							esc_html__(
3512
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3513
+								'event_espresso'
3514
+							),
3515
+							$a_callback
3516
+						)
3517
+					);
3518
+				}
3519
+			}
3520
+		}
3521
+
3522
+		if ($success === false) {
3523
+			EE_Error::add_error(
3524
+				esc_html__(
3525
+					'Something went wrong with updating the meta table data for the registration.',
3526
+					'event_espresso'
3527
+				),
3528
+				__FILE__, __FUNCTION__, __LINE__
3529
+			);
3530
+		}
3531
+	}
3532
+
3533
+
3534
+	public function trash_cpt_item($post_id)
3535
+	{
3536
+	}
3537
+
3538
+
3539
+	public function delete_cpt_item($post_id)
3540
+	{
3541
+	}
3542
+
3543
+
3544
+	public function restore_cpt_item($post_id)
3545
+	{
3546
+	}
3547
+
3548
+
3549
+	protected function _restore_cpt_item($post_id, $revision_id)
3550
+	{
3551
+	}
3552
+
3553
+
3554
+	public function attendee_editor_metaboxes()
3555
+	{
3556
+		$this->verify_cpt_object();
3557
+		remove_meta_box(
3558
+			'postexcerpt',
3559
+			esc_html__('Excerpt', 'event_espresso'),
3560
+			'post_excerpt_meta_box',
3561
+			$this->_cpt_routes[$this->_req_action],
3562
+			'normal',
3563
+			'core'
3564
+		);
3565
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3566
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3567
+			add_meta_box(
3568
+				'postexcerpt',
3569
+				esc_html__('Short Biography', 'event_espresso'),
3570
+				'post_excerpt_meta_box',
3571
+				$this->_cpt_routes[$this->_req_action],
3572
+				'normal'
3573
+			);
3574
+		}
3575
+		if (post_type_supports('espresso_attendees', 'comments')) {
3576
+			add_meta_box(
3577
+				'commentsdiv',
3578
+				esc_html__('Notes on the Contact', 'event_espresso'),
3579
+				'post_comment_meta_box',
3580
+				$this->_cpt_routes[$this->_req_action],
3581
+				'normal',
3582
+				'core'
3583
+			);
3584
+		}
3585
+		add_meta_box(
3586
+			'attendee_contact_info',
3587
+			esc_html__('Contact Info', 'event_espresso'),
3588
+			array($this, 'attendee_contact_info'),
3589
+			$this->_cpt_routes[$this->_req_action],
3590
+			'side',
3591
+			'core'
3592
+		);
3593
+		add_meta_box(
3594
+			'attendee_details_address',
3595
+			esc_html__('Address Details', 'event_espresso'),
3596
+			array($this, 'attendee_address_details'),
3597
+			$this->_cpt_routes[$this->_req_action],
3598
+			'normal',
3599
+			'core'
3600
+		);
3601
+		add_meta_box(
3602
+			'attendee_registrations',
3603
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3604
+			array($this, 'attendee_registrations_meta_box'),
3605
+			$this->_cpt_routes[$this->_req_action],
3606
+			'normal',
3607
+			'high'
3608
+		);
3609
+	}
3610
+
3611
+
3612
+	/**
3613
+	 * Metabox for attendee contact info
3614
+	 *
3615
+	 * @param  WP_Post $post wp post object
3616
+	 * @return string attendee contact info ( and form )
3617
+	 * @throws EE_Error
3618
+	 * @throws InvalidArgumentException
3619
+	 * @throws InvalidDataTypeException
3620
+	 * @throws InvalidInterfaceException
3621
+	 * @throws LogicException
3622
+	 * @throws DomainException
3623
+	 */
3624
+	public function attendee_contact_info($post)
3625
+	{
3626
+		//get attendee object ( should already have it )
3627
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3628
+		$form->enqueueStylesAndScripts();
3629
+		echo $form->display();
3630
+	}
3631
+
3632
+
3633
+	/**
3634
+	 * Return form handler for the contact details metabox
3635
+	 *
3636
+	 * @param EE_Attendee $attendee
3637
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3638
+	 * @throws DomainException
3639
+	 * @throws InvalidArgumentException
3640
+	 * @throws InvalidDataTypeException
3641
+	 * @throws InvalidInterfaceException
3642
+	 */
3643
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3644
+	{
3645
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3646
+	}
3647
+
3648
+
3649
+	/**
3650
+	 * Metabox for attendee details
3651
+	 *
3652
+	 * @param  WP_Post $post wp post object
3653
+	 * @throws DomainException
3654
+	 */
3655
+	public function attendee_address_details($post)
3656
+	{
3657
+		//get attendee object (should already have it)
3658
+		$this->_template_args['attendee']     = $this->_cpt_model_obj;
3659
+		$this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3660
+			new EE_Question_Form_Input(
3661
+				EE_Question::new_instance(
3662
+					array(
3663
+						'QST_ID'           => 0,
3664
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3665
+						'QST_system'       => 'admin-state',
3666
+					)
3667
+				),
3668
+				EE_Answer::new_instance(
3669
+					array(
3670
+						'ANS_ID'    => 0,
3671
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3672
+					)
3673
+				),
3674
+				array(
3675
+					'input_id'       => 'STA_ID',
3676
+					'input_name'     => 'STA_ID',
3677
+					'input_prefix'   => '',
3678
+					'append_qstn_id' => false,
3679
+				)
3680
+			)
3681
+		);
3682
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3683
+			new EE_Question_Form_Input(
3684
+				EE_Question::new_instance(
3685
+					array(
3686
+						'QST_ID'           => 0,
3687
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3688
+						'QST_system'       => 'admin-country',
3689
+					)
3690
+				),
3691
+				EE_Answer::new_instance(
3692
+					array(
3693
+						'ANS_ID'    => 0,
3694
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3695
+					)
3696
+				),
3697
+				array(
3698
+					'input_id'       => 'CNT_ISO',
3699
+					'input_name'     => 'CNT_ISO',
3700
+					'input_prefix'   => '',
3701
+					'append_qstn_id' => false,
3702
+				)
3703
+			)
3704
+		);
3705
+		$template                             =
3706
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3707
+		EEH_Template::display_template($template, $this->_template_args);
3708
+	}
3709
+
3710
+
3711
+	/**
3712
+	 *        _attendee_details
3713
+	 *
3714
+	 * @access protected
3715
+	 * @param $post
3716
+	 * @return void
3717
+	 * @throws DomainException
3718
+	 * @throws EE_Error
3719
+	 */
3720
+	public function attendee_registrations_meta_box($post)
3721
+	{
3722
+		$this->_template_args['attendee']      = $this->_cpt_model_obj;
3723
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3724
+		$template                              =
3725
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3726
+		EEH_Template::display_template($template, $this->_template_args);
3727
+	}
3728
+
3729
+
3730
+	/**
3731
+	 * add in the form fields for the attendee edit
3732
+	 *
3733
+	 * @param  WP_Post $post wp post object
3734
+	 * @return string html for new form.
3735
+	 * @throws DomainException
3736
+	 */
3737
+	public function after_title_form_fields($post)
3738
+	{
3739
+		if ($post->post_type == 'espresso_attendees') {
3740
+			$template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3741
+			$template_args['attendee'] = $this->_cpt_model_obj;
3742
+			EEH_Template::display_template($template, $template_args);
3743
+		}
3744
+	}
3745
+
3746
+
3747
+	/**
3748
+	 *        _trash_or_restore_attendee
3749
+	 *
3750
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3751
+	 * @return void
3752
+	 * @throws EE_Error
3753
+	 * @throws InvalidArgumentException
3754
+	 * @throws InvalidDataTypeException
3755
+	 * @throws InvalidInterfaceException
3756
+	 * @access protected
3757
+	 */
3758
+	protected function _trash_or_restore_attendees($trash = true)
3759
+	{
3760
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3761
+		$ATT_MDL = EEM_Attendee::instance();
3762
+		$success = 1;
3763
+		//Checkboxes
3764
+		if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3765
+			// if array has more than one element than success message should be plural
3766
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3767
+			// cycle thru checkboxes
3768
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3769
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3770
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3771
+				if ( ! $updated) {
3772
+					$success = 0;
3773
+				}
3774
+			}
3775
+		} else {
3776
+			// grab single id and delete
3777
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3778
+			//get attendee
3779
+			$att     = $ATT_MDL->get_one_by_ID($ATT_ID);
3780
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3781
+			$updated = $att->save();
3782
+			if ( ! $updated) {
3783
+				$success = 0;
3784
+			}
3785
+		}
3786
+		$what        = $success > 1
3787
+			? esc_html__('Contacts', 'event_espresso')
3788
+			: esc_html__('Contact', 'event_espresso');
3789
+		$action_desc = $trash
3790
+			? esc_html__('moved to the trash', 'event_espresso')
3791
+			: esc_html__('restored', 'event_espresso');
3792
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3793
+	}
3794 3794
 
3795 3795
 }
Please login to merge, or discard this patch.
Spacing   +93 added lines, -93 removed lines patch added patch discarded remove patch
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
         // when adding a new registration...
77 77
         if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
78 78
             EE_System::do_not_cache();
79
-            if (! isset($this->_req_data['processing_registration'])
79
+            if ( ! isset($this->_req_data['processing_registration'])
80 80
                  || absint($this->_req_data['processing_registration']) !== 1
81 81
             ) {
82 82
                 // and it's NOT the attendee information reg step
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
     public function _set_page_routes()
172 172
     {
173 173
         $this->_get_registration_status_array();
174
-        $reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
174
+        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
175 175
             ? $this->_req_data['_REG_ID'] : 0;
176 176
         $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
177 177
             ? $this->_req_data['reg_status_change_form']['REG_ID']
@@ -669,7 +669,7 @@  discard block
 block discarded – undo
669 669
         //style
670 670
         wp_register_style(
671 671
             'espresso_reg',
672
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
672
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
673 673
             array('ee-admin-css'),
674 674
             EVENT_ESPRESSO_VERSION
675 675
         );
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
         //script
678 678
         wp_register_script(
679 679
             'espresso_reg',
680
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
680
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
681 681
             array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
682 682
             EVENT_ESPRESSO_VERSION,
683 683
             true
@@ -715,7 +715,7 @@  discard block
 block discarded – undo
715 715
         wp_dequeue_style('espresso_reg');
716 716
         wp_register_style(
717 717
             'espresso_att',
718
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
718
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
719 719
             array('ee-admin-css'),
720 720
             EVENT_ESPRESSO_VERSION
721 721
         );
@@ -727,7 +727,7 @@  discard block
 block discarded – undo
727 727
     {
728 728
         wp_register_script(
729 729
             'ee-spco-for-admin',
730
-            REG_ASSETS_URL . 'spco_for_admin.js',
730
+            REG_ASSETS_URL.'spco_for_admin.js',
731 731
             array('underscore', 'jquery'),
732 732
             EVENT_ESPRESSO_VERSION,
733 733
             true
@@ -861,7 +861,7 @@  discard block
 block discarded – undo
861 861
                     'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
862 862
                 ),
863 863
             );
864
-            $this->_views['trash']      = array(
864
+            $this->_views['trash'] = array(
865 865
                 'slug'        => 'trash',
866 866
                 'label'       => esc_html__('Trash', 'event_espresso'),
867 867
                 'count'       => 0,
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
         }
951 951
         $sc_items = array(
952 952
             'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
953
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
954 954
                 'desc'  => EEH_Template::pretty_status(
955 955
                     EEM_Registration::status_id_approved,
956 956
                     false,
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
                 ),
959 959
             ),
960 960
             'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
961
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
962 962
                 'desc'  => EEH_Template::pretty_status(
963 963
                     EEM_Registration::status_id_pending_payment,
964 964
                     false,
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
                 ),
967 967
             ),
968 968
             'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
969
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
970 970
                 'desc'  => EEH_Template::pretty_status(
971 971
                     EEM_Registration::status_id_wait_list,
972 972
                     false,
@@ -974,7 +974,7 @@  discard block
 block discarded – undo
974 974
                 ),
975 975
             ),
976 976
             'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
977
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_incomplete,
978 978
                 'desc'  => EEH_Template::pretty_status(
979 979
                     EEM_Registration::status_id_incomplete,
980 980
                     false,
@@ -982,7 +982,7 @@  discard block
 block discarded – undo
982 982
                 ),
983 983
             ),
984 984
             'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
985
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
986 986
                 'desc'  => EEH_Template::pretty_status(
987 987
                     EEM_Registration::status_id_not_approved,
988 988
                     false,
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
                 ),
991 991
             ),
992 992
             'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
993
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
994 994
                 'desc'  => EEH_Template::pretty_status(
995 995
                     EEM_Registration::status_id_declined,
996 996
                     false,
@@ -998,7 +998,7 @@  discard block
 block discarded – undo
998 998
                 ),
999 999
             ),
1000 1000
             'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1001
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1002 1002
                 'desc'  => EEH_Template::pretty_status(
1003 1003
                     EEM_Registration::status_id_cancelled,
1004 1004
                     false,
@@ -1021,7 +1021,7 @@  discard block
 block discarded – undo
1021 1021
         $EVT_ID                                    = ! empty($this->_req_data['event_id'])
1022 1022
             ? absint($this->_req_data['event_id'])
1023 1023
             : 0;
1024
-        $ATT_ID = !empty($this->_req_data['ATT_ID'])
1024
+        $ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025 1025
             ? absint($this->_req_data['ATT_ID'])
1026 1026
             : 0;
1027 1027
         if ($ATT_ID) {
@@ -1033,13 +1033,13 @@  discard block
 block discarded – undo
1033 1033
                         'event_espresso'
1034 1034
                     ),
1035 1035
                     '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1036
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
1037 1037
                         array(
1038 1038
                             'action' => 'edit_attendee',
1039 1039
                             'post' => $ATT_ID
1040 1040
                         ),
1041 1041
                         REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1042
+                    ).'">'.$attendee->full_name().'</a>',
1043 1043
                     '</h3>'
1044 1044
                 );
1045 1045
             }
@@ -1050,7 +1050,7 @@  discard block
 block discarded – undo
1050 1050
                 'espresso_registrations_new_registration',
1051 1051
                 $EVT_ID
1052 1052
             )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1053
+                $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1054 1054
                     'new_registration',
1055 1055
                     'add-registrant',
1056 1056
                     array('event_id' => $EVT_ID),
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
                 $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091 1091
                 $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092 1092
                 $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1093
+                $this->_template_args['admin_page_header'] .= ' ( '.$datetime->start_date().' )';
1094 1094
                 $this->_template_args['admin_page_header'] .= '</span></h3>';
1095 1095
             }
1096 1096
         }
@@ -1197,7 +1197,7 @@  discard block
 block discarded – undo
1197 1197
             'caps'                     => EEM_Registration::caps_read_admin,
1198 1198
             'default_where_conditions' => 'this_model_only',
1199 1199
         );
1200
-        if (! $count) {
1200
+        if ( ! $count) {
1201 1201
             $query_params = array_merge(
1202 1202
                 $query_params,
1203 1203
                 $this->_get_orderby_for_registrations_query(),
@@ -1218,7 +1218,7 @@  discard block
 block discarded – undo
1218 1218
     protected function addAttendeeIdToWhereConditions(array $request)
1219 1219
     {
1220 1220
         $where = array();
1221
-        if (! empty($request['ATT_ID'])) {
1221
+        if ( ! empty($request['ATT_ID'])) {
1222 1222
             $where['ATT_ID'] = absint($request['ATT_ID']);
1223 1223
         }
1224 1224
         return $where;
@@ -1234,7 +1234,7 @@  discard block
 block discarded – undo
1234 1234
     protected function _add_event_id_to_where_conditions(array $request)
1235 1235
     {
1236 1236
         $where = array();
1237
-        if (! empty($request['event_id'])) {
1237
+        if ( ! empty($request['event_id'])) {
1238 1238
             $where['EVT_ID'] = absint($request['event_id']);
1239 1239
         }
1240 1240
         return $where;
@@ -1250,7 +1250,7 @@  discard block
 block discarded – undo
1250 1250
     protected function _add_category_id_to_where_conditions(array $request)
1251 1251
     {
1252 1252
         $where = array();
1253
-        if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1253
+        if ( ! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1254 1254
             $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1255 1255
         }
1256 1256
         return $where;
@@ -1266,10 +1266,10 @@  discard block
 block discarded – undo
1266 1266
     protected function _add_datetime_id_to_where_conditions(array $request)
1267 1267
     {
1268 1268
         $where = array();
1269
-        if (! empty($request['datetime_id'])) {
1269
+        if ( ! empty($request['datetime_id'])) {
1270 1270
             $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1271 1271
         }
1272
-        if (! empty($request['DTT_ID'])) {
1272
+        if ( ! empty($request['DTT_ID'])) {
1273 1273
             $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1274 1274
         }
1275 1275
         return $where;
@@ -1295,7 +1295,7 @@  discard block
 block discarded – undo
1295 1295
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1296 1296
          * UNLESS viewing trashed registrations.
1297 1297
          */
1298
-        if (! empty($registration_status)) {
1298
+        if ( ! empty($registration_status)) {
1299 1299
             $where['STS_ID'] = $registration_status;
1300 1300
         } else {
1301 1301
             //make sure we exclude incomplete registrations, but only if not trashed.
@@ -1338,12 +1338,12 @@  discard block
 block discarded – undo
1338 1338
                 array(
1339 1339
                     EEM_Registration::instance()->convert_datetime_for_query(
1340 1340
                         'REG_date',
1341
-                        $now . ' 00:00:00',
1341
+                        $now.' 00:00:00',
1342 1342
                         'Y-m-d H:i:s'
1343 1343
                     ),
1344 1344
                     EEM_Registration::instance()->convert_datetime_for_query(
1345 1345
                         'REG_date',
1346
-                        $now . ' 23:59:59',
1346
+                        $now.' 23:59:59',
1347 1347
                         'Y-m-d H:i:s'
1348 1348
                     ),
1349 1349
                 ),
@@ -1356,12 +1356,12 @@  discard block
 block discarded – undo
1356 1356
                 array(
1357 1357
                     EEM_Registration::instance()->convert_datetime_for_query(
1358 1358
                         'REG_date',
1359
-                        $current_year_and_month . '-01 00:00:00',
1359
+                        $current_year_and_month.'-01 00:00:00',
1360 1360
                         'Y-m-d H:i:s'
1361 1361
                     ),
1362 1362
                     EEM_Registration::instance()->convert_datetime_for_query(
1363 1363
                         'REG_date',
1364
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1364
+                        $current_year_and_month.'-'.$days_this_month.' 23:59:59',
1365 1365
                         'Y-m-d H:i:s'
1366 1366
                     ),
1367 1367
                 ),
@@ -1376,18 +1376,18 @@  discard block
 block discarded – undo
1376 1376
                 : '';
1377 1377
             //if there is not a month or year then we can't go further
1378 1378
             if ($month_requested && $year_requested) {
1379
-                $days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1379
+                $days_in_month     = date('t', strtotime($year_requested.'-'.$month_requested.'-'.'01'));
1380 1380
                 $where['REG_date'] = array(
1381 1381
                     'BETWEEN',
1382 1382
                     array(
1383 1383
                         EEM_Registration::instance()->convert_datetime_for_query(
1384 1384
                             'REG_date',
1385
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1385
+                            $year_requested.'-'.$month_requested.'-01 00:00:00',
1386 1386
                             'Y-m-d H:i:s'
1387 1387
                         ),
1388 1388
                         EEM_Registration::instance()->convert_datetime_for_query(
1389 1389
                             'REG_date',
1390
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1390
+                            $year_requested.'-'.$month_requested.'-'.$days_in_month.' 23:59:59',
1391 1391
                             'Y-m-d H:i:s'
1392 1392
                         ),
1393 1393
                     ),
@@ -1407,8 +1407,8 @@  discard block
 block discarded – undo
1407 1407
     protected function _add_search_to_where_conditions(array $request)
1408 1408
     {
1409 1409
         $where = array();
1410
-        if (! empty($request['s'])) {
1411
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1410
+        if ( ! empty($request['s'])) {
1411
+            $search_string = '%'.sanitize_text_field($request['s']).'%';
1412 1412
             $where['OR*search_conditions'] = array(
1413 1413
                 'Event.EVT_name'                          => array('LIKE', $search_string),
1414 1414
                 'Event.EVT_desc'                          => array('LIKE', $search_string),
@@ -1525,7 +1525,7 @@  discard block
 block discarded – undo
1525 1525
             : $per_page;
1526 1526
 
1527 1527
         //-1 means return all results so get out if that's set.
1528
-        if ((int)$per_page === -1) {
1528
+        if ((int) $per_page === -1) {
1529 1529
             return array();
1530 1530
         }
1531 1531
         $per_page = absint($per_page);
@@ -1581,7 +1581,7 @@  discard block
 block discarded – undo
1581 1581
                 ),
1582 1582
                 REG_ADMIN_URL
1583 1583
             );
1584
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1584
+            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1585 1585
                 array(
1586 1586
                     'action' => 'default',
1587 1587
                     'EVT_ID' => $event_id,
@@ -1589,7 +1589,7 @@  discard block
 block discarded – undo
1589 1589
                 ),
1590 1590
                 admin_url('admin.php')
1591 1591
             );
1592
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1592
+            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1593 1593
                 array(
1594 1594
                     'page'   => 'espresso_events',
1595 1595
                     'action' => 'edit',
@@ -1598,12 +1598,12 @@  discard block
 block discarded – undo
1598 1598
                 admin_url('admin.php')
1599 1599
             );
1600 1600
             //next and previous links
1601
-            $next_reg                                      = $this->_registration->next(
1601
+            $next_reg = $this->_registration->next(
1602 1602
                 null,
1603 1603
                 array(),
1604 1604
                 'REG_ID'
1605 1605
             );
1606
-            $this->_template_args['next_registration']     = $next_reg
1606
+            $this->_template_args['next_registration'] = $next_reg
1607 1607
                 ? $this->_next_link(
1608 1608
                     EE_Admin_Page::add_query_args_and_nonce(
1609 1609
                         array(
@@ -1615,7 +1615,7 @@  discard block
 block discarded – undo
1615 1615
                     'dashicons dashicons-arrow-right ee-icon-size-22'
1616 1616
                 )
1617 1617
                 : '';
1618
-            $previous_reg                                  = $this->_registration->previous(
1618
+            $previous_reg = $this->_registration->previous(
1619 1619
                 null,
1620 1620
                 array(),
1621 1621
                 'REG_ID'
@@ -1633,7 +1633,7 @@  discard block
 block discarded – undo
1633 1633
                 )
1634 1634
                 : '';
1635 1635
             // grab header
1636
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1636
+            $template_path                             = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1637 1637
             $this->_template_args['REG_ID']            = $this->_registration->ID();
1638 1638
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1639 1639
                 $template_path,
@@ -1753,7 +1753,7 @@  discard block
 block discarded – undo
1753 1753
                             EEH_HTML::strong(
1754 1754
                                 $this->_registration->pretty_status(),
1755 1755
                                 '',
1756
-                                'status-' . $this->_registration->status_ID(),
1756
+                                'status-'.$this->_registration->status_ID(),
1757 1757
                                 'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1758 1758
                             )
1759 1759
                         )
@@ -1833,11 +1833,11 @@  discard block
 block discarded – undo
1833 1833
     {
1834 1834
         if (isset($this->_req_data['reg_status_change_form'])) {
1835 1835
             $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1836
-                ? (array)$this->_req_data['reg_status_change_form']['REG_ID']
1836
+                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1837 1837
                 : array();
1838 1838
         } else {
1839 1839
             $REG_IDs = isset($this->_req_data['_REG_ID'])
1840
-                ? (array)$this->_req_data['_REG_ID']
1840
+                ? (array) $this->_req_data['_REG_ID']
1841 1841
                 : array();
1842 1842
         }
1843 1843
         // sanitize $REG_IDs
@@ -1900,7 +1900,7 @@  discard block
 block discarded – undo
1900 1900
     {
1901 1901
         $success = false;
1902 1902
         // typecast $REG_IDs
1903
-        $REG_IDs = (array)$REG_IDs;
1903
+        $REG_IDs = (array) $REG_IDs;
1904 1904
         if ( ! empty($REG_IDs)) {
1905 1905
             $success = true;
1906 1906
             // set default status if none is passed
@@ -2050,7 +2050,7 @@  discard block
 block discarded – undo
2050 2050
             $action,
2051 2051
             $notify
2052 2052
         );
2053
-        $method = $action . '_registration';
2053
+        $method = $action.'_registration';
2054 2054
         if (method_exists($this, $method)) {
2055 2055
             $this->$method($notify);
2056 2056
         }
@@ -2168,7 +2168,7 @@  discard block
 block discarded – undo
2168 2168
             $filtered_line_item_tree,
2169 2169
             array('EE_Registration' => $this->_registration)
2170 2170
         );
2171
-        $attendee                                = $this->_registration->attendee();
2171
+        $attendee = $this->_registration->attendee();
2172 2172
         if (EE_Registry::instance()->CAP->current_user_can(
2173 2173
             'ee_read_transaction',
2174 2174
             'espresso_transactions_view_transaction'
@@ -2247,7 +2247,7 @@  discard block
 block discarded – undo
2247 2247
                 'Payment method response',
2248 2248
                 'event_espresso'
2249 2249
             );
2250
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2250
+            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2251 2251
         }
2252 2252
         $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2253 2253
         $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
@@ -2275,7 +2275,7 @@  discard block
 block discarded – undo
2275 2275
         $this->_template_args['REG_ID']                                       = $this->_registration->ID();
2276 2276
         $this->_template_args['event_id']                                     = $this->_registration->event_ID();
2277 2277
         $template_path                                                        =
2278
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2278
+            REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2279 2279
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2280 2280
     }
2281 2281
 
@@ -2304,7 +2304,7 @@  discard block
 block discarded – undo
2304 2304
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2305 2305
             $this->_template_args['REG_ID']                    = $this->_registration->ID();
2306 2306
             $template_path                                     =
2307
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2307
+                REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2308 2308
             echo EEH_Template::display_template($template_path, $this->_template_args, true);
2309 2309
         }
2310 2310
     }
@@ -2321,7 +2321,7 @@  discard block
 block discarded – undo
2321 2321
     public function form_before_question_group($output)
2322 2322
     {
2323 2323
         EE_Error::doing_it_wrong(
2324
-            __CLASS__ . '::' . __FUNCTION__,
2324
+            __CLASS__.'::'.__FUNCTION__,
2325 2325
             esc_html__(
2326 2326
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2327 2327
                 'event_espresso'
@@ -2346,7 +2346,7 @@  discard block
 block discarded – undo
2346 2346
     public function form_after_question_group($output)
2347 2347
     {
2348 2348
         EE_Error::doing_it_wrong(
2349
-            __CLASS__ . '::' . __FUNCTION__,
2349
+            __CLASS__.'::'.__FUNCTION__,
2350 2350
             esc_html__(
2351 2351
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2352 2352
                 'event_espresso'
@@ -2384,7 +2384,7 @@  discard block
 block discarded – undo
2384 2384
     public function form_form_field_label_wrap($label)
2385 2385
     {
2386 2386
         EE_Error::doing_it_wrong(
2387
-            __CLASS__ . '::' . __FUNCTION__,
2387
+            __CLASS__.'::'.__FUNCTION__,
2388 2388
             esc_html__(
2389 2389
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390 2390
                 'event_espresso'
@@ -2394,7 +2394,7 @@  discard block
 block discarded – undo
2394 2394
         return '
2395 2395
 			<tr>
2396 2396
 				<th>
2397
-					' . $label . '
2397
+					' . $label.'
2398 2398
 				</th>';
2399 2399
     }
2400 2400
 
@@ -2410,7 +2410,7 @@  discard block
 block discarded – undo
2410 2410
     public function form_form_field_input__wrap($input)
2411 2411
     {
2412 2412
         EE_Error::doing_it_wrong(
2413
-            __CLASS__ . '::' . __FUNCTION__,
2413
+            __CLASS__.'::'.__FUNCTION__,
2414 2414
             esc_html__(
2415 2415
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2416 2416
                 'event_espresso'
@@ -2419,7 +2419,7 @@  discard block
 block discarded – undo
2419 2419
         );
2420 2420
         return '
2421 2421
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2422
-					' . $input . '
2422
+					' . $input.'
2423 2423
 				</td>
2424 2424
 			</tr>';
2425 2425
     }
@@ -2464,7 +2464,7 @@  discard block
 block discarded – undo
2464 2464
     protected function _get_reg_custom_questions_form($REG_ID)
2465 2465
     {
2466 2466
         if ( ! $this->_reg_custom_questions_form) {
2467
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2467
+            require_once(REG_ADMIN.'form_sections'.DS.'EE_Registration_Custom_Questions_Form.form.php');
2468 2468
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2469 2469
                 EEM_Registration::instance()->get_one_by_ID($REG_ID)
2470 2470
             );
@@ -2500,7 +2500,7 @@  discard block
 block discarded – undo
2500 2500
         if ($form->is_valid()) {
2501 2501
             foreach ($form->subforms() as $question_group_id => $question_group_form) {
2502 2502
                 foreach ($question_group_form->inputs() as $question_id => $input) {
2503
-                    $where_conditions    = array(
2503
+                    $where_conditions = array(
2504 2504
                         'QST_ID' => $question_id,
2505 2505
                         'REG_ID' => $REG_ID,
2506 2506
                     );
@@ -2541,7 +2541,7 @@  discard block
 block discarded – undo
2541 2541
         $REG = EEM_Registration::instance();
2542 2542
         //get all other registrations on this transaction, and cache
2543 2543
         //the attendees for them so we don't have to run another query using force_join
2544
-        $registrations                           = $REG->get_all(array(
2544
+        $registrations = $REG->get_all(array(
2545 2545
             array(
2546 2546
                 'TXN_ID' => $this->_registration->transaction_ID(),
2547 2547
                 'REG_ID' => array('!=', $this->_registration->ID()),
@@ -2565,7 +2565,7 @@  discard block
 block discarded – undo
2565 2565
             $att_nmbr = 1;
2566 2566
             foreach ($registrations as $registration) {
2567 2567
                 /* @var $registration EE_Registration */
2568
-                $attendee                                                    = $registration->attendee()
2568
+                $attendee = $registration->attendee()
2569 2569
                     ? $registration->attendee()
2570 2570
                     : EEM_Attendee::instance()
2571 2571
                                   ->create_default_object();
@@ -2578,19 +2578,19 @@  discard block
 block discarded – undo
2578 2578
                     ', ',
2579 2579
                     $attendee->full_address_as_array()
2580 2580
                 );
2581
-                $this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2581
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2582 2582
                     array(
2583 2583
                         'action' => 'edit_attendee',
2584 2584
                         'post'   => $attendee->ID(),
2585 2585
                     ),
2586 2586
                     REG_ADMIN_URL
2587 2587
                 );
2588
-                $this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2588
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] = $registration->event_obj()->name();
2589 2589
                 $att_nmbr++;
2590 2590
             }
2591 2591
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2592 2592
         }
2593
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2593
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2594 2594
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2595 2595
     }
2596 2596
 
@@ -2633,20 +2633,20 @@  discard block
 block discarded – undo
2633 2633
         $this->_template_args['phone']             = $attendee->phone();
2634 2634
         $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2635 2635
         //edit link
2636
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2636
+        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(array(
2637 2637
             'action' => 'edit_attendee',
2638 2638
             'post'   => $attendee->ID(),
2639 2639
         ), REG_ADMIN_URL);
2640 2640
         $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2641 2641
         //create link
2642
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2642
+        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2643 2643
             ? EE_Admin_Page::add_query_args_and_nonce(array(
2644 2644
                 'action'  => 'duplicate_attendee',
2645 2645
                 '_REG_ID' => $this->_registration->ID(),
2646 2646
             ), REG_ADMIN_URL) : '';
2647 2647
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2648 2648
         $this->_template_args['att_check']    = $att_check;
2649
-        $template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2649
+        $template_path                        = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2650 2650
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2651 2651
     }
2652 2652
 
@@ -2691,7 +2691,7 @@  discard block
 block discarded – undo
2691 2691
             /** @var EE_Registration $REG */
2692 2692
             $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2693 2693
             $payments = $REG->registration_payments();
2694
-            if (! empty($payments)) {
2694
+            if ( ! empty($payments)) {
2695 2695
                 $name = $REG->attendee() instanceof EE_Attendee
2696 2696
                     ? $REG->attendee()->full_name()
2697 2697
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2887,7 +2887,7 @@  discard block
 block discarded – undo
2887 2887
                 'action' => 'edit',
2888 2888
                 'post'   => $this->_reg_event->ID(),
2889 2889
             ), EVENTS_ADMIN_URL);
2890
-            $edit_event_lnk                     = '<a href="'
2890
+            $edit_event_lnk = '<a href="'
2891 2891
                                                   . $edit_event_url
2892 2892
                                                   . '" title="'
2893 2893
                                                   . esc_attr__('Edit ', 'event_espresso')
@@ -2905,7 +2905,7 @@  discard block
 block discarded – undo
2905 2905
         }
2906 2906
         // grab header
2907 2907
         $template_path                              =
2908
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2908
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2909 2909
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2910 2910
             $this->_template_args, true);
2911 2911
         //$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
@@ -2943,7 +2943,7 @@  discard block
 block discarded – undo
2943 2943
                 '</b>'
2944 2944
             );
2945 2945
             return '
2946
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2946
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
2947 2947
 	<script >
2948 2948
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
2949 2949
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -3011,7 +3011,7 @@  discard block
 block discarded – undo
3011 3011
         //we come back to the process_registration_step route.
3012 3012
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3013 3013
         return EEH_Template::display_template(
3014
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3014
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
3015 3015
             $template_args,
3016 3016
             true
3017 3017
         );
@@ -3033,7 +3033,7 @@  discard block
 block discarded – undo
3033 3033
         if (is_object($this->_reg_event)) {
3034 3034
             return true;
3035 3035
         }
3036
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3036
+        $EVT_ID = ( ! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3037 3037
         if ( ! $EVT_ID) {
3038 3038
             return false;
3039 3039
         }
@@ -3103,7 +3103,7 @@  discard block
 block discarded – undo
3103 3103
                 }
3104 3104
                 break;
3105 3105
             case 'questions' :
3106
-                if (! isset(
3106
+                if ( ! isset(
3107 3107
                     $this->_req_data['txn_reg_status_change'],
3108 3108
                     $this->_req_data['txn_reg_status_change']['send_notifications'])
3109 3109
                 ) {
@@ -3223,7 +3223,7 @@  discard block
 block discarded – undo
3223 3223
     public function get_attendees($per_page, $count = false, $trash = false)
3224 3224
     {
3225 3225
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3226
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3226
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3227 3227
         $ATT_MDL                    = EEM_Attendee::instance();
3228 3228
         $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3229 3229
         switch ($this->_req_data['orderby']) {
@@ -3263,7 +3263,7 @@  discard block
 block discarded – undo
3263 3263
             : $per_page;
3264 3264
         $_where       = array();
3265 3265
         if ( ! empty($this->_req_data['s'])) {
3266
-            $sstr         = '%' . $this->_req_data['s'] . '%';
3266
+            $sstr         = '%'.$this->_req_data['s'].'%';
3267 3267
             $_where['OR'] = array(
3268 3268
                 'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3269 3269
                 'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
@@ -3290,17 +3290,17 @@  discard block
 block discarded – undo
3290 3290
             'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3291 3291
             'limit' => $limit
3292 3292
         );
3293
-        if (! $count) {
3293
+        if ( ! $count) {
3294 3294
             $query_args['order_by'] = array($orderby => $sort);
3295 3295
         }
3296 3296
         if ($trash) {
3297 3297
             $query_args[0]['status'] = array('!=', 'publish');
3298
-            $all_attendees    = $count
3298
+            $all_attendees = $count
3299 3299
                 ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3300 3300
                 : $ATT_MDL->get_all($query_args);
3301 3301
         } else {
3302 3302
             $query_args[0]['status'] = array('IN', array('publish'));
3303
-            $all_attendees    = $count
3303
+            $all_attendees = $count
3304 3304
                 ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3305 3305
                 : $ATT_MDL->get_all($query_args);
3306 3306
         }
@@ -3330,9 +3330,9 @@  discard block
 block discarded – undo
3330 3330
      *                                                     the query parameters from the request
3331 3331
      * @return void ends the request with a redirect or download
3332 3332
      */
3333
-    public function _registrations_report_base( $method_name_for_getting_query_params )
3333
+    public function _registrations_report_base($method_name_for_getting_query_params)
3334 3334
     {
3335
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3335
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3336 3336
             wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3337 3337
                 array(
3338 3338
                     'page'        => 'espresso_batch',
@@ -3341,7 +3341,7 @@  discard block
 block discarded – undo
3341 3341
                     'filters'     => urlencode(
3342 3342
                         serialize(
3343 3343
                             call_user_func(
3344
-                                array( $this, $method_name_for_getting_query_params ),
3344
+                                array($this, $method_name_for_getting_query_params),
3345 3345
                                 EEH_Array::is_set(
3346 3346
                                     $this->_req_data,
3347 3347
                                     'filters',
@@ -3361,8 +3361,8 @@  discard block
 block discarded – undo
3361 3361
                 'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3362 3362
             );
3363 3363
             $this->_req_data = array_merge($this->_req_data, $new_request_args);
3364
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3365
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3364
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3365
+                require_once(EE_CLASSES.'EE_Export.class.php');
3366 3366
                 $EE_Export = EE_Export::instance($this->_req_data);
3367 3367
                 $EE_Export->export();
3368 3368
             }
@@ -3383,8 +3383,8 @@  discard block
 block discarded – undo
3383 3383
 
3384 3384
     public function _contact_list_export()
3385 3385
     {
3386
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3387
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3386
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3387
+            require_once(EE_CLASSES.'EE_Export.class.php');
3388 3388
             $EE_Export = EE_Export::instance($this->_req_data);
3389 3389
             $EE_Export->export_attendees();
3390 3390
         }
@@ -3401,8 +3401,8 @@  discard block
 block discarded – undo
3401 3401
                 'return_url'  => urlencode($this->_req_data['return_url']),
3402 3402
             )));
3403 3403
         } else {
3404
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3405
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3404
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3405
+                require_once(EE_CLASSES.'EE_Export.class.php');
3406 3406
                 $EE_Export = EE_Export::instance($this->_req_data);
3407 3407
                 $EE_Export->report_attendees();
3408 3408
             }
@@ -3484,7 +3484,7 @@  discard block
 block discarded – undo
3484 3484
             $updated_fields = array(
3485 3485
                 'ATT_fname'     => $this->_req_data['ATT_fname'],
3486 3486
                 'ATT_lname'     => $this->_req_data['ATT_lname'],
3487
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3487
+                'ATT_full_name' => $this->_req_data['ATT_fname'].' '.$this->_req_data['ATT_lname'],
3488 3488
                 'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3489 3489
                 'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3490 3490
                 'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
@@ -3702,8 +3702,8 @@  discard block
 block discarded – undo
3702 3702
                 )
3703 3703
             )
3704 3704
         );
3705
-        $template                             =
3706
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3705
+        $template =
3706
+            REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3707 3707
         EEH_Template::display_template($template, $this->_template_args);
3708 3708
     }
3709 3709
 
@@ -3722,7 +3722,7 @@  discard block
 block discarded – undo
3722 3722
         $this->_template_args['attendee']      = $this->_cpt_model_obj;
3723 3723
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3724 3724
         $template                              =
3725
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3725
+            REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3726 3726
         EEH_Template::display_template($template, $this->_template_args);
3727 3727
     }
3728 3728
 
@@ -3737,7 +3737,7 @@  discard block
 block discarded – undo
3737 3737
     public function after_title_form_fields($post)
3738 3738
     {
3739 3739
         if ($post->post_type == 'espresso_attendees') {
3740
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3740
+            $template                  = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3741 3741
             $template_args['attendee'] = $this->_cpt_model_obj;
3742 3742
             EEH_Template::display_template($template, $template_args);
3743 3743
         }
Please login to merge, or discard this patch.
admin_pages/transactions/templates/txn_admin_details_header.template.php 1 patch
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -1,17 +1,17 @@
 block discarded – undo
1 1
 
2
-		<h3 class="txn-navigation-strip"><?php echo $previous_transaction . '&nbsp;'; echo __( 'Transaction # ', 'event_espresso' ) . $txn_nmbr['value']; echo '&nbsp;' . $next_transaction; ?></h3>
3
-		<h2 id="txn-date-h2" class="txn-date-h2"><?php echo $txn_datetime['value'];?></h2>
2
+		<h3 class="txn-navigation-strip"><?php echo $previous_transaction.'&nbsp;'; echo __('Transaction # ', 'event_espresso').$txn_nmbr['value']; echo '&nbsp;'.$next_transaction; ?></h3>
3
+		<h2 id="txn-date-h2" class="txn-date-h2"><?php echo $txn_datetime['value']; ?></h2>
4 4
 		<h2 id="txn-status-h2" class="txn-status-h2">
5
-			<?php echo __( 'Transaction Status: ', 'event_espresso' );?><span id="txn-status" class="<?php echo $txn_status['class'];?>"><?php echo $txn_status['value'];?></span>
5
+			<?php echo __('Transaction Status: ', 'event_espresso'); ?><span id="txn-status" class="<?php echo $txn_status['class']; ?>"><?php echo $txn_status['value']; ?></span>
6 6
 		</h2>
7 7
 
8 8
 	<?php $attributes = $amount_due ? 'class="txn-amount-due-h2"' : 'class="txn-amount-due-h2 hidden"'; ?>
9 9
 		<h2 id="txn-amount-due-h2" <?php echo $attributes; ?>>
10
-			<?php echo __( 'Total Amount Due: ', 'event_espresso' );?><span id="txn-admin-total-amount-due" class="<?php echo $amount_due_class;?>"><?php echo $amount_due;?></span>
10
+			<?php echo __('Total Amount Due: ', 'event_espresso'); ?><span id="txn-admin-total-amount-due" class="<?php echo $amount_due_class; ?>"><?php echo $amount_due; ?></span>
11 11
 		</h2>
12 12
 
13 13
 		<h3 id="txn-selected-method-of-payment-h3" class="txn-selected-method-of-payment-h3">
14
-			<?php echo __( 'Last Method of Payment: ', 'event_espresso' );?><?php echo $method_of_payment_name;?>
14
+			<?php echo __('Last Method of Payment: ', 'event_espresso'); ?><?php echo $method_of_payment_name; ?>
15 15
 		</h3>
16 16
 
17 17
 
Please login to merge, or discard this patch.
core/helpers/EEH_Activation.helper.php 2 patches
Indentation   +1581 added lines, -1581 removed lines patch added patch discarded remove patch
@@ -18,233 +18,233 @@  discard block
 block discarded – undo
18 18
 class EEH_Activation implements ResettableInterface
19 19
 {
20 20
 
21
-    /**
22
-     * constant used to indicate a cron task is no longer in use
23
-     */
24
-    const cron_task_no_longer_in_use = 'no_longer_in_use';
25
-
26
-    /**
27
-     * WP_User->ID
28
-     *
29
-     * @var int
30
-     */
31
-    private static $_default_creator_id;
32
-
33
-    /**
34
-     * indicates whether or not we've already verified core's default data during this request,
35
-     * because after migrations are done, any addons activated while in maintenance mode
36
-     * will want to setup their own default data, and they might hook into core's default data
37
-     * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
38
-     * This prevents doing that for EVERY single addon.
39
-     *
40
-     * @var boolean
41
-     */
42
-    protected static $_initialized_db_content_already_in_this_request = false;
43
-
44
-    /**
45
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
46
-     */
47
-    private static $table_analysis;
48
-
49
-    /**
50
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
51
-     */
52
-    private static $table_manager;
53
-
54
-
55
-    /**
56
-     * @return \EventEspresso\core\services\database\TableAnalysis
57
-     */
58
-    public static function getTableAnalysis()
59
-    {
60
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
61
-            self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
62
-        }
63
-        return self::$table_analysis;
64
-    }
65
-
66
-
67
-    /**
68
-     * @return \EventEspresso\core\services\database\TableManager
69
-     */
70
-    public static function getTableManager()
71
-    {
72
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
73
-            self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
74
-        }
75
-        return self::$table_manager;
76
-    }
77
-
78
-
79
-    /**
80
-     *    _ensure_table_name_has_prefix
81
-     *
82
-     * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
83
-     * @access     public
84
-     * @static
85
-     * @param $table_name
86
-     * @return string
87
-     */
88
-    public static function ensure_table_name_has_prefix($table_name)
89
-    {
90
-        return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
91
-    }
92
-
93
-
94
-    /**
95
-     *    system_initialization
96
-     *    ensures the EE configuration settings are loaded with at least default options set
97
-     *    and that all critical EE pages have been generated with the appropriate shortcodes in place
98
-     *
99
-     * @access public
100
-     * @static
101
-     * @return void
102
-     */
103
-    public static function system_initialization()
104
-    {
105
-        EEH_Activation::reset_and_update_config();
106
-        //which is fired BEFORE activation of plugin anyways
107
-        EEH_Activation::verify_default_pages_exist();
108
-    }
109
-
110
-
111
-    /**
112
-     * Sets the database schema and creates folders. This should
113
-     * be called on plugin activation and reactivation
114
-     *
115
-     * @return boolean success, whether the database and folders are setup properly
116
-     * @throws \EE_Error
117
-     */
118
-    public static function initialize_db_and_folders()
119
-    {
120
-        return EEH_Activation::create_database_tables();
121
-    }
122
-
123
-
124
-    /**
125
-     * assuming we have an up-to-date database schema, this will populate it
126
-     * with default and initial data. This should be called
127
-     * upon activation of a new plugin, reactivation, and at the end
128
-     * of running migration scripts
129
-     *
130
-     * @throws \EE_Error
131
-     */
132
-    public static function initialize_db_content()
133
-    {
134
-        //let's avoid doing all this logic repeatedly, especially when addons are requesting it
135
-        if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
136
-            return;
137
-        }
138
-        EEH_Activation::$_initialized_db_content_already_in_this_request = true;
139
-
140
-        EEH_Activation::initialize_system_questions();
141
-        EEH_Activation::insert_default_status_codes();
142
-        EEH_Activation::generate_default_message_templates();
143
-        EEH_Activation::create_no_ticket_prices_array();
144
-
145
-        EEH_Activation::validate_messages_system();
146
-        EEH_Activation::insert_default_payment_methods();
147
-        //in case we've
148
-        EEH_Activation::remove_cron_tasks();
149
-        EEH_Activation::create_cron_tasks();
150
-        // remove all TXN locks since that is being done via extra meta now
151
-        delete_option('ee_locked_transactions');
152
-        //also, check for CAF default db content
153
-        do_action('AHEE__EEH_Activation__initialize_db_content');
154
-        //also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
155
-        //which users really won't care about on initial activation
156
-        EE_Error::overwrite_success();
157
-    }
158
-
159
-
160
-    /**
161
-     * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
162
-     * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
163
-     * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
164
-     * (null)
165
-     *
166
-     * @param string $which_to_include can be 'current' (ones that are currently in use),
167
-     *                                 'old' (only returns ones that should no longer be used),or 'all',
168
-     * @return array
169
-     * @throws \EE_Error
170
-     */
171
-    public static function get_cron_tasks($which_to_include)
172
-    {
173
-        $cron_tasks = apply_filters(
174
-            'FHEE__EEH_Activation__get_cron_tasks',
175
-            array(
176
-                'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
21
+	/**
22
+	 * constant used to indicate a cron task is no longer in use
23
+	 */
24
+	const cron_task_no_longer_in_use = 'no_longer_in_use';
25
+
26
+	/**
27
+	 * WP_User->ID
28
+	 *
29
+	 * @var int
30
+	 */
31
+	private static $_default_creator_id;
32
+
33
+	/**
34
+	 * indicates whether or not we've already verified core's default data during this request,
35
+	 * because after migrations are done, any addons activated while in maintenance mode
36
+	 * will want to setup their own default data, and they might hook into core's default data
37
+	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
38
+	 * This prevents doing that for EVERY single addon.
39
+	 *
40
+	 * @var boolean
41
+	 */
42
+	protected static $_initialized_db_content_already_in_this_request = false;
43
+
44
+	/**
45
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
46
+	 */
47
+	private static $table_analysis;
48
+
49
+	/**
50
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
51
+	 */
52
+	private static $table_manager;
53
+
54
+
55
+	/**
56
+	 * @return \EventEspresso\core\services\database\TableAnalysis
57
+	 */
58
+	public static function getTableAnalysis()
59
+	{
60
+		if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
61
+			self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
62
+		}
63
+		return self::$table_analysis;
64
+	}
65
+
66
+
67
+	/**
68
+	 * @return \EventEspresso\core\services\database\TableManager
69
+	 */
70
+	public static function getTableManager()
71
+	{
72
+		if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
73
+			self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
74
+		}
75
+		return self::$table_manager;
76
+	}
77
+
78
+
79
+	/**
80
+	 *    _ensure_table_name_has_prefix
81
+	 *
82
+	 * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
83
+	 * @access     public
84
+	 * @static
85
+	 * @param $table_name
86
+	 * @return string
87
+	 */
88
+	public static function ensure_table_name_has_prefix($table_name)
89
+	{
90
+		return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
91
+	}
92
+
93
+
94
+	/**
95
+	 *    system_initialization
96
+	 *    ensures the EE configuration settings are loaded with at least default options set
97
+	 *    and that all critical EE pages have been generated with the appropriate shortcodes in place
98
+	 *
99
+	 * @access public
100
+	 * @static
101
+	 * @return void
102
+	 */
103
+	public static function system_initialization()
104
+	{
105
+		EEH_Activation::reset_and_update_config();
106
+		//which is fired BEFORE activation of plugin anyways
107
+		EEH_Activation::verify_default_pages_exist();
108
+	}
109
+
110
+
111
+	/**
112
+	 * Sets the database schema and creates folders. This should
113
+	 * be called on plugin activation and reactivation
114
+	 *
115
+	 * @return boolean success, whether the database and folders are setup properly
116
+	 * @throws \EE_Error
117
+	 */
118
+	public static function initialize_db_and_folders()
119
+	{
120
+		return EEH_Activation::create_database_tables();
121
+	}
122
+
123
+
124
+	/**
125
+	 * assuming we have an up-to-date database schema, this will populate it
126
+	 * with default and initial data. This should be called
127
+	 * upon activation of a new plugin, reactivation, and at the end
128
+	 * of running migration scripts
129
+	 *
130
+	 * @throws \EE_Error
131
+	 */
132
+	public static function initialize_db_content()
133
+	{
134
+		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
135
+		if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
136
+			return;
137
+		}
138
+		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
139
+
140
+		EEH_Activation::initialize_system_questions();
141
+		EEH_Activation::insert_default_status_codes();
142
+		EEH_Activation::generate_default_message_templates();
143
+		EEH_Activation::create_no_ticket_prices_array();
144
+
145
+		EEH_Activation::validate_messages_system();
146
+		EEH_Activation::insert_default_payment_methods();
147
+		//in case we've
148
+		EEH_Activation::remove_cron_tasks();
149
+		EEH_Activation::create_cron_tasks();
150
+		// remove all TXN locks since that is being done via extra meta now
151
+		delete_option('ee_locked_transactions');
152
+		//also, check for CAF default db content
153
+		do_action('AHEE__EEH_Activation__initialize_db_content');
154
+		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
155
+		//which users really won't care about on initial activation
156
+		EE_Error::overwrite_success();
157
+	}
158
+
159
+
160
+	/**
161
+	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
162
+	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
163
+	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
164
+	 * (null)
165
+	 *
166
+	 * @param string $which_to_include can be 'current' (ones that are currently in use),
167
+	 *                                 'old' (only returns ones that should no longer be used),or 'all',
168
+	 * @return array
169
+	 * @throws \EE_Error
170
+	 */
171
+	public static function get_cron_tasks($which_to_include)
172
+	{
173
+		$cron_tasks = apply_filters(
174
+			'FHEE__EEH_Activation__get_cron_tasks',
175
+			array(
176
+				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
177 177
 //				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
178
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
179
-                //there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
180
-                'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
181
-            )
182
-        );
183
-        if ($which_to_include === 'old') {
184
-            $cron_tasks = array_filter(
185
-                $cron_tasks,
186
-                function ($value) {
187
-                    return $value === EEH_Activation::cron_task_no_longer_in_use;
188
-                }
189
-            );
190
-        } elseif ($which_to_include === 'current') {
191
-            $cron_tasks = array_filter($cron_tasks);
192
-        } elseif (WP_DEBUG && $which_to_include !== 'all') {
193
-            throw new EE_Error(
194
-                sprintf(
195
-                    __(
196
-                        'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
197
-                        'event_espresso'
198
-                    ),
199
-                    $which_to_include
200
-                )
201
-            );
202
-        }
203
-        return $cron_tasks;
204
-    }
205
-
206
-
207
-    /**
208
-     * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
209
-     *
210
-     * @throws \EE_Error
211
-     */
212
-    public static function create_cron_tasks()
213
-    {
214
-
215
-        foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
216
-            if (! wp_next_scheduled($hook_name)) {
217
-                /**
218
-                 * This allows client code to define the initial start timestamp for this schedule.
219
-                 */
220
-                if (is_array($frequency)
221
-                    && count($frequency) === 2
222
-                    && isset($frequency[0], $frequency[1])
223
-                ) {
224
-                    $start_timestamp = $frequency[0];
225
-                    $frequency = $frequency[1];
226
-                } else {
227
-                    $start_timestamp = time();
228
-                }
229
-                wp_schedule_event($start_timestamp, $frequency, $hook_name);
230
-            }
231
-        }
232
-
233
-    }
234
-
235
-
236
-    /**
237
-     * Remove the currently-existing and now-removed cron tasks.
238
-     *
239
-     * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
240
-     * @throws \EE_Error
241
-     */
242
-    public static function remove_cron_tasks($remove_all = true)
243
-    {
244
-        $cron_tasks_to_remove = $remove_all ? 'all' : 'old';
245
-        $crons                = _get_cron_array();
246
-        $crons                = is_array($crons) ? $crons : array();
247
-        /* reminder of what $crons look like:
178
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
179
+				//there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
180
+				'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
181
+			)
182
+		);
183
+		if ($which_to_include === 'old') {
184
+			$cron_tasks = array_filter(
185
+				$cron_tasks,
186
+				function ($value) {
187
+					return $value === EEH_Activation::cron_task_no_longer_in_use;
188
+				}
189
+			);
190
+		} elseif ($which_to_include === 'current') {
191
+			$cron_tasks = array_filter($cron_tasks);
192
+		} elseif (WP_DEBUG && $which_to_include !== 'all') {
193
+			throw new EE_Error(
194
+				sprintf(
195
+					__(
196
+						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
197
+						'event_espresso'
198
+					),
199
+					$which_to_include
200
+				)
201
+			);
202
+		}
203
+		return $cron_tasks;
204
+	}
205
+
206
+
207
+	/**
208
+	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
209
+	 *
210
+	 * @throws \EE_Error
211
+	 */
212
+	public static function create_cron_tasks()
213
+	{
214
+
215
+		foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
216
+			if (! wp_next_scheduled($hook_name)) {
217
+				/**
218
+				 * This allows client code to define the initial start timestamp for this schedule.
219
+				 */
220
+				if (is_array($frequency)
221
+					&& count($frequency) === 2
222
+					&& isset($frequency[0], $frequency[1])
223
+				) {
224
+					$start_timestamp = $frequency[0];
225
+					$frequency = $frequency[1];
226
+				} else {
227
+					$start_timestamp = time();
228
+				}
229
+				wp_schedule_event($start_timestamp, $frequency, $hook_name);
230
+			}
231
+		}
232
+
233
+	}
234
+
235
+
236
+	/**
237
+	 * Remove the currently-existing and now-removed cron tasks.
238
+	 *
239
+	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
240
+	 * @throws \EE_Error
241
+	 */
242
+	public static function remove_cron_tasks($remove_all = true)
243
+	{
244
+		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
245
+		$crons                = _get_cron_array();
246
+		$crons                = is_array($crons) ? $crons : array();
247
+		/* reminder of what $crons look like:
248 248
          * Top-level keys are timestamps, and their values are arrays.
249 249
          * The 2nd level arrays have keys with each of the cron task hook names to run at that time
250 250
          * and their values are arrays.
@@ -261,911 +261,911 @@  discard block
 block discarded – undo
261 261
          *					...
262 262
          *      ...
263 263
          */
264
-        $ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
265
-        foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
266
-            if (is_array($hooks_to_fire_at_time)) {
267
-                foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
268
-                    if (isset($ee_cron_tasks_to_remove[$hook_name])
269
-                        && is_array($ee_cron_tasks_to_remove[$hook_name])
270
-                    ) {
271
-                        unset($crons[$timestamp][$hook_name]);
272
-                    }
273
-                }
274
-                //also take care of any empty cron timestamps.
275
-                if (empty($hooks_to_fire_at_time)) {
276
-                    unset($crons[$timestamp]);
277
-                }
278
-            }
279
-        }
280
-        _set_cron_array($crons);
281
-    }
282
-
283
-
284
-    /**
285
-     *    CPT_initialization
286
-     *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
287
-     *
288
-     * @access public
289
-     * @static
290
-     * @return void
291
-     */
292
-    public static function CPT_initialization()
293
-    {
294
-        // register Custom Post Types
295
-        EE_Registry::instance()->load_core('Register_CPTs');
296
-        flush_rewrite_rules();
297
-    }
298
-
299
-
300
-
301
-    /**
302
-     *    reset_and_update_config
303
-     * The following code was moved over from EE_Config so that it will no longer run on every request.
304
-     * If there is old calendar config data saved, then it will get converted on activation.
305
-     * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
306
-     *
307
-     * @access public
308
-     * @static
309
-     * @return void
310
-     */
311
-    public static function reset_and_update_config()
312
-    {
313
-        do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
314
-        add_filter(
315
-            'FHEE__EE_Config___load_core_config__config_settings',
316
-            array('EEH_Activation', 'migrate_old_config_data'),
317
-            10,
318
-            3
319
-        );
320
-        //EE_Config::reset();
321
-        if (! EE_Config::logging_enabled()) {
322
-            delete_option(EE_Config::LOG_NAME);
323
-        }
324
-    }
325
-
326
-
327
-    /**
328
-     *    load_calendar_config
329
-     *
330
-     * @access    public
331
-     * @return    void
332
-     */
333
-    public static function load_calendar_config()
334
-    {
335
-        // grab array of all plugin folders and loop thru it
336
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
337
-        if (empty($plugins)) {
338
-            return;
339
-        }
340
-        foreach ($plugins as $plugin_path) {
341
-            // grab plugin folder name from path
342
-            $plugin = basename($plugin_path);
343
-            // drill down to Espresso plugins
344
-            // then to calendar related plugins
345
-            if (
346
-                strpos($plugin, 'espresso') !== false
347
-                || strpos($plugin, 'Espresso') !== false
348
-                || strpos($plugin, 'ee4') !== false
349
-                || strpos($plugin, 'EE4') !== false
350
-                || strpos($plugin, 'calendar') !== false
351
-            ) {
352
-                // this is what we are looking for
353
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
354
-                // does it exist in this folder ?
355
-                if (is_readable($calendar_config)) {
356
-                    // YEAH! let's load it
357
-                    require_once($calendar_config);
358
-                }
359
-            }
360
-        }
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     *    _migrate_old_config_data
367
-     *
368
-     * @access    public
369
-     * @param array|stdClass $settings
370
-     * @param string         $config
371
-     * @param \EE_Config     $EE_Config
372
-     * @return \stdClass
373
-     */
374
-    public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
375
-    {
376
-        $convert_from_array = array('addons');
377
-        // in case old settings were saved as an array
378
-        if (is_array($settings) && in_array($config, $convert_from_array)) {
379
-            // convert existing settings to an object
380
-            $config_array = $settings;
381
-            $settings = new stdClass();
382
-            foreach ($config_array as $key => $value) {
383
-                if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
384
-                    $EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
385
-                } else {
386
-                    $settings->{$key} = $value;
387
-                }
388
-            }
389
-            add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
390
-        }
391
-        return $settings;
392
-    }
393
-
394
-
395
-    /**
396
-     * deactivate_event_espresso
397
-     *
398
-     * @access public
399
-     * @static
400
-     * @return void
401
-     */
402
-    public static function deactivate_event_espresso()
403
-    {
404
-        // check permissions
405
-        if (current_user_can('activate_plugins')) {
406
-            deactivate_plugins(EE_PLUGIN_BASENAME, true);
407
-        }
408
-    }
409
-
410
-
411
-
412
-    /**
413
-     * verify_default_pages_exist
414
-     *
415
-     * @access public
416
-     * @static
417
-     * @return void
418
-     * @throws InvalidDataTypeException
419
-     */
420
-    public static function verify_default_pages_exist()
421
-    {
422
-        $critical_page_problem = false;
423
-        $critical_pages = array(
424
-            array(
425
-                'id'   => 'reg_page_id',
426
-                'name' => __('Registration Checkout', 'event_espresso'),
427
-                'post' => null,
428
-                'code' => 'ESPRESSO_CHECKOUT',
429
-            ),
430
-            array(
431
-                'id'   => 'txn_page_id',
432
-                'name' => __('Transactions', 'event_espresso'),
433
-                'post' => null,
434
-                'code' => 'ESPRESSO_TXN_PAGE',
435
-            ),
436
-            array(
437
-                'id'   => 'thank_you_page_id',
438
-                'name' => __('Thank You', 'event_espresso'),
439
-                'post' => null,
440
-                'code' => 'ESPRESSO_THANK_YOU',
441
-            ),
442
-            array(
443
-                'id'   => 'cancel_page_id',
444
-                'name' => __('Registration Cancelled', 'event_espresso'),
445
-                'post' => null,
446
-                'code' => 'ESPRESSO_CANCELLED',
447
-            ),
448
-        );
449
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
450
-        foreach ($critical_pages as $critical_page) {
451
-            // is critical page ID set in config ?
452
-            if ($EE_Core_Config->{$critical_page['id']} !== false) {
453
-                // attempt to find post by ID
454
-                $critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
455
-            }
456
-            // no dice?
457
-            if ($critical_page['post'] === null) {
458
-                // attempt to find post by title
459
-                $critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
460
-                // still nothing?
461
-                if ($critical_page['post'] === null) {
462
-                    $critical_page = EEH_Activation::create_critical_page($critical_page);
463
-                    // REALLY? Still nothing ??!?!?
464
-                    if ($critical_page['post'] === null) {
465
-                        $msg = __(
466
-                            'The Event Espresso critical page configuration settings could not be updated.',
467
-                            'event_espresso'
468
-                        );
469
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
470
-                        break;
471
-                    }
472
-                }
473
-            }
474
-            // check that Post ID matches critical page ID in config
475
-            if (
476
-                isset($critical_page['post']->ID)
477
-                && $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
478
-            ) {
479
-                //update Config with post ID
480
-                $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
481
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
482
-                    $msg = __(
483
-                        'The Event Espresso critical page configuration settings could not be updated.',
484
-                        'event_espresso'
485
-                    );
486
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
487
-                }
488
-            }
489
-            $critical_page_problem =
490
-                ! isset($critical_page['post']->post_status)
491
-                || $critical_page['post']->post_status !== 'publish'
492
-                || strpos($critical_page['post']->post_content, $critical_page['code']) === false
493
-                    ? true
494
-                    : $critical_page_problem;
495
-        }
496
-        if ($critical_page_problem) {
497
-            new PersistentAdminNotice(
498
-                'critical_page_problem',
499
-                sprintf(
500
-                    esc_html__(
501
-                        'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
502
-                        'event_espresso'
503
-                    ),
504
-                    '<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
505
-                    . __('Event Espresso Critical Pages Settings', 'event_espresso')
506
-                    . '</a>'
507
-                )
508
-            );
509
-        }
510
-        if (EE_Error::has_notices()) {
511
-            EE_Error::get_notices(false, true, true);
512
-        }
513
-    }
514
-
515
-
516
-
517
-    /**
518
-     * Returns the first post which uses the specified shortcode
519
-     *
520
-     * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
521
-     *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
522
-     *                             "[ESPRESSO_THANK_YOU"
523
-     *                             (we don't search for the closing shortcode bracket because they might have added
524
-     *                             parameter to the shortcode
525
-     * @return WP_Post or NULl
526
-     */
527
-    public static function get_page_by_ee_shortcode($ee_shortcode)
528
-    {
529
-        global $wpdb;
530
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
531
-        $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
532
-        if ($post_id) {
533
-            return get_post($post_id);
534
-        } else {
535
-            return null;
536
-        }
537
-    }
538
-
539
-
540
-    /**
541
-     *    This function generates a post for critical espresso pages
542
-     *
543
-     * @access public
544
-     * @static
545
-     * @param array $critical_page
546
-     * @return array
547
-     */
548
-    public static function create_critical_page($critical_page)
549
-    {
550
-
551
-        $post_args = array(
552
-            'post_title'     => $critical_page['name'],
553
-            'post_status'    => 'publish',
554
-            'post_type'      => 'page',
555
-            'comment_status' => 'closed',
556
-            'post_content'   => '[' . $critical_page['code'] . ']',
557
-        );
558
-
559
-        $post_id = wp_insert_post($post_args);
560
-        if (! $post_id) {
561
-            $msg = sprintf(
562
-                __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
563
-                $critical_page['name']
564
-            );
565
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
566
-            return $critical_page;
567
-        }
568
-        // get newly created post's details
569
-        if (! $critical_page['post'] = get_post($post_id)) {
570
-            $msg = sprintf(
571
-                __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
572
-                $critical_page['name']
573
-            );
574
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
575
-        }
576
-
577
-        return $critical_page;
578
-
579
-    }
580
-
581
-
582
-
583
-
584
-    /**
585
-     * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
586
-     * The role being used to check is filterable.
587
-     *
588
-     * @since  4.6.0
589
-     * @global WPDB $wpdb
590
-     * @return mixed null|int WP_user ID or NULL
591
-     */
592
-    public static function get_default_creator_id()
593
-    {
594
-        global $wpdb;
595
-        if ( ! empty(self::$_default_creator_id)) {
596
-            return self::$_default_creator_id;
597
-        }/**/
598
-        $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
599
-        //let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
600
-        $pre_filtered_id = apply_filters(
601
-            'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
602
-            false,
603
-            $role_to_check
604
-        );
605
-        if ($pre_filtered_id !== false) {
606
-            return (int)$pre_filtered_id;
607
-        }
608
-        $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
609
-        $query = $wpdb->prepare(
610
-            "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
611
-            '%' . $role_to_check . '%'
612
-        );
613
-        $user_id = $wpdb->get_var($query);
614
-        $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
615
-        if ($user_id && (int)$user_id) {
616
-            self::$_default_creator_id = (int)$user_id;
617
-            return self::$_default_creator_id;
618
-        } else {
619
-            return null;
620
-        }
621
-    }
622
-
623
-
624
-
625
-    /**
626
-     * used by EE and EE addons during plugin activation to create tables.
627
-     * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
628
-     * but includes extra logic regarding activations.
629
-     *
630
-     * @access public
631
-     * @static
632
-     * @param string  $table_name              without the $wpdb->prefix
633
-     * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
634
-     *                                         table query)
635
-     * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
636
-     * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
637
-     *                                         and new once this function is done (ie, you really do want to CREATE a
638
-     *                                         table, and expect it to be empty once you're done) leave as FALSE when
639
-     *                                         you just want to verify the table exists and matches this definition
640
-     *                                         (and if it HAS data in it you want to leave it be)
641
-     * @return void
642
-     * @throws EE_Error if there are database errors
643
-     */
644
-    public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
645
-    {
646
-        if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
647
-            return;
648
-        }
649
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
650
-        if ( ! function_exists('dbDelta')) {
651
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
652
-        }
653
-        $tableAnalysis = \EEH_Activation::getTableAnalysis();
654
-        $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
655
-        // do we need to first delete an existing version of this table ?
656
-        if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
657
-            // ok, delete the table... but ONLY if it's empty
658
-            $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
659
-            // table is NOT empty, are you SURE you want to delete this table ???
660
-            if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
661
-                \EEH_Activation::getTableManager()->dropTable($wp_table_name);
662
-            } else if ( ! $deleted_safely) {
663
-                // so we should be more cautious rather than just dropping tables so easily
664
-                error_log(
665
-                    sprintf(
666
-                        __(
667
-                            'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
668
-                            'event_espresso'
669
-                        ),
670
-                        $wp_table_name,
671
-                        '<br/>',
672
-                        'espresso_db_update'
673
-                    )
674
-                );
675
-            }
676
-        }
677
-        $engine = str_replace('ENGINE=', '', $engine);
678
-        \EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
679
-    }
680
-
681
-
682
-
683
-    /**
684
-     *    add_column_if_it_doesn't_exist
685
-     *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
686
-     *
687
-     * @access     public
688
-     * @static
689
-     * @deprecated instead use TableManager::addColumn()
690
-     * @param string $table_name  (without "wp_", eg "esp_attendee"
691
-     * @param string $column_name
692
-     * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
693
-     *                            'VARCHAR(10)'
694
-     * @return bool|int
695
-     */
696
-    public static function add_column_if_it_doesnt_exist(
697
-        $table_name,
698
-        $column_name,
699
-        $column_info = 'INT UNSIGNED NOT NULL'
700
-    ) {
701
-        return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
702
-    }
703
-
704
-
705
-    /**
706
-     * get_fields_on_table
707
-     * Gets all the fields on the database table.
708
-     *
709
-     * @access     public
710
-     * @deprecated instead use TableManager::getTableColumns()
711
-     * @static
712
-     * @param string $table_name , without prefixed $wpdb->prefix
713
-     * @return array of database column names
714
-     */
715
-    public static function get_fields_on_table($table_name = null)
716
-    {
717
-        return \EEH_Activation::getTableManager()->getTableColumns($table_name);
718
-    }
719
-
720
-
721
-    /**
722
-     * db_table_is_empty
723
-     *
724
-     * @access     public\
725
-     * @deprecated instead use TableAnalysis::tableIsEmpty()
726
-     * @static
727
-     * @param string $table_name
728
-     * @return bool
729
-     */
730
-    public static function db_table_is_empty($table_name)
731
-    {
732
-        return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
733
-    }
734
-
735
-
736
-    /**
737
-     * delete_db_table_if_empty
738
-     *
739
-     * @access public
740
-     * @static
741
-     * @param string $table_name
742
-     * @return bool | int
743
-     */
744
-    public static function delete_db_table_if_empty($table_name)
745
-    {
746
-        if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
747
-            return \EEH_Activation::getTableManager()->dropTable($table_name);
748
-        }
749
-        return false;
750
-    }
751
-
752
-
753
-    /**
754
-     * delete_unused_db_table
755
-     *
756
-     * @access     public
757
-     * @static
758
-     * @deprecated instead use TableManager::dropTable()
759
-     * @param string $table_name
760
-     * @return bool | int
761
-     */
762
-    public static function delete_unused_db_table($table_name)
763
-    {
764
-        return \EEH_Activation::getTableManager()->dropTable($table_name);
765
-    }
766
-
767
-
768
-    /**
769
-     * drop_index
770
-     *
771
-     * @access     public
772
-     * @static
773
-     * @deprecated instead use TableManager::dropIndex()
774
-     * @param string $table_name
775
-     * @param string $index_name
776
-     * @return bool | int
777
-     */
778
-    public static function drop_index($table_name, $index_name)
779
-    {
780
-        return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
781
-    }
782
-
783
-
784
-
785
-    /**
786
-     * create_database_tables
787
-     *
788
-     * @access public
789
-     * @static
790
-     * @throws EE_Error
791
-     * @return boolean success (whether database is setup properly or not)
792
-     */
793
-    public static function create_database_tables()
794
-    {
795
-        EE_Registry::instance()->load_core('Data_Migration_Manager');
796
-        //find the migration script that sets the database to be compatible with the code
797
-        $dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
798
-        if ($dms_name) {
799
-            $current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
800
-            $current_data_migration_script->set_migrating(false);
801
-            $current_data_migration_script->schema_changes_before_migration();
802
-            $current_data_migration_script->schema_changes_after_migration();
803
-            if ($current_data_migration_script->get_errors()) {
804
-                if (WP_DEBUG) {
805
-                    foreach ($current_data_migration_script->get_errors() as $error) {
806
-                        EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
807
-                    }
808
-                } else {
809
-                    EE_Error::add_error(
810
-                        __(
811
-                            'There were errors creating the Event Espresso database tables and Event Espresso has been 
264
+		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
265
+		foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
266
+			if (is_array($hooks_to_fire_at_time)) {
267
+				foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
268
+					if (isset($ee_cron_tasks_to_remove[$hook_name])
269
+						&& is_array($ee_cron_tasks_to_remove[$hook_name])
270
+					) {
271
+						unset($crons[$timestamp][$hook_name]);
272
+					}
273
+				}
274
+				//also take care of any empty cron timestamps.
275
+				if (empty($hooks_to_fire_at_time)) {
276
+					unset($crons[$timestamp]);
277
+				}
278
+			}
279
+		}
280
+		_set_cron_array($crons);
281
+	}
282
+
283
+
284
+	/**
285
+	 *    CPT_initialization
286
+	 *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
287
+	 *
288
+	 * @access public
289
+	 * @static
290
+	 * @return void
291
+	 */
292
+	public static function CPT_initialization()
293
+	{
294
+		// register Custom Post Types
295
+		EE_Registry::instance()->load_core('Register_CPTs');
296
+		flush_rewrite_rules();
297
+	}
298
+
299
+
300
+
301
+	/**
302
+	 *    reset_and_update_config
303
+	 * The following code was moved over from EE_Config so that it will no longer run on every request.
304
+	 * If there is old calendar config data saved, then it will get converted on activation.
305
+	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
306
+	 *
307
+	 * @access public
308
+	 * @static
309
+	 * @return void
310
+	 */
311
+	public static function reset_and_update_config()
312
+	{
313
+		do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
314
+		add_filter(
315
+			'FHEE__EE_Config___load_core_config__config_settings',
316
+			array('EEH_Activation', 'migrate_old_config_data'),
317
+			10,
318
+			3
319
+		);
320
+		//EE_Config::reset();
321
+		if (! EE_Config::logging_enabled()) {
322
+			delete_option(EE_Config::LOG_NAME);
323
+		}
324
+	}
325
+
326
+
327
+	/**
328
+	 *    load_calendar_config
329
+	 *
330
+	 * @access    public
331
+	 * @return    void
332
+	 */
333
+	public static function load_calendar_config()
334
+	{
335
+		// grab array of all plugin folders and loop thru it
336
+		$plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
337
+		if (empty($plugins)) {
338
+			return;
339
+		}
340
+		foreach ($plugins as $plugin_path) {
341
+			// grab plugin folder name from path
342
+			$plugin = basename($plugin_path);
343
+			// drill down to Espresso plugins
344
+			// then to calendar related plugins
345
+			if (
346
+				strpos($plugin, 'espresso') !== false
347
+				|| strpos($plugin, 'Espresso') !== false
348
+				|| strpos($plugin, 'ee4') !== false
349
+				|| strpos($plugin, 'EE4') !== false
350
+				|| strpos($plugin, 'calendar') !== false
351
+			) {
352
+				// this is what we are looking for
353
+				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
354
+				// does it exist in this folder ?
355
+				if (is_readable($calendar_config)) {
356
+					// YEAH! let's load it
357
+					require_once($calendar_config);
358
+				}
359
+			}
360
+		}
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 *    _migrate_old_config_data
367
+	 *
368
+	 * @access    public
369
+	 * @param array|stdClass $settings
370
+	 * @param string         $config
371
+	 * @param \EE_Config     $EE_Config
372
+	 * @return \stdClass
373
+	 */
374
+	public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
375
+	{
376
+		$convert_from_array = array('addons');
377
+		// in case old settings were saved as an array
378
+		if (is_array($settings) && in_array($config, $convert_from_array)) {
379
+			// convert existing settings to an object
380
+			$config_array = $settings;
381
+			$settings = new stdClass();
382
+			foreach ($config_array as $key => $value) {
383
+				if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
384
+					$EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
385
+				} else {
386
+					$settings->{$key} = $value;
387
+				}
388
+			}
389
+			add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
390
+		}
391
+		return $settings;
392
+	}
393
+
394
+
395
+	/**
396
+	 * deactivate_event_espresso
397
+	 *
398
+	 * @access public
399
+	 * @static
400
+	 * @return void
401
+	 */
402
+	public static function deactivate_event_espresso()
403
+	{
404
+		// check permissions
405
+		if (current_user_can('activate_plugins')) {
406
+			deactivate_plugins(EE_PLUGIN_BASENAME, true);
407
+		}
408
+	}
409
+
410
+
411
+
412
+	/**
413
+	 * verify_default_pages_exist
414
+	 *
415
+	 * @access public
416
+	 * @static
417
+	 * @return void
418
+	 * @throws InvalidDataTypeException
419
+	 */
420
+	public static function verify_default_pages_exist()
421
+	{
422
+		$critical_page_problem = false;
423
+		$critical_pages = array(
424
+			array(
425
+				'id'   => 'reg_page_id',
426
+				'name' => __('Registration Checkout', 'event_espresso'),
427
+				'post' => null,
428
+				'code' => 'ESPRESSO_CHECKOUT',
429
+			),
430
+			array(
431
+				'id'   => 'txn_page_id',
432
+				'name' => __('Transactions', 'event_espresso'),
433
+				'post' => null,
434
+				'code' => 'ESPRESSO_TXN_PAGE',
435
+			),
436
+			array(
437
+				'id'   => 'thank_you_page_id',
438
+				'name' => __('Thank You', 'event_espresso'),
439
+				'post' => null,
440
+				'code' => 'ESPRESSO_THANK_YOU',
441
+			),
442
+			array(
443
+				'id'   => 'cancel_page_id',
444
+				'name' => __('Registration Cancelled', 'event_espresso'),
445
+				'post' => null,
446
+				'code' => 'ESPRESSO_CANCELLED',
447
+			),
448
+		);
449
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
450
+		foreach ($critical_pages as $critical_page) {
451
+			// is critical page ID set in config ?
452
+			if ($EE_Core_Config->{$critical_page['id']} !== false) {
453
+				// attempt to find post by ID
454
+				$critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
455
+			}
456
+			// no dice?
457
+			if ($critical_page['post'] === null) {
458
+				// attempt to find post by title
459
+				$critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
460
+				// still nothing?
461
+				if ($critical_page['post'] === null) {
462
+					$critical_page = EEH_Activation::create_critical_page($critical_page);
463
+					// REALLY? Still nothing ??!?!?
464
+					if ($critical_page['post'] === null) {
465
+						$msg = __(
466
+							'The Event Espresso critical page configuration settings could not be updated.',
467
+							'event_espresso'
468
+						);
469
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
470
+						break;
471
+					}
472
+				}
473
+			}
474
+			// check that Post ID matches critical page ID in config
475
+			if (
476
+				isset($critical_page['post']->ID)
477
+				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
478
+			) {
479
+				//update Config with post ID
480
+				$EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
481
+				if (! EE_Config::instance()->update_espresso_config(false, false)) {
482
+					$msg = __(
483
+						'The Event Espresso critical page configuration settings could not be updated.',
484
+						'event_espresso'
485
+					);
486
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
487
+				}
488
+			}
489
+			$critical_page_problem =
490
+				! isset($critical_page['post']->post_status)
491
+				|| $critical_page['post']->post_status !== 'publish'
492
+				|| strpos($critical_page['post']->post_content, $critical_page['code']) === false
493
+					? true
494
+					: $critical_page_problem;
495
+		}
496
+		if ($critical_page_problem) {
497
+			new PersistentAdminNotice(
498
+				'critical_page_problem',
499
+				sprintf(
500
+					esc_html__(
501
+						'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
502
+						'event_espresso'
503
+					),
504
+					'<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
505
+					. __('Event Espresso Critical Pages Settings', 'event_espresso')
506
+					. '</a>'
507
+				)
508
+			);
509
+		}
510
+		if (EE_Error::has_notices()) {
511
+			EE_Error::get_notices(false, true, true);
512
+		}
513
+	}
514
+
515
+
516
+
517
+	/**
518
+	 * Returns the first post which uses the specified shortcode
519
+	 *
520
+	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
521
+	 *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
522
+	 *                             "[ESPRESSO_THANK_YOU"
523
+	 *                             (we don't search for the closing shortcode bracket because they might have added
524
+	 *                             parameter to the shortcode
525
+	 * @return WP_Post or NULl
526
+	 */
527
+	public static function get_page_by_ee_shortcode($ee_shortcode)
528
+	{
529
+		global $wpdb;
530
+		$shortcode_and_opening_bracket = '[' . $ee_shortcode;
531
+		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
532
+		if ($post_id) {
533
+			return get_post($post_id);
534
+		} else {
535
+			return null;
536
+		}
537
+	}
538
+
539
+
540
+	/**
541
+	 *    This function generates a post for critical espresso pages
542
+	 *
543
+	 * @access public
544
+	 * @static
545
+	 * @param array $critical_page
546
+	 * @return array
547
+	 */
548
+	public static function create_critical_page($critical_page)
549
+	{
550
+
551
+		$post_args = array(
552
+			'post_title'     => $critical_page['name'],
553
+			'post_status'    => 'publish',
554
+			'post_type'      => 'page',
555
+			'comment_status' => 'closed',
556
+			'post_content'   => '[' . $critical_page['code'] . ']',
557
+		);
558
+
559
+		$post_id = wp_insert_post($post_args);
560
+		if (! $post_id) {
561
+			$msg = sprintf(
562
+				__('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
563
+				$critical_page['name']
564
+			);
565
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
566
+			return $critical_page;
567
+		}
568
+		// get newly created post's details
569
+		if (! $critical_page['post'] = get_post($post_id)) {
570
+			$msg = sprintf(
571
+				__('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
572
+				$critical_page['name']
573
+			);
574
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
575
+		}
576
+
577
+		return $critical_page;
578
+
579
+	}
580
+
581
+
582
+
583
+
584
+	/**
585
+	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
586
+	 * The role being used to check is filterable.
587
+	 *
588
+	 * @since  4.6.0
589
+	 * @global WPDB $wpdb
590
+	 * @return mixed null|int WP_user ID or NULL
591
+	 */
592
+	public static function get_default_creator_id()
593
+	{
594
+		global $wpdb;
595
+		if ( ! empty(self::$_default_creator_id)) {
596
+			return self::$_default_creator_id;
597
+		}/**/
598
+		$role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
599
+		//let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
600
+		$pre_filtered_id = apply_filters(
601
+			'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
602
+			false,
603
+			$role_to_check
604
+		);
605
+		if ($pre_filtered_id !== false) {
606
+			return (int)$pre_filtered_id;
607
+		}
608
+		$capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
609
+		$query = $wpdb->prepare(
610
+			"SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
611
+			'%' . $role_to_check . '%'
612
+		);
613
+		$user_id = $wpdb->get_var($query);
614
+		$user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
615
+		if ($user_id && (int)$user_id) {
616
+			self::$_default_creator_id = (int)$user_id;
617
+			return self::$_default_creator_id;
618
+		} else {
619
+			return null;
620
+		}
621
+	}
622
+
623
+
624
+
625
+	/**
626
+	 * used by EE and EE addons during plugin activation to create tables.
627
+	 * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
628
+	 * but includes extra logic regarding activations.
629
+	 *
630
+	 * @access public
631
+	 * @static
632
+	 * @param string  $table_name              without the $wpdb->prefix
633
+	 * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
634
+	 *                                         table query)
635
+	 * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
636
+	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
637
+	 *                                         and new once this function is done (ie, you really do want to CREATE a
638
+	 *                                         table, and expect it to be empty once you're done) leave as FALSE when
639
+	 *                                         you just want to verify the table exists and matches this definition
640
+	 *                                         (and if it HAS data in it you want to leave it be)
641
+	 * @return void
642
+	 * @throws EE_Error if there are database errors
643
+	 */
644
+	public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
645
+	{
646
+		if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
647
+			return;
648
+		}
649
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
650
+		if ( ! function_exists('dbDelta')) {
651
+			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
652
+		}
653
+		$tableAnalysis = \EEH_Activation::getTableAnalysis();
654
+		$wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
655
+		// do we need to first delete an existing version of this table ?
656
+		if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
657
+			// ok, delete the table... but ONLY if it's empty
658
+			$deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
659
+			// table is NOT empty, are you SURE you want to delete this table ???
660
+			if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
661
+				\EEH_Activation::getTableManager()->dropTable($wp_table_name);
662
+			} else if ( ! $deleted_safely) {
663
+				// so we should be more cautious rather than just dropping tables so easily
664
+				error_log(
665
+					sprintf(
666
+						__(
667
+							'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
668
+							'event_espresso'
669
+						),
670
+						$wp_table_name,
671
+						'<br/>',
672
+						'espresso_db_update'
673
+					)
674
+				);
675
+			}
676
+		}
677
+		$engine = str_replace('ENGINE=', '', $engine);
678
+		\EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
679
+	}
680
+
681
+
682
+
683
+	/**
684
+	 *    add_column_if_it_doesn't_exist
685
+	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
686
+	 *
687
+	 * @access     public
688
+	 * @static
689
+	 * @deprecated instead use TableManager::addColumn()
690
+	 * @param string $table_name  (without "wp_", eg "esp_attendee"
691
+	 * @param string $column_name
692
+	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
693
+	 *                            'VARCHAR(10)'
694
+	 * @return bool|int
695
+	 */
696
+	public static function add_column_if_it_doesnt_exist(
697
+		$table_name,
698
+		$column_name,
699
+		$column_info = 'INT UNSIGNED NOT NULL'
700
+	) {
701
+		return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
702
+	}
703
+
704
+
705
+	/**
706
+	 * get_fields_on_table
707
+	 * Gets all the fields on the database table.
708
+	 *
709
+	 * @access     public
710
+	 * @deprecated instead use TableManager::getTableColumns()
711
+	 * @static
712
+	 * @param string $table_name , without prefixed $wpdb->prefix
713
+	 * @return array of database column names
714
+	 */
715
+	public static function get_fields_on_table($table_name = null)
716
+	{
717
+		return \EEH_Activation::getTableManager()->getTableColumns($table_name);
718
+	}
719
+
720
+
721
+	/**
722
+	 * db_table_is_empty
723
+	 *
724
+	 * @access     public\
725
+	 * @deprecated instead use TableAnalysis::tableIsEmpty()
726
+	 * @static
727
+	 * @param string $table_name
728
+	 * @return bool
729
+	 */
730
+	public static function db_table_is_empty($table_name)
731
+	{
732
+		return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
733
+	}
734
+
735
+
736
+	/**
737
+	 * delete_db_table_if_empty
738
+	 *
739
+	 * @access public
740
+	 * @static
741
+	 * @param string $table_name
742
+	 * @return bool | int
743
+	 */
744
+	public static function delete_db_table_if_empty($table_name)
745
+	{
746
+		if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
747
+			return \EEH_Activation::getTableManager()->dropTable($table_name);
748
+		}
749
+		return false;
750
+	}
751
+
752
+
753
+	/**
754
+	 * delete_unused_db_table
755
+	 *
756
+	 * @access     public
757
+	 * @static
758
+	 * @deprecated instead use TableManager::dropTable()
759
+	 * @param string $table_name
760
+	 * @return bool | int
761
+	 */
762
+	public static function delete_unused_db_table($table_name)
763
+	{
764
+		return \EEH_Activation::getTableManager()->dropTable($table_name);
765
+	}
766
+
767
+
768
+	/**
769
+	 * drop_index
770
+	 *
771
+	 * @access     public
772
+	 * @static
773
+	 * @deprecated instead use TableManager::dropIndex()
774
+	 * @param string $table_name
775
+	 * @param string $index_name
776
+	 * @return bool | int
777
+	 */
778
+	public static function drop_index($table_name, $index_name)
779
+	{
780
+		return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
781
+	}
782
+
783
+
784
+
785
+	/**
786
+	 * create_database_tables
787
+	 *
788
+	 * @access public
789
+	 * @static
790
+	 * @throws EE_Error
791
+	 * @return boolean success (whether database is setup properly or not)
792
+	 */
793
+	public static function create_database_tables()
794
+	{
795
+		EE_Registry::instance()->load_core('Data_Migration_Manager');
796
+		//find the migration script that sets the database to be compatible with the code
797
+		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
798
+		if ($dms_name) {
799
+			$current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
800
+			$current_data_migration_script->set_migrating(false);
801
+			$current_data_migration_script->schema_changes_before_migration();
802
+			$current_data_migration_script->schema_changes_after_migration();
803
+			if ($current_data_migration_script->get_errors()) {
804
+				if (WP_DEBUG) {
805
+					foreach ($current_data_migration_script->get_errors() as $error) {
806
+						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
807
+					}
808
+				} else {
809
+					EE_Error::add_error(
810
+						__(
811
+							'There were errors creating the Event Espresso database tables and Event Espresso has been 
812 812
                             deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.',
813
-                            'event_espresso'
814
-                        )
815
-                    );
816
-                }
817
-                return false;
818
-            }
819
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to();
820
-        } else {
821
-            EE_Error::add_error(
822
-                __(
823
-                    'Could not determine most up-to-date data migration script from which to pull database schema
813
+							'event_espresso'
814
+						)
815
+					);
816
+				}
817
+				return false;
818
+			}
819
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
820
+		} else {
821
+			EE_Error::add_error(
822
+				__(
823
+					'Could not determine most up-to-date data migration script from which to pull database schema
824 824
                      structure. So database is probably not setup properly',
825
-                    'event_espresso'
826
-                ),
827
-                __FILE__,
828
-                __FUNCTION__,
829
-                __LINE__
830
-            );
831
-            return false;
832
-        }
833
-        return true;
834
-    }
835
-
836
-
837
-
838
-    /**
839
-     * initialize_system_questions
840
-     *
841
-     * @access public
842
-     * @static
843
-     * @return void
844
-     */
845
-    public static function initialize_system_questions()
846
-    {
847
-        // QUESTION GROUPS
848
-        global $wpdb;
849
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
850
-        $SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
851
-        // what we have
852
-        $question_groups = $wpdb->get_col($SQL);
853
-        // check the response
854
-        $question_groups = is_array($question_groups) ? $question_groups : array();
855
-        // what we should have
856
-        $QSG_systems = array(1, 2);
857
-        // loop thru what we should have and compare to what we have
858
-        foreach ($QSG_systems as $QSG_system) {
859
-            // reset values array
860
-            $QSG_values = array();
861
-            // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
862
-            if (! in_array("$QSG_system", $question_groups)) {
863
-                // add it
864
-                switch ($QSG_system) {
865
-                    case 1:
866
-                        $QSG_values = array(
867
-                            'QSG_name'            => __('Personal Information', 'event_espresso'),
868
-                            'QSG_identifier'      => 'personal-information-' . time(),
869
-                            'QSG_desc'            => '',
870
-                            'QSG_order'           => 1,
871
-                            'QSG_show_group_name' => 1,
872
-                            'QSG_show_group_desc' => 1,
873
-                            'QSG_system'          => EEM_Question_Group::system_personal,
874
-                            'QSG_deleted'         => 0,
875
-                        );
876
-                        break;
877
-                    case 2:
878
-                        $QSG_values = array(
879
-                            'QSG_name'            => __('Address Information', 'event_espresso'),
880
-                            'QSG_identifier'      => 'address-information-' . time(),
881
-                            'QSG_desc'            => '',
882
-                            'QSG_order'           => 2,
883
-                            'QSG_show_group_name' => 1,
884
-                            'QSG_show_group_desc' => 1,
885
-                            'QSG_system'          => EEM_Question_Group::system_address,
886
-                            'QSG_deleted'         => 0,
887
-                        );
888
-                        break;
889
-                }
890
-                // make sure we have some values before inserting them
891
-                if (! empty($QSG_values)) {
892
-                    // insert system question
893
-                    $wpdb->insert(
894
-                        $table_name,
895
-                        $QSG_values,
896
-                        array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
897
-                    );
898
-                    $QSG_IDs[$QSG_system] = $wpdb->insert_id;
899
-                }
900
-            }
901
-        }
902
-        // QUESTIONS
903
-        global $wpdb;
904
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
905
-        $SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
906
-        // what we have
907
-        $questions = $wpdb->get_col($SQL);
908
-        // what we should have
909
-        $QST_systems = array(
910
-            'fname',
911
-            'lname',
912
-            'email',
913
-            'address',
914
-            'address2',
915
-            'city',
916
-            'country',
917
-            'state',
918
-            'zip',
919
-            'phone',
920
-        );
921
-        $order_for_group_1 = 1;
922
-        $order_for_group_2 = 1;
923
-        // loop thru what we should have and compare to what we have
924
-        foreach ($QST_systems as $QST_system) {
925
-            // reset values array
926
-            $QST_values = array();
927
-            // if we don't have what we should have
928
-            if (! in_array($QST_system, $questions)) {
929
-                // add it
930
-                switch ($QST_system) {
931
-                    case 'fname':
932
-                        $QST_values = array(
933
-                            'QST_display_text'  => __('First Name', 'event_espresso'),
934
-                            'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
935
-                            'QST_system'        => 'fname',
936
-                            'QST_type'          => 'TEXT',
937
-                            'QST_required'      => 1,
938
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
939
-                            'QST_order'         => 1,
940
-                            'QST_admin_only'    => 0,
941
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
942
-                            'QST_wp_user'       => self::get_default_creator_id(),
943
-                            'QST_deleted'       => 0,
944
-                        );
945
-                        break;
946
-                    case 'lname':
947
-                        $QST_values = array(
948
-                            'QST_display_text'  => __('Last Name', 'event_espresso'),
949
-                            'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
950
-                            'QST_system'        => 'lname',
951
-                            'QST_type'          => 'TEXT',
952
-                            'QST_required'      => 1,
953
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
954
-                            'QST_order'         => 2,
955
-                            'QST_admin_only'    => 0,
956
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
957
-                            'QST_wp_user'       => self::get_default_creator_id(),
958
-                            'QST_deleted'       => 0,
959
-                        );
960
-                        break;
961
-                    case 'email':
962
-                        $QST_values = array(
963
-                            'QST_display_text'  => __('Email Address', 'event_espresso'),
964
-                            'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
965
-                            'QST_system'        => 'email',
966
-                            'QST_type'          => 'EMAIL',
967
-                            'QST_required'      => 1,
968
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
969
-                            'QST_order'         => 3,
970
-                            'QST_admin_only'    => 0,
971
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
972
-                            'QST_wp_user'       => self::get_default_creator_id(),
973
-                            'QST_deleted'       => 0,
974
-                        );
975
-                        break;
976
-                    case 'address':
977
-                        $QST_values = array(
978
-                            'QST_display_text'  => __('Address', 'event_espresso'),
979
-                            'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
980
-                            'QST_system'        => 'address',
981
-                            'QST_type'          => 'TEXT',
982
-                            'QST_required'      => 0,
983
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
984
-                            'QST_order'         => 4,
985
-                            'QST_admin_only'    => 0,
986
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
987
-                            'QST_wp_user'       => self::get_default_creator_id(),
988
-                            'QST_deleted'       => 0,
989
-                        );
990
-                        break;
991
-                    case 'address2':
992
-                        $QST_values = array(
993
-                            'QST_display_text'  => __('Address2', 'event_espresso'),
994
-                            'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
995
-                            'QST_system'        => 'address2',
996
-                            'QST_type'          => 'TEXT',
997
-                            'QST_required'      => 0,
998
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
999
-                            'QST_order'         => 5,
1000
-                            'QST_admin_only'    => 0,
1001
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1002
-                            'QST_wp_user'       => self::get_default_creator_id(),
1003
-                            'QST_deleted'       => 0,
1004
-                        );
1005
-                        break;
1006
-                    case 'city':
1007
-                        $QST_values = array(
1008
-                            'QST_display_text'  => __('City', 'event_espresso'),
1009
-                            'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1010
-                            'QST_system'        => 'city',
1011
-                            'QST_type'          => 'TEXT',
1012
-                            'QST_required'      => 0,
1013
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1014
-                            'QST_order'         => 6,
1015
-                            'QST_admin_only'    => 0,
1016
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1017
-                            'QST_wp_user'       => self::get_default_creator_id(),
1018
-                            'QST_deleted'       => 0,
1019
-                        );
1020
-                        break;
1021
-                    case 'country':
1022
-                        $QST_values = array(
1023
-                            'QST_display_text'  => __('Country', 'event_espresso'),
1024
-                            'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1025
-                            'QST_system'        => 'country',
1026
-                            'QST_type'          => 'COUNTRY',
1027
-                            'QST_required'      => 0,
1028
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1029
-                            'QST_order'         => 7,
1030
-                            'QST_admin_only'    => 0,
1031
-                            'QST_wp_user'       => self::get_default_creator_id(),
1032
-                            'QST_deleted'       => 0,
1033
-                        );
1034
-                        break;
1035
-                    case 'state':
1036
-                        $QST_values = array(
1037
-                            'QST_display_text'  => __('State/Province', 'event_espresso'),
1038
-                            'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1039
-                            'QST_system'        => 'state',
1040
-                            'QST_type'          => 'STATE',
1041
-                            'QST_required'      => 0,
1042
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1043
-                            'QST_order'         => 8,
1044
-                            'QST_admin_only'    => 0,
1045
-                            'QST_wp_user'       => self::get_default_creator_id(),
1046
-                            'QST_deleted'       => 0,
1047
-                        );
1048
-                        break;
1049
-                    case 'zip':
1050
-                        $QST_values = array(
1051
-                            'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1052
-                            'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1053
-                            'QST_system'        => 'zip',
1054
-                            'QST_type'          => 'TEXT',
1055
-                            'QST_required'      => 0,
1056
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1057
-                            'QST_order'         => 9,
1058
-                            'QST_admin_only'    => 0,
1059
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1060
-                            'QST_wp_user'       => self::get_default_creator_id(),
1061
-                            'QST_deleted'       => 0,
1062
-                        );
1063
-                        break;
1064
-                    case 'phone':
1065
-                        $QST_values = array(
1066
-                            'QST_display_text'  => __('Phone Number', 'event_espresso'),
1067
-                            'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1068
-                            'QST_system'        => 'phone',
1069
-                            'QST_type'          => 'TEXT',
1070
-                            'QST_required'      => 0,
1071
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1072
-                            'QST_order'         => 10,
1073
-                            'QST_admin_only'    => 0,
1074
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1075
-                            'QST_wp_user'       => self::get_default_creator_id(),
1076
-                            'QST_deleted'       => 0,
1077
-                        );
1078
-                        break;
1079
-                }
1080
-                if (! empty($QST_values)) {
1081
-                    // insert system question
1082
-                    $wpdb->insert(
1083
-                        $table_name,
1084
-                        $QST_values,
1085
-                        array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1086
-                    );
1087
-                    $QST_ID = $wpdb->insert_id;
1088
-                    // QUESTION GROUP QUESTIONS
1089
-                    if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1090
-                        $system_question_we_want = EEM_Question_Group::system_personal;
1091
-                    } else {
1092
-                        $system_question_we_want = EEM_Question_Group::system_address;
1093
-                    }
1094
-                    if (isset($QSG_IDs[$system_question_we_want])) {
1095
-                        $QSG_ID = $QSG_IDs[$system_question_we_want];
1096
-                    } else {
1097
-                        $id_col = EEM_Question_Group::instance()
1098
-                                                    ->get_col(array(array('QSG_system' => $system_question_we_want)));
1099
-                        if (is_array($id_col)) {
1100
-                            $QSG_ID = reset($id_col);
1101
-                        } else {
1102
-                            //ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1103
-                            EE_Log::instance()->log(
1104
-                                __FILE__,
1105
-                                __FUNCTION__,
1106
-                                sprintf(
1107
-                                    __(
1108
-                                        'Could not associate question %1$s to a question group because no system question
825
+					'event_espresso'
826
+				),
827
+				__FILE__,
828
+				__FUNCTION__,
829
+				__LINE__
830
+			);
831
+			return false;
832
+		}
833
+		return true;
834
+	}
835
+
836
+
837
+
838
+	/**
839
+	 * initialize_system_questions
840
+	 *
841
+	 * @access public
842
+	 * @static
843
+	 * @return void
844
+	 */
845
+	public static function initialize_system_questions()
846
+	{
847
+		// QUESTION GROUPS
848
+		global $wpdb;
849
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
850
+		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
851
+		// what we have
852
+		$question_groups = $wpdb->get_col($SQL);
853
+		// check the response
854
+		$question_groups = is_array($question_groups) ? $question_groups : array();
855
+		// what we should have
856
+		$QSG_systems = array(1, 2);
857
+		// loop thru what we should have and compare to what we have
858
+		foreach ($QSG_systems as $QSG_system) {
859
+			// reset values array
860
+			$QSG_values = array();
861
+			// if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
862
+			if (! in_array("$QSG_system", $question_groups)) {
863
+				// add it
864
+				switch ($QSG_system) {
865
+					case 1:
866
+						$QSG_values = array(
867
+							'QSG_name'            => __('Personal Information', 'event_espresso'),
868
+							'QSG_identifier'      => 'personal-information-' . time(),
869
+							'QSG_desc'            => '',
870
+							'QSG_order'           => 1,
871
+							'QSG_show_group_name' => 1,
872
+							'QSG_show_group_desc' => 1,
873
+							'QSG_system'          => EEM_Question_Group::system_personal,
874
+							'QSG_deleted'         => 0,
875
+						);
876
+						break;
877
+					case 2:
878
+						$QSG_values = array(
879
+							'QSG_name'            => __('Address Information', 'event_espresso'),
880
+							'QSG_identifier'      => 'address-information-' . time(),
881
+							'QSG_desc'            => '',
882
+							'QSG_order'           => 2,
883
+							'QSG_show_group_name' => 1,
884
+							'QSG_show_group_desc' => 1,
885
+							'QSG_system'          => EEM_Question_Group::system_address,
886
+							'QSG_deleted'         => 0,
887
+						);
888
+						break;
889
+				}
890
+				// make sure we have some values before inserting them
891
+				if (! empty($QSG_values)) {
892
+					// insert system question
893
+					$wpdb->insert(
894
+						$table_name,
895
+						$QSG_values,
896
+						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
897
+					);
898
+					$QSG_IDs[$QSG_system] = $wpdb->insert_id;
899
+				}
900
+			}
901
+		}
902
+		// QUESTIONS
903
+		global $wpdb;
904
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
905
+		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
906
+		// what we have
907
+		$questions = $wpdb->get_col($SQL);
908
+		// what we should have
909
+		$QST_systems = array(
910
+			'fname',
911
+			'lname',
912
+			'email',
913
+			'address',
914
+			'address2',
915
+			'city',
916
+			'country',
917
+			'state',
918
+			'zip',
919
+			'phone',
920
+		);
921
+		$order_for_group_1 = 1;
922
+		$order_for_group_2 = 1;
923
+		// loop thru what we should have and compare to what we have
924
+		foreach ($QST_systems as $QST_system) {
925
+			// reset values array
926
+			$QST_values = array();
927
+			// if we don't have what we should have
928
+			if (! in_array($QST_system, $questions)) {
929
+				// add it
930
+				switch ($QST_system) {
931
+					case 'fname':
932
+						$QST_values = array(
933
+							'QST_display_text'  => __('First Name', 'event_espresso'),
934
+							'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
935
+							'QST_system'        => 'fname',
936
+							'QST_type'          => 'TEXT',
937
+							'QST_required'      => 1,
938
+							'QST_required_text' => __('This field is required', 'event_espresso'),
939
+							'QST_order'         => 1,
940
+							'QST_admin_only'    => 0,
941
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
942
+							'QST_wp_user'       => self::get_default_creator_id(),
943
+							'QST_deleted'       => 0,
944
+						);
945
+						break;
946
+					case 'lname':
947
+						$QST_values = array(
948
+							'QST_display_text'  => __('Last Name', 'event_espresso'),
949
+							'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
950
+							'QST_system'        => 'lname',
951
+							'QST_type'          => 'TEXT',
952
+							'QST_required'      => 1,
953
+							'QST_required_text' => __('This field is required', 'event_espresso'),
954
+							'QST_order'         => 2,
955
+							'QST_admin_only'    => 0,
956
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
957
+							'QST_wp_user'       => self::get_default_creator_id(),
958
+							'QST_deleted'       => 0,
959
+						);
960
+						break;
961
+					case 'email':
962
+						$QST_values = array(
963
+							'QST_display_text'  => __('Email Address', 'event_espresso'),
964
+							'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
965
+							'QST_system'        => 'email',
966
+							'QST_type'          => 'EMAIL',
967
+							'QST_required'      => 1,
968
+							'QST_required_text' => __('This field is required', 'event_espresso'),
969
+							'QST_order'         => 3,
970
+							'QST_admin_only'    => 0,
971
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
972
+							'QST_wp_user'       => self::get_default_creator_id(),
973
+							'QST_deleted'       => 0,
974
+						);
975
+						break;
976
+					case 'address':
977
+						$QST_values = array(
978
+							'QST_display_text'  => __('Address', 'event_espresso'),
979
+							'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
980
+							'QST_system'        => 'address',
981
+							'QST_type'          => 'TEXT',
982
+							'QST_required'      => 0,
983
+							'QST_required_text' => __('This field is required', 'event_espresso'),
984
+							'QST_order'         => 4,
985
+							'QST_admin_only'    => 0,
986
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
987
+							'QST_wp_user'       => self::get_default_creator_id(),
988
+							'QST_deleted'       => 0,
989
+						);
990
+						break;
991
+					case 'address2':
992
+						$QST_values = array(
993
+							'QST_display_text'  => __('Address2', 'event_espresso'),
994
+							'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
995
+							'QST_system'        => 'address2',
996
+							'QST_type'          => 'TEXT',
997
+							'QST_required'      => 0,
998
+							'QST_required_text' => __('This field is required', 'event_espresso'),
999
+							'QST_order'         => 5,
1000
+							'QST_admin_only'    => 0,
1001
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1002
+							'QST_wp_user'       => self::get_default_creator_id(),
1003
+							'QST_deleted'       => 0,
1004
+						);
1005
+						break;
1006
+					case 'city':
1007
+						$QST_values = array(
1008
+							'QST_display_text'  => __('City', 'event_espresso'),
1009
+							'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1010
+							'QST_system'        => 'city',
1011
+							'QST_type'          => 'TEXT',
1012
+							'QST_required'      => 0,
1013
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1014
+							'QST_order'         => 6,
1015
+							'QST_admin_only'    => 0,
1016
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1017
+							'QST_wp_user'       => self::get_default_creator_id(),
1018
+							'QST_deleted'       => 0,
1019
+						);
1020
+						break;
1021
+					case 'country':
1022
+						$QST_values = array(
1023
+							'QST_display_text'  => __('Country', 'event_espresso'),
1024
+							'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1025
+							'QST_system'        => 'country',
1026
+							'QST_type'          => 'COUNTRY',
1027
+							'QST_required'      => 0,
1028
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1029
+							'QST_order'         => 7,
1030
+							'QST_admin_only'    => 0,
1031
+							'QST_wp_user'       => self::get_default_creator_id(),
1032
+							'QST_deleted'       => 0,
1033
+						);
1034
+						break;
1035
+					case 'state':
1036
+						$QST_values = array(
1037
+							'QST_display_text'  => __('State/Province', 'event_espresso'),
1038
+							'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1039
+							'QST_system'        => 'state',
1040
+							'QST_type'          => 'STATE',
1041
+							'QST_required'      => 0,
1042
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1043
+							'QST_order'         => 8,
1044
+							'QST_admin_only'    => 0,
1045
+							'QST_wp_user'       => self::get_default_creator_id(),
1046
+							'QST_deleted'       => 0,
1047
+						);
1048
+						break;
1049
+					case 'zip':
1050
+						$QST_values = array(
1051
+							'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1052
+							'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1053
+							'QST_system'        => 'zip',
1054
+							'QST_type'          => 'TEXT',
1055
+							'QST_required'      => 0,
1056
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1057
+							'QST_order'         => 9,
1058
+							'QST_admin_only'    => 0,
1059
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1060
+							'QST_wp_user'       => self::get_default_creator_id(),
1061
+							'QST_deleted'       => 0,
1062
+						);
1063
+						break;
1064
+					case 'phone':
1065
+						$QST_values = array(
1066
+							'QST_display_text'  => __('Phone Number', 'event_espresso'),
1067
+							'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1068
+							'QST_system'        => 'phone',
1069
+							'QST_type'          => 'TEXT',
1070
+							'QST_required'      => 0,
1071
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1072
+							'QST_order'         => 10,
1073
+							'QST_admin_only'    => 0,
1074
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1075
+							'QST_wp_user'       => self::get_default_creator_id(),
1076
+							'QST_deleted'       => 0,
1077
+						);
1078
+						break;
1079
+				}
1080
+				if (! empty($QST_values)) {
1081
+					// insert system question
1082
+					$wpdb->insert(
1083
+						$table_name,
1084
+						$QST_values,
1085
+						array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1086
+					);
1087
+					$QST_ID = $wpdb->insert_id;
1088
+					// QUESTION GROUP QUESTIONS
1089
+					if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1090
+						$system_question_we_want = EEM_Question_Group::system_personal;
1091
+					} else {
1092
+						$system_question_we_want = EEM_Question_Group::system_address;
1093
+					}
1094
+					if (isset($QSG_IDs[$system_question_we_want])) {
1095
+						$QSG_ID = $QSG_IDs[$system_question_we_want];
1096
+					} else {
1097
+						$id_col = EEM_Question_Group::instance()
1098
+													->get_col(array(array('QSG_system' => $system_question_we_want)));
1099
+						if (is_array($id_col)) {
1100
+							$QSG_ID = reset($id_col);
1101
+						} else {
1102
+							//ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1103
+							EE_Log::instance()->log(
1104
+								__FILE__,
1105
+								__FUNCTION__,
1106
+								sprintf(
1107
+									__(
1108
+										'Could not associate question %1$s to a question group because no system question
1109 1109
                                          group existed',
1110
-                                        'event_espresso'
1111
-                                    ),
1112
-                                    $QST_ID),
1113
-                                'error');
1114
-                            continue;
1115
-                        }
1116
-                    }
1117
-                    // add system questions to groups
1118
-                    $wpdb->insert(
1119
-                        \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1120
-                        array(
1121
-                            'QSG_ID'    => $QSG_ID,
1122
-                            'QST_ID'    => $QST_ID,
1123
-                            'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1124
-                        ),
1125
-                        array('%d', '%d', '%d')
1126
-                    );
1127
-                }
1128
-            }
1129
-        }
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     * Makes sure the default payment method (Invoice) is active.
1135
-     * This used to be done automatically as part of constructing the old gateways config
1136
-     *
1137
-     * @throws \EE_Error
1138
-     */
1139
-    public static function insert_default_payment_methods()
1140
-    {
1141
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1142
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
1143
-            EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1144
-        } else {
1145
-            EEM_Payment_Method::instance()->verify_button_urls();
1146
-        }
1147
-    }
1148
-
1149
-    /**
1150
-     * insert_default_status_codes
1151
-     *
1152
-     * @access public
1153
-     * @static
1154
-     * @return void
1155
-     */
1156
-    public static function insert_default_status_codes()
1157
-    {
1158
-
1159
-        global $wpdb;
1160
-
1161
-        if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1162
-
1163
-            $table_name = EEM_Status::instance()->table();
1164
-
1165
-            $SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1166
-            $wpdb->query($SQL);
1167
-
1168
-            $SQL = "INSERT INTO $table_name
1110
+										'event_espresso'
1111
+									),
1112
+									$QST_ID),
1113
+								'error');
1114
+							continue;
1115
+						}
1116
+					}
1117
+					// add system questions to groups
1118
+					$wpdb->insert(
1119
+						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1120
+						array(
1121
+							'QSG_ID'    => $QSG_ID,
1122
+							'QST_ID'    => $QST_ID,
1123
+							'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1124
+						),
1125
+						array('%d', '%d', '%d')
1126
+					);
1127
+				}
1128
+			}
1129
+		}
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 * Makes sure the default payment method (Invoice) is active.
1135
+	 * This used to be done automatically as part of constructing the old gateways config
1136
+	 *
1137
+	 * @throws \EE_Error
1138
+	 */
1139
+	public static function insert_default_payment_methods()
1140
+	{
1141
+		if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1142
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
1143
+			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1144
+		} else {
1145
+			EEM_Payment_Method::instance()->verify_button_urls();
1146
+		}
1147
+	}
1148
+
1149
+	/**
1150
+	 * insert_default_status_codes
1151
+	 *
1152
+	 * @access public
1153
+	 * @static
1154
+	 * @return void
1155
+	 */
1156
+	public static function insert_default_status_codes()
1157
+	{
1158
+
1159
+		global $wpdb;
1160
+
1161
+		if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1162
+
1163
+			$table_name = EEM_Status::instance()->table();
1164
+
1165
+			$SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1166
+			$wpdb->query($SQL);
1167
+
1168
+			$SQL = "INSERT INTO $table_name
1169 1169
 					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1170 1170
 					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1171 1171
 					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
@@ -1205,462 +1205,462 @@  discard block
 block discarded – undo
1205 1205
 					('MID', 'IDLE', 'message', 0, NULL, 1),
1206 1206
 					('MRS', 'RESEND', 'message', 0, NULL, 1),
1207 1207
 					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1208
-            $wpdb->query($SQL);
1209
-
1210
-        }
1211
-
1212
-    }
1213
-
1214
-
1215
-    /**
1216
-     * generate_default_message_templates
1217
-     *
1218
-     * @static
1219
-     * @throws EE_Error
1220
-     * @return bool     true means new templates were created.
1221
-     *                  false means no templates were created.
1222
-     *                  This is NOT an error flag. To check for errors you will want
1223
-     *                  to use either EE_Error or a try catch for an EE_Error exception.
1224
-     */
1225
-    public static function generate_default_message_templates()
1226
-    {
1227
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1228
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1229
-        /*
1208
+			$wpdb->query($SQL);
1209
+
1210
+		}
1211
+
1212
+	}
1213
+
1214
+
1215
+	/**
1216
+	 * generate_default_message_templates
1217
+	 *
1218
+	 * @static
1219
+	 * @throws EE_Error
1220
+	 * @return bool     true means new templates were created.
1221
+	 *                  false means no templates were created.
1222
+	 *                  This is NOT an error flag. To check for errors you will want
1223
+	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1224
+	 */
1225
+	public static function generate_default_message_templates()
1226
+	{
1227
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1228
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1229
+		/*
1230 1230
          * This first method is taking care of ensuring any default messengers
1231 1231
          * that should be made active and have templates generated are done.
1232 1232
          */
1233
-        $new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1234
-            $message_resource_manager
1235
-        );
1236
-        /**
1237
-         * This method is verifying there are no NEW default message types
1238
-         * for ACTIVE messengers that need activated (and corresponding templates setup).
1239
-         */
1240
-        $new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1241
-            $message_resource_manager
1242
-        );
1243
-        //after all is done, let's persist these changes to the db.
1244
-        $message_resource_manager->update_has_activated_messengers_option();
1245
-        $message_resource_manager->update_active_messengers_option();
1246
-        // will return true if either of these are true.  Otherwise will return false.
1247
-        return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1248
-    }
1249
-
1250
-
1251
-
1252
-    /**
1253
-     * @param \EE_Message_Resource_Manager $message_resource_manager
1254
-     * @return array|bool
1255
-     * @throws \EE_Error
1256
-     */
1257
-    protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1258
-        EE_Message_Resource_Manager $message_resource_manager
1259
-    ) {
1260
-        /** @type EE_messenger[] $active_messengers */
1261
-        $active_messengers = $message_resource_manager->active_messengers();
1262
-        $installed_message_types = $message_resource_manager->installed_message_types();
1263
-        $templates_created = false;
1264
-        foreach ($active_messengers as $active_messenger) {
1265
-            $default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1266
-            $default_message_type_names_to_activate = array();
1267
-            // looping through each default message type reported by the messenger
1268
-            // and setup the actual message types to activate.
1269
-            foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1270
-                // if already active or has already been activated before we skip
1271
-                // (otherwise we might reactivate something user's intentionally deactivated.)
1272
-                // we also skip if the message type is not installed.
1273
-                if (
1274
-                    $message_resource_manager->has_message_type_been_activated_for_messenger(
1275
-                        $default_message_type_name_for_messenger,
1276
-                        $active_messenger->name
1277
-                    )
1278
-                    || $message_resource_manager->is_message_type_active_for_messenger(
1279
-                        $active_messenger->name,
1280
-                        $default_message_type_name_for_messenger
1281
-                    )
1282
-                    || ! isset($installed_message_types[$default_message_type_name_for_messenger])
1283
-                ) {
1284
-                    continue;
1285
-                }
1286
-                $default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1287
-            }
1288
-            //let's activate!
1289
-            $message_resource_manager->ensure_message_types_are_active(
1290
-                $default_message_type_names_to_activate,
1291
-                $active_messenger->name,
1292
-                false
1293
-            );
1294
-            //activate the templates for these message types
1295
-            if ( ! empty($default_message_type_names_to_activate)) {
1296
-                $templates_created = EEH_MSG_Template::generate_new_templates(
1297
-                    $active_messenger->name,
1298
-                    $default_message_type_names_for_messenger,
1299
-                    '',
1300
-                    true
1301
-                );
1302
-            }
1303
-        }
1304
-        return $templates_created;
1305
-    }
1306
-
1307
-
1308
-
1309
-    /**
1310
-     * This will activate and generate default messengers and default message types for those messengers.
1311
-     *
1312
-     * @param EE_message_Resource_Manager $message_resource_manager
1313
-     * @return array|bool  True means there were default messengers and message type templates generated.
1314
-     *                     False means that there were no templates generated
1315
-     *                     (which could simply mean there are no default message types for a messenger).
1316
-     * @throws EE_Error
1317
-     */
1318
-    protected static function _activate_and_generate_default_messengers_and_message_templates(
1319
-        EE_Message_Resource_Manager $message_resource_manager
1320
-    ) {
1321
-        /** @type EE_messenger[] $messengers_to_generate */
1322
-        $messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1323
-        $installed_message_types = $message_resource_manager->installed_message_types();
1324
-        $templates_generated = false;
1325
-        foreach ($messengers_to_generate as $messenger_to_generate) {
1326
-            $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1327
-            //verify the default message types match an installed message type.
1328
-            foreach ($default_message_type_names_for_messenger as $key => $name) {
1329
-                if (
1330
-                    ! isset($installed_message_types[$name])
1331
-                    || $message_resource_manager->has_message_type_been_activated_for_messenger(
1332
-                        $name,
1333
-                        $messenger_to_generate->name
1334
-                    )
1335
-                ) {
1336
-                    unset($default_message_type_names_for_messenger[$key]);
1337
-                }
1338
-            }
1339
-            // in previous iterations, the active_messengers option in the db
1340
-            // needed updated before calling create templates. however with the changes this may not be necessary.
1341
-            // This comment is left here just in case we discover that we _do_ need to update before
1342
-            // passing off to create templates (after the refactor is done).
1343
-            // @todo remove this comment when determined not necessary.
1344
-            $message_resource_manager->activate_messenger(
1345
-                $messenger_to_generate->name,
1346
-                $default_message_type_names_for_messenger,
1347
-                false
1348
-            );
1349
-            //create any templates needing created (or will reactivate templates already generated as necessary).
1350
-            if ( ! empty($default_message_type_names_for_messenger)) {
1351
-                $templates_generated = EEH_MSG_Template::generate_new_templates(
1352
-                    $messenger_to_generate->name,
1353
-                    $default_message_type_names_for_messenger,
1354
-                    '',
1355
-                    true
1356
-                );
1357
-            }
1358
-        }
1359
-        return $templates_generated;
1360
-    }
1361
-
1362
-
1363
-    /**
1364
-     * This returns the default messengers to generate templates for on activation of EE.
1365
-     * It considers:
1366
-     * - whether a messenger is already active in the db.
1367
-     * - whether a messenger has been made active at any time in the past.
1368
-     *
1369
-     * @static
1370
-     * @param  EE_Message_Resource_Manager $message_resource_manager
1371
-     * @return EE_messenger[]
1372
-     */
1373
-    protected static function _get_default_messengers_to_generate_on_activation(
1374
-        EE_Message_Resource_Manager $message_resource_manager
1375
-    ) {
1376
-        $active_messengers    = $message_resource_manager->active_messengers();
1377
-        $installed_messengers = $message_resource_manager->installed_messengers();
1378
-        $has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1379
-
1380
-        $messengers_to_generate = array();
1381
-        foreach ($installed_messengers as $installed_messenger) {
1382
-            //if installed messenger is a messenger that should be activated on install
1383
-            //and is not already active
1384
-            //and has never been activated
1385
-            if (
1386
-                ! $installed_messenger->activate_on_install
1387
-                || isset($active_messengers[$installed_messenger->name])
1388
-                || isset($has_activated[$installed_messenger->name])
1389
-            ) {
1390
-                continue;
1391
-            }
1392
-            $messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1393
-        }
1394
-        return $messengers_to_generate;
1395
-    }
1396
-
1397
-
1398
-    /**
1399
-     * This simply validates active message types to ensure they actually match installed
1400
-     * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1401
-     * rows are set inactive.
1402
-     * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1403
-     * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1404
-     * are still handled in here.
1405
-     *
1406
-     * @since 4.3.1
1407
-     * @return void
1408
-     */
1409
-    public static function validate_messages_system()
1410
-    {
1411
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1412
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1413
-        $message_resource_manager->validate_active_message_types_are_installed();
1414
-        do_action('AHEE__EEH_Activation__validate_messages_system');
1415
-    }
1416
-
1417
-
1418
-    /**
1419
-     * create_no_ticket_prices_array
1420
-     *
1421
-     * @access public
1422
-     * @static
1423
-     * @return void
1424
-     */
1425
-    public static function create_no_ticket_prices_array()
1426
-    {
1427
-        // this creates an array for tracking events that have no active ticket prices created
1428
-        // this allows us to warn admins of the situation so that it can be corrected
1429
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1430
-        if (! $espresso_no_ticket_prices) {
1431
-            add_option('ee_no_ticket_prices', array(), '', false);
1432
-        }
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * plugin_deactivation
1438
-     *
1439
-     * @access public
1440
-     * @static
1441
-     * @return void
1442
-     */
1443
-    public static function plugin_deactivation()
1444
-    {
1445
-    }
1446
-
1447
-
1448
-    /**
1449
-     * Finds all our EE4 custom post types, and deletes them and their associated data
1450
-     * (like post meta or term relations)
1451
-     *
1452
-     * @global wpdb $wpdb
1453
-     * @throws \EE_Error
1454
-     */
1455
-    public static function delete_all_espresso_cpt_data()
1456
-    {
1457
-        global $wpdb;
1458
-        //get all the CPT post_types
1459
-        $ee_post_types = array();
1460
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1461
-            if (method_exists($model_name, 'instance')) {
1462
-                $model_obj = call_user_func(array($model_name, 'instance'));
1463
-                if ($model_obj instanceof EEM_CPT_Base) {
1464
-                    $ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1465
-                }
1466
-            }
1467
-        }
1468
-        //get all our CPTs
1469
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1470
-        $cpt_ids = $wpdb->get_col($query);
1471
-        //delete each post meta and term relations too
1472
-        foreach ($cpt_ids as $post_id) {
1473
-            wp_delete_post($post_id, true);
1474
-        }
1475
-    }
1476
-
1477
-    /**
1478
-     * Deletes all EE custom tables
1479
-     *
1480
-     * @return array
1481
-     */
1482
-    public static function drop_espresso_tables()
1483
-    {
1484
-        $tables = array();
1485
-        // load registry
1486
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1487
-            if (method_exists($model_name, 'instance')) {
1488
-                $model_obj = call_user_func(array($model_name, 'instance'));
1489
-                if ($model_obj instanceof EEM_Base) {
1490
-                    foreach ($model_obj->get_tables() as $table) {
1491
-                        if (strpos($table->get_table_name(), 'esp_')
1492
-                            &&
1493
-                            (
1494
-                                is_main_site()//main site? nuke them all
1495
-                                || ! $table->is_global()//not main site,but not global either. nuke it
1496
-                            )
1497
-                        ) {
1498
-                            $tables[$table->get_table_name()] = $table->get_table_name();
1499
-                        }
1500
-                    }
1501
-                }
1502
-            }
1503
-        }
1504
-
1505
-        //there are some tables whose models were removed.
1506
-        //they should be removed when removing all EE core's data
1507
-        $tables_without_models = array(
1508
-            'esp_promotion',
1509
-            'esp_promotion_applied',
1510
-            'esp_promotion_object',
1511
-            'esp_promotion_rule',
1512
-            'esp_rule',
1513
-        );
1514
-        foreach ($tables_without_models as $table) {
1515
-            $tables[$table] = $table;
1516
-        }
1517
-        return \EEH_Activation::getTableManager()->dropTables($tables);
1518
-    }
1519
-
1520
-
1521
-
1522
-    /**
1523
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
1524
-     * each table name provided has a wpdb prefix attached, and that it exists.
1525
-     * Returns the list actually deleted
1526
-     *
1527
-     * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1528
-     * @global WPDB $wpdb
1529
-     * @param array $table_names
1530
-     * @return array of table names which we deleted
1531
-     */
1532
-    public static function drop_tables($table_names)
1533
-    {
1534
-        return \EEH_Activation::getTableManager()->dropTables($table_names);
1535
-    }
1536
-
1537
-
1538
-
1539
-    /**
1540
-     * plugin_uninstall
1541
-     *
1542
-     * @access public
1543
-     * @static
1544
-     * @param bool $remove_all
1545
-     * @return void
1546
-     */
1547
-    public static function delete_all_espresso_tables_and_data($remove_all = true)
1548
-    {
1549
-        global $wpdb;
1550
-        self::drop_espresso_tables();
1551
-        $wp_options_to_delete = array(
1552
-            'ee_no_ticket_prices'                => true,
1553
-            'ee_active_messengers'               => true,
1554
-            'ee_has_activated_messenger'         => true,
1555
-            'ee_flush_rewrite_rules'             => true,
1556
-            'ee_config'                          => false,
1557
-            'ee_data_migration_current_db_state' => true,
1558
-            'ee_data_migration_mapping_'         => false,
1559
-            'ee_data_migration_script_'          => false,
1560
-            'ee_data_migrations'                 => true,
1561
-            'ee_dms_map'                         => false,
1562
-            'ee_notices'                         => true,
1563
-            'lang_file_check_'                   => false,
1564
-            'ee_maintenance_mode'                => true,
1565
-            'ee_ueip_optin'                      => true,
1566
-            'ee_ueip_has_notified'               => true,
1567
-            'ee_plugin_activation_errors'        => true,
1568
-            'ee_id_mapping_from'                 => false,
1569
-            'espresso_persistent_admin_notices'  => true,
1570
-            'ee_encryption_key'                  => true,
1571
-            'pue_force_upgrade_'                 => false,
1572
-            'pue_json_error_'                    => false,
1573
-            'pue_install_key_'                   => false,
1574
-            'pue_verification_error_'            => false,
1575
-            'pu_dismissed_upgrade_'              => false,
1576
-            'external_updates-'                  => false,
1577
-            'ee_extra_data'                      => true,
1578
-            'ee_ssn_'                            => false,
1579
-            'ee_rss_'                            => false,
1580
-            'ee_rte_n_tx_'                       => false,
1581
-            'ee_pers_admin_notices'              => true,
1582
-            'ee_job_parameters_'                 => false,
1583
-            'ee_upload_directories_incomplete'   => true,
1584
-            'ee_verified_db_collations'          => true,
1585
-        );
1586
-        if (is_main_site()) {
1587
-            $wp_options_to_delete['ee_network_config'] = true;
1588
-        }
1589
-        $undeleted_options = array();
1590
-        foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1591
-            if ($no_wildcard) {
1592
-                if ( ! delete_option($option_name)) {
1593
-                    $undeleted_options[] = $option_name;
1594
-                }
1595
-            } else {
1596
-                $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1597
-                foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1598
-                    if ( ! delete_option($option_name_from_wildcard)) {
1599
-                        $undeleted_options[] = $option_name_from_wildcard;
1600
-                    }
1601
-                }
1602
-            }
1603
-        }
1604
-        //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1605
-        remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1606
-        if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1607
-            $db_update_sans_ee4 = array();
1608
-            foreach ($espresso_db_update as $version => $times_activated) {
1609
-                if ((string)$version[0] === '3') {//if its NON EE4
1610
-                    $db_update_sans_ee4[$version] = $times_activated;
1611
-                }
1612
-            }
1613
-            update_option('espresso_db_update', $db_update_sans_ee4);
1614
-        }
1615
-        $errors = '';
1616
-        if ( ! empty($undeleted_options)) {
1617
-            $errors .= sprintf(
1618
-                __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1619
-                '<br/>',
1620
-                implode(',<br/>', $undeleted_options)
1621
-            );
1622
-        }
1623
-        if ( ! empty($errors)) {
1624
-            EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1625
-        }
1626
-    }
1627
-
1628
-    /**
1629
-     * Gets the mysql error code from the last used query by wpdb
1630
-     *
1631
-     * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1632
-     */
1633
-    public static function last_wpdb_error_code()
1634
-    {
1635
-        global $wpdb;
1636
-        if ($wpdb->use_mysqli) {
1637
-            return mysqli_errno($wpdb->dbh);
1638
-        } else {
1639
-            return mysql_errno($wpdb->dbh);
1640
-        }
1641
-    }
1642
-
1643
-    /**
1644
-     * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1645
-     *
1646
-     * @global wpdb  $wpdb
1647
-     * @deprecated instead use TableAnalysis::tableExists()
1648
-     * @param string $table_name with or without $wpdb->prefix
1649
-     * @return boolean
1650
-     */
1651
-    public static function table_exists($table_name)
1652
-    {
1653
-        return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1654
-    }
1655
-
1656
-    /**
1657
-     * Resets the cache on EEH_Activation
1658
-     */
1659
-    public static function reset()
1660
-    {
1661
-        self::$_default_creator_id                             = null;
1662
-        self::$_initialized_db_content_already_in_this_request = false;
1663
-    }
1233
+		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1234
+			$message_resource_manager
1235
+		);
1236
+		/**
1237
+		 * This method is verifying there are no NEW default message types
1238
+		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1239
+		 */
1240
+		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1241
+			$message_resource_manager
1242
+		);
1243
+		//after all is done, let's persist these changes to the db.
1244
+		$message_resource_manager->update_has_activated_messengers_option();
1245
+		$message_resource_manager->update_active_messengers_option();
1246
+		// will return true if either of these are true.  Otherwise will return false.
1247
+		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1248
+	}
1249
+
1250
+
1251
+
1252
+	/**
1253
+	 * @param \EE_Message_Resource_Manager $message_resource_manager
1254
+	 * @return array|bool
1255
+	 * @throws \EE_Error
1256
+	 */
1257
+	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1258
+		EE_Message_Resource_Manager $message_resource_manager
1259
+	) {
1260
+		/** @type EE_messenger[] $active_messengers */
1261
+		$active_messengers = $message_resource_manager->active_messengers();
1262
+		$installed_message_types = $message_resource_manager->installed_message_types();
1263
+		$templates_created = false;
1264
+		foreach ($active_messengers as $active_messenger) {
1265
+			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1266
+			$default_message_type_names_to_activate = array();
1267
+			// looping through each default message type reported by the messenger
1268
+			// and setup the actual message types to activate.
1269
+			foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1270
+				// if already active or has already been activated before we skip
1271
+				// (otherwise we might reactivate something user's intentionally deactivated.)
1272
+				// we also skip if the message type is not installed.
1273
+				if (
1274
+					$message_resource_manager->has_message_type_been_activated_for_messenger(
1275
+						$default_message_type_name_for_messenger,
1276
+						$active_messenger->name
1277
+					)
1278
+					|| $message_resource_manager->is_message_type_active_for_messenger(
1279
+						$active_messenger->name,
1280
+						$default_message_type_name_for_messenger
1281
+					)
1282
+					|| ! isset($installed_message_types[$default_message_type_name_for_messenger])
1283
+				) {
1284
+					continue;
1285
+				}
1286
+				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1287
+			}
1288
+			//let's activate!
1289
+			$message_resource_manager->ensure_message_types_are_active(
1290
+				$default_message_type_names_to_activate,
1291
+				$active_messenger->name,
1292
+				false
1293
+			);
1294
+			//activate the templates for these message types
1295
+			if ( ! empty($default_message_type_names_to_activate)) {
1296
+				$templates_created = EEH_MSG_Template::generate_new_templates(
1297
+					$active_messenger->name,
1298
+					$default_message_type_names_for_messenger,
1299
+					'',
1300
+					true
1301
+				);
1302
+			}
1303
+		}
1304
+		return $templates_created;
1305
+	}
1306
+
1307
+
1308
+
1309
+	/**
1310
+	 * This will activate and generate default messengers and default message types for those messengers.
1311
+	 *
1312
+	 * @param EE_message_Resource_Manager $message_resource_manager
1313
+	 * @return array|bool  True means there were default messengers and message type templates generated.
1314
+	 *                     False means that there were no templates generated
1315
+	 *                     (which could simply mean there are no default message types for a messenger).
1316
+	 * @throws EE_Error
1317
+	 */
1318
+	protected static function _activate_and_generate_default_messengers_and_message_templates(
1319
+		EE_Message_Resource_Manager $message_resource_manager
1320
+	) {
1321
+		/** @type EE_messenger[] $messengers_to_generate */
1322
+		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1323
+		$installed_message_types = $message_resource_manager->installed_message_types();
1324
+		$templates_generated = false;
1325
+		foreach ($messengers_to_generate as $messenger_to_generate) {
1326
+			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1327
+			//verify the default message types match an installed message type.
1328
+			foreach ($default_message_type_names_for_messenger as $key => $name) {
1329
+				if (
1330
+					! isset($installed_message_types[$name])
1331
+					|| $message_resource_manager->has_message_type_been_activated_for_messenger(
1332
+						$name,
1333
+						$messenger_to_generate->name
1334
+					)
1335
+				) {
1336
+					unset($default_message_type_names_for_messenger[$key]);
1337
+				}
1338
+			}
1339
+			// in previous iterations, the active_messengers option in the db
1340
+			// needed updated before calling create templates. however with the changes this may not be necessary.
1341
+			// This comment is left here just in case we discover that we _do_ need to update before
1342
+			// passing off to create templates (after the refactor is done).
1343
+			// @todo remove this comment when determined not necessary.
1344
+			$message_resource_manager->activate_messenger(
1345
+				$messenger_to_generate->name,
1346
+				$default_message_type_names_for_messenger,
1347
+				false
1348
+			);
1349
+			//create any templates needing created (or will reactivate templates already generated as necessary).
1350
+			if ( ! empty($default_message_type_names_for_messenger)) {
1351
+				$templates_generated = EEH_MSG_Template::generate_new_templates(
1352
+					$messenger_to_generate->name,
1353
+					$default_message_type_names_for_messenger,
1354
+					'',
1355
+					true
1356
+				);
1357
+			}
1358
+		}
1359
+		return $templates_generated;
1360
+	}
1361
+
1362
+
1363
+	/**
1364
+	 * This returns the default messengers to generate templates for on activation of EE.
1365
+	 * It considers:
1366
+	 * - whether a messenger is already active in the db.
1367
+	 * - whether a messenger has been made active at any time in the past.
1368
+	 *
1369
+	 * @static
1370
+	 * @param  EE_Message_Resource_Manager $message_resource_manager
1371
+	 * @return EE_messenger[]
1372
+	 */
1373
+	protected static function _get_default_messengers_to_generate_on_activation(
1374
+		EE_Message_Resource_Manager $message_resource_manager
1375
+	) {
1376
+		$active_messengers    = $message_resource_manager->active_messengers();
1377
+		$installed_messengers = $message_resource_manager->installed_messengers();
1378
+		$has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1379
+
1380
+		$messengers_to_generate = array();
1381
+		foreach ($installed_messengers as $installed_messenger) {
1382
+			//if installed messenger is a messenger that should be activated on install
1383
+			//and is not already active
1384
+			//and has never been activated
1385
+			if (
1386
+				! $installed_messenger->activate_on_install
1387
+				|| isset($active_messengers[$installed_messenger->name])
1388
+				|| isset($has_activated[$installed_messenger->name])
1389
+			) {
1390
+				continue;
1391
+			}
1392
+			$messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1393
+		}
1394
+		return $messengers_to_generate;
1395
+	}
1396
+
1397
+
1398
+	/**
1399
+	 * This simply validates active message types to ensure they actually match installed
1400
+	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1401
+	 * rows are set inactive.
1402
+	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1403
+	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1404
+	 * are still handled in here.
1405
+	 *
1406
+	 * @since 4.3.1
1407
+	 * @return void
1408
+	 */
1409
+	public static function validate_messages_system()
1410
+	{
1411
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1412
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1413
+		$message_resource_manager->validate_active_message_types_are_installed();
1414
+		do_action('AHEE__EEH_Activation__validate_messages_system');
1415
+	}
1416
+
1417
+
1418
+	/**
1419
+	 * create_no_ticket_prices_array
1420
+	 *
1421
+	 * @access public
1422
+	 * @static
1423
+	 * @return void
1424
+	 */
1425
+	public static function create_no_ticket_prices_array()
1426
+	{
1427
+		// this creates an array for tracking events that have no active ticket prices created
1428
+		// this allows us to warn admins of the situation so that it can be corrected
1429
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1430
+		if (! $espresso_no_ticket_prices) {
1431
+			add_option('ee_no_ticket_prices', array(), '', false);
1432
+		}
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * plugin_deactivation
1438
+	 *
1439
+	 * @access public
1440
+	 * @static
1441
+	 * @return void
1442
+	 */
1443
+	public static function plugin_deactivation()
1444
+	{
1445
+	}
1446
+
1447
+
1448
+	/**
1449
+	 * Finds all our EE4 custom post types, and deletes them and their associated data
1450
+	 * (like post meta or term relations)
1451
+	 *
1452
+	 * @global wpdb $wpdb
1453
+	 * @throws \EE_Error
1454
+	 */
1455
+	public static function delete_all_espresso_cpt_data()
1456
+	{
1457
+		global $wpdb;
1458
+		//get all the CPT post_types
1459
+		$ee_post_types = array();
1460
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1461
+			if (method_exists($model_name, 'instance')) {
1462
+				$model_obj = call_user_func(array($model_name, 'instance'));
1463
+				if ($model_obj instanceof EEM_CPT_Base) {
1464
+					$ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1465
+				}
1466
+			}
1467
+		}
1468
+		//get all our CPTs
1469
+		$query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1470
+		$cpt_ids = $wpdb->get_col($query);
1471
+		//delete each post meta and term relations too
1472
+		foreach ($cpt_ids as $post_id) {
1473
+			wp_delete_post($post_id, true);
1474
+		}
1475
+	}
1476
+
1477
+	/**
1478
+	 * Deletes all EE custom tables
1479
+	 *
1480
+	 * @return array
1481
+	 */
1482
+	public static function drop_espresso_tables()
1483
+	{
1484
+		$tables = array();
1485
+		// load registry
1486
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1487
+			if (method_exists($model_name, 'instance')) {
1488
+				$model_obj = call_user_func(array($model_name, 'instance'));
1489
+				if ($model_obj instanceof EEM_Base) {
1490
+					foreach ($model_obj->get_tables() as $table) {
1491
+						if (strpos($table->get_table_name(), 'esp_')
1492
+							&&
1493
+							(
1494
+								is_main_site()//main site? nuke them all
1495
+								|| ! $table->is_global()//not main site,but not global either. nuke it
1496
+							)
1497
+						) {
1498
+							$tables[$table->get_table_name()] = $table->get_table_name();
1499
+						}
1500
+					}
1501
+				}
1502
+			}
1503
+		}
1504
+
1505
+		//there are some tables whose models were removed.
1506
+		//they should be removed when removing all EE core's data
1507
+		$tables_without_models = array(
1508
+			'esp_promotion',
1509
+			'esp_promotion_applied',
1510
+			'esp_promotion_object',
1511
+			'esp_promotion_rule',
1512
+			'esp_rule',
1513
+		);
1514
+		foreach ($tables_without_models as $table) {
1515
+			$tables[$table] = $table;
1516
+		}
1517
+		return \EEH_Activation::getTableManager()->dropTables($tables);
1518
+	}
1519
+
1520
+
1521
+
1522
+	/**
1523
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1524
+	 * each table name provided has a wpdb prefix attached, and that it exists.
1525
+	 * Returns the list actually deleted
1526
+	 *
1527
+	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1528
+	 * @global WPDB $wpdb
1529
+	 * @param array $table_names
1530
+	 * @return array of table names which we deleted
1531
+	 */
1532
+	public static function drop_tables($table_names)
1533
+	{
1534
+		return \EEH_Activation::getTableManager()->dropTables($table_names);
1535
+	}
1536
+
1537
+
1538
+
1539
+	/**
1540
+	 * plugin_uninstall
1541
+	 *
1542
+	 * @access public
1543
+	 * @static
1544
+	 * @param bool $remove_all
1545
+	 * @return void
1546
+	 */
1547
+	public static function delete_all_espresso_tables_and_data($remove_all = true)
1548
+	{
1549
+		global $wpdb;
1550
+		self::drop_espresso_tables();
1551
+		$wp_options_to_delete = array(
1552
+			'ee_no_ticket_prices'                => true,
1553
+			'ee_active_messengers'               => true,
1554
+			'ee_has_activated_messenger'         => true,
1555
+			'ee_flush_rewrite_rules'             => true,
1556
+			'ee_config'                          => false,
1557
+			'ee_data_migration_current_db_state' => true,
1558
+			'ee_data_migration_mapping_'         => false,
1559
+			'ee_data_migration_script_'          => false,
1560
+			'ee_data_migrations'                 => true,
1561
+			'ee_dms_map'                         => false,
1562
+			'ee_notices'                         => true,
1563
+			'lang_file_check_'                   => false,
1564
+			'ee_maintenance_mode'                => true,
1565
+			'ee_ueip_optin'                      => true,
1566
+			'ee_ueip_has_notified'               => true,
1567
+			'ee_plugin_activation_errors'        => true,
1568
+			'ee_id_mapping_from'                 => false,
1569
+			'espresso_persistent_admin_notices'  => true,
1570
+			'ee_encryption_key'                  => true,
1571
+			'pue_force_upgrade_'                 => false,
1572
+			'pue_json_error_'                    => false,
1573
+			'pue_install_key_'                   => false,
1574
+			'pue_verification_error_'            => false,
1575
+			'pu_dismissed_upgrade_'              => false,
1576
+			'external_updates-'                  => false,
1577
+			'ee_extra_data'                      => true,
1578
+			'ee_ssn_'                            => false,
1579
+			'ee_rss_'                            => false,
1580
+			'ee_rte_n_tx_'                       => false,
1581
+			'ee_pers_admin_notices'              => true,
1582
+			'ee_job_parameters_'                 => false,
1583
+			'ee_upload_directories_incomplete'   => true,
1584
+			'ee_verified_db_collations'          => true,
1585
+		);
1586
+		if (is_main_site()) {
1587
+			$wp_options_to_delete['ee_network_config'] = true;
1588
+		}
1589
+		$undeleted_options = array();
1590
+		foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1591
+			if ($no_wildcard) {
1592
+				if ( ! delete_option($option_name)) {
1593
+					$undeleted_options[] = $option_name;
1594
+				}
1595
+			} else {
1596
+				$option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1597
+				foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1598
+					if ( ! delete_option($option_name_from_wildcard)) {
1599
+						$undeleted_options[] = $option_name_from_wildcard;
1600
+					}
1601
+				}
1602
+			}
1603
+		}
1604
+		//also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1605
+		remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1606
+		if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1607
+			$db_update_sans_ee4 = array();
1608
+			foreach ($espresso_db_update as $version => $times_activated) {
1609
+				if ((string)$version[0] === '3') {//if its NON EE4
1610
+					$db_update_sans_ee4[$version] = $times_activated;
1611
+				}
1612
+			}
1613
+			update_option('espresso_db_update', $db_update_sans_ee4);
1614
+		}
1615
+		$errors = '';
1616
+		if ( ! empty($undeleted_options)) {
1617
+			$errors .= sprintf(
1618
+				__('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1619
+				'<br/>',
1620
+				implode(',<br/>', $undeleted_options)
1621
+			);
1622
+		}
1623
+		if ( ! empty($errors)) {
1624
+			EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1625
+		}
1626
+	}
1627
+
1628
+	/**
1629
+	 * Gets the mysql error code from the last used query by wpdb
1630
+	 *
1631
+	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1632
+	 */
1633
+	public static function last_wpdb_error_code()
1634
+	{
1635
+		global $wpdb;
1636
+		if ($wpdb->use_mysqli) {
1637
+			return mysqli_errno($wpdb->dbh);
1638
+		} else {
1639
+			return mysql_errno($wpdb->dbh);
1640
+		}
1641
+	}
1642
+
1643
+	/**
1644
+	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1645
+	 *
1646
+	 * @global wpdb  $wpdb
1647
+	 * @deprecated instead use TableAnalysis::tableExists()
1648
+	 * @param string $table_name with or without $wpdb->prefix
1649
+	 * @return boolean
1650
+	 */
1651
+	public static function table_exists($table_name)
1652
+	{
1653
+		return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1654
+	}
1655
+
1656
+	/**
1657
+	 * Resets the cache on EEH_Activation
1658
+	 */
1659
+	public static function reset()
1660
+	{
1661
+		self::$_default_creator_id                             = null;
1662
+		self::$_initialized_db_content_already_in_this_request = false;
1663
+	}
1664 1664
 }
1665 1665
 // End of file EEH_Activation.helper.php
1666 1666
 // Location: /helpers/EEH_Activation.core.php
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -57,7 +57,7 @@  discard block
 block discarded – undo
57 57
      */
58 58
     public static function getTableAnalysis()
59 59
     {
60
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
60
+        if ( ! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
61 61
             self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
62 62
         }
63 63
         return self::$table_analysis;
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
      */
70 70
     public static function getTableManager()
71 71
     {
72
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
72
+        if ( ! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
73 73
             self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
74 74
         }
75 75
         return self::$table_manager;
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
         if ($which_to_include === 'old') {
184 184
             $cron_tasks = array_filter(
185 185
                 $cron_tasks,
186
-                function ($value) {
186
+                function($value) {
187 187
                     return $value === EEH_Activation::cron_task_no_longer_in_use;
188 188
                 }
189 189
             );
@@ -213,7 +213,7 @@  discard block
 block discarded – undo
213 213
     {
214 214
 
215 215
         foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
216
-            if (! wp_next_scheduled($hook_name)) {
216
+            if ( ! wp_next_scheduled($hook_name)) {
217 217
                 /**
218 218
                  * This allows client code to define the initial start timestamp for this schedule.
219 219
                  */
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
             3
319 319
         );
320 320
         //EE_Config::reset();
321
-        if (! EE_Config::logging_enabled()) {
321
+        if ( ! EE_Config::logging_enabled()) {
322 322
             delete_option(EE_Config::LOG_NAME);
323 323
         }
324 324
     }
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
     public static function load_calendar_config()
334 334
     {
335 335
         // grab array of all plugin folders and loop thru it
336
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
336
+        $plugins = glob(WP_PLUGIN_DIR.DS.'*', GLOB_ONLYDIR);
337 337
         if (empty($plugins)) {
338 338
             return;
339 339
         }
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
                 || strpos($plugin, 'calendar') !== false
351 351
             ) {
352 352
                 // this is what we are looking for
353
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
353
+                $calendar_config = $plugin_path.DS.'EE_Calendar_Config.php';
354 354
                 // does it exist in this folder ?
355 355
                 if (is_readable($calendar_config)) {
356 356
                     // YEAH! let's load it
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
             ) {
479 479
                 //update Config with post ID
480 480
                 $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
481
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
481
+                if ( ! EE_Config::instance()->update_espresso_config(false, false)) {
482 482
                     $msg = __(
483 483
                         'The Event Espresso critical page configuration settings could not be updated.',
484 484
                         'event_espresso'
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
                         'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
502 502
                         'event_espresso'
503 503
                     ),
504
-                    '<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
504
+                    '<a href="'.admin_url('admin.php?page=espresso_general_settings&action=critical_pages').'">'
505 505
                     . __('Event Espresso Critical Pages Settings', 'event_espresso')
506 506
                     . '</a>'
507 507
                 )
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
     public static function get_page_by_ee_shortcode($ee_shortcode)
528 528
     {
529 529
         global $wpdb;
530
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
530
+        $shortcode_and_opening_bracket = '['.$ee_shortcode;
531 531
         $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
532 532
         if ($post_id) {
533 533
             return get_post($post_id);
@@ -553,11 +553,11 @@  discard block
 block discarded – undo
553 553
             'post_status'    => 'publish',
554 554
             'post_type'      => 'page',
555 555
             'comment_status' => 'closed',
556
-            'post_content'   => '[' . $critical_page['code'] . ']',
556
+            'post_content'   => '['.$critical_page['code'].']',
557 557
         );
558 558
 
559 559
         $post_id = wp_insert_post($post_args);
560
-        if (! $post_id) {
560
+        if ( ! $post_id) {
561 561
             $msg = sprintf(
562 562
                 __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
563 563
                 $critical_page['name']
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
             return $critical_page;
567 567
         }
568 568
         // get newly created post's details
569
-        if (! $critical_page['post'] = get_post($post_id)) {
569
+        if ( ! $critical_page['post'] = get_post($post_id)) {
570 570
             $msg = sprintf(
571 571
                 __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
572 572
                 $critical_page['name']
@@ -603,17 +603,17 @@  discard block
 block discarded – undo
603 603
             $role_to_check
604 604
         );
605 605
         if ($pre_filtered_id !== false) {
606
-            return (int)$pre_filtered_id;
606
+            return (int) $pre_filtered_id;
607 607
         }
608 608
         $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
609 609
         $query = $wpdb->prepare(
610 610
             "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
611
-            '%' . $role_to_check . '%'
611
+            '%'.$role_to_check.'%'
612 612
         );
613 613
         $user_id = $wpdb->get_var($query);
614 614
         $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
615
-        if ($user_id && (int)$user_id) {
616
-            self::$_default_creator_id = (int)$user_id;
615
+        if ($user_id && (int) $user_id) {
616
+            self::$_default_creator_id = (int) $user_id;
617 617
             return self::$_default_creator_id;
618 618
         } else {
619 619
             return null;
@@ -648,7 +648,7 @@  discard block
 block discarded – undo
648 648
         }
649 649
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
650 650
         if ( ! function_exists('dbDelta')) {
651
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
651
+            require_once(ABSPATH.'wp-admin/includes/upgrade.php');
652 652
         }
653 653
         $tableAnalysis = \EEH_Activation::getTableAnalysis();
654 654
         $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
@@ -859,13 +859,13 @@  discard block
 block discarded – undo
859 859
             // reset values array
860 860
             $QSG_values = array();
861 861
             // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
862
-            if (! in_array("$QSG_system", $question_groups)) {
862
+            if ( ! in_array("$QSG_system", $question_groups)) {
863 863
                 // add it
864 864
                 switch ($QSG_system) {
865 865
                     case 1:
866 866
                         $QSG_values = array(
867 867
                             'QSG_name'            => __('Personal Information', 'event_espresso'),
868
-                            'QSG_identifier'      => 'personal-information-' . time(),
868
+                            'QSG_identifier'      => 'personal-information-'.time(),
869 869
                             'QSG_desc'            => '',
870 870
                             'QSG_order'           => 1,
871 871
                             'QSG_show_group_name' => 1,
@@ -877,7 +877,7 @@  discard block
 block discarded – undo
877 877
                     case 2:
878 878
                         $QSG_values = array(
879 879
                             'QSG_name'            => __('Address Information', 'event_espresso'),
880
-                            'QSG_identifier'      => 'address-information-' . time(),
880
+                            'QSG_identifier'      => 'address-information-'.time(),
881 881
                             'QSG_desc'            => '',
882 882
                             'QSG_order'           => 2,
883 883
                             'QSG_show_group_name' => 1,
@@ -888,7 +888,7 @@  discard block
 block discarded – undo
888 888
                         break;
889 889
                 }
890 890
                 // make sure we have some values before inserting them
891
-                if (! empty($QSG_values)) {
891
+                if ( ! empty($QSG_values)) {
892 892
                     // insert system question
893 893
                     $wpdb->insert(
894 894
                         $table_name,
@@ -925,7 +925,7 @@  discard block
 block discarded – undo
925 925
             // reset values array
926 926
             $QST_values = array();
927 927
             // if we don't have what we should have
928
-            if (! in_array($QST_system, $questions)) {
928
+            if ( ! in_array($QST_system, $questions)) {
929 929
                 // add it
930 930
                 switch ($QST_system) {
931 931
                     case 'fname':
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
                         );
1078 1078
                         break;
1079 1079
                 }
1080
-                if (! empty($QST_values)) {
1080
+                if ( ! empty($QST_values)) {
1081 1081
                     // insert system question
1082 1082
                     $wpdb->insert(
1083 1083
                         $table_name,
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
      */
1139 1139
     public static function insert_default_payment_methods()
1140 1140
     {
1141
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1141
+        if ( ! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1142 1142
             EE_Registry::instance()->load_lib('Payment_Method_Manager');
1143 1143
             EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1144 1144
         } else {
@@ -1427,7 +1427,7 @@  discard block
 block discarded – undo
1427 1427
         // this creates an array for tracking events that have no active ticket prices created
1428 1428
         // this allows us to warn admins of the situation so that it can be corrected
1429 1429
         $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1430
-        if (! $espresso_no_ticket_prices) {
1430
+        if ( ! $espresso_no_ticket_prices) {
1431 1431
             add_option('ee_no_ticket_prices', array(), '', false);
1432 1432
         }
1433 1433
     }
@@ -1466,7 +1466,7 @@  discard block
 block discarded – undo
1466 1466
             }
1467 1467
         }
1468 1468
         //get all our CPTs
1469
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1469
+        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",", $ee_post_types).")";
1470 1470
         $cpt_ids = $wpdb->get_col($query);
1471 1471
         //delete each post meta and term relations too
1472 1472
         foreach ($cpt_ids as $post_id) {
@@ -1606,7 +1606,7 @@  discard block
 block discarded – undo
1606 1606
         if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1607 1607
             $db_update_sans_ee4 = array();
1608 1608
             foreach ($espresso_db_update as $version => $times_activated) {
1609
-                if ((string)$version[0] === '3') {//if its NON EE4
1609
+                if ((string) $version[0] === '3') {//if its NON EE4
1610 1610
                     $db_update_sans_ee4[$version] = $times_activated;
1611 1611
                 }
1612 1612
             }
Please login to merge, or discard this patch.
reg_steps/payment_options/EE_SPCO_Reg_Step_Payment_Options.class.php 1 patch
Indentation   +2870 added lines, -2870 removed lines patch added patch discarded remove patch
@@ -15,2874 +15,2874 @@
 block discarded – undo
15 15
 class EE_SPCO_Reg_Step_Payment_Options extends EE_SPCO_Reg_Step
16 16
 {
17 17
 
18
-    /**
19
-     * @access protected
20
-     * @var EE_Line_Item_Display $Line_Item_Display
21
-     */
22
-    protected $line_item_display;
23
-
24
-    /**
25
-     * @access protected
26
-     * @var boolean $handle_IPN_in_this_request
27
-     */
28
-    protected $handle_IPN_in_this_request = false;
29
-
30
-
31
-    /**
32
-     *    set_hooks - for hooking into EE Core, other modules, etc
33
-     *
34
-     * @access    public
35
-     * @return    void
36
-     */
37
-    public static function set_hooks()
38
-    {
39
-        add_filter(
40
-            'FHEE__SPCO__EE_Line_Item_Filter_Collection',
41
-            array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
42
-        );
43
-        add_action(
44
-            'wp_ajax_switch_spco_billing_form',
45
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
46
-        );
47
-        add_action(
48
-            'wp_ajax_nopriv_switch_spco_billing_form',
49
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
50
-        );
51
-        add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
52
-        add_action(
53
-            'wp_ajax_nopriv_save_payer_details',
54
-            array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
55
-        );
56
-        add_action(
57
-            'wp_ajax_get_transaction_details_for_gateways',
58
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
59
-        );
60
-        add_action(
61
-            'wp_ajax_nopriv_get_transaction_details_for_gateways',
62
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
63
-        );
64
-        add_filter(
65
-            'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
66
-            array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
67
-            10,
68
-            1
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     *    ajax switch_spco_billing_form
75
-     *
76
-     * @throws \EE_Error
77
-     */
78
-    public static function switch_spco_billing_form()
79
-    {
80
-        EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
81
-    }
82
-
83
-
84
-    /**
85
-     *    ajax save_payer_details
86
-     *
87
-     * @throws \EE_Error
88
-     */
89
-    public static function save_payer_details()
90
-    {
91
-        EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
-    }
93
-
94
-
95
-    /**
96
-     *    ajax get_transaction_details
97
-     *
98
-     * @throws \EE_Error
99
-     */
100
-    public static function get_transaction_details()
101
-    {
102
-        EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
103
-    }
104
-
105
-
106
-    /**
107
-     * bypass_recaptcha_for_load_payment_method
108
-     *
109
-     * @access public
110
-     * @return array
111
-     * @throws InvalidArgumentException
112
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
113
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
114
-     */
115
-    public static function bypass_recaptcha_for_load_payment_method()
116
-    {
117
-        return array(
118
-            'EESID'  => EE_Registry::instance()->SSN->id(),
119
-            'step'   => 'payment_options',
120
-            'action' => 'spco_billing_form',
121
-        );
122
-    }
123
-
124
-
125
-    /**
126
-     *    class constructor
127
-     *
128
-     * @access    public
129
-     * @param    EE_Checkout $checkout
130
-     */
131
-    public function __construct(EE_Checkout $checkout)
132
-    {
133
-        $this->_slug     = 'payment_options';
134
-        $this->_name     = esc_html__('Payment Options', 'event_espresso');
135
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'payment_options_main.template.php';
136
-        $this->checkout  = $checkout;
137
-        $this->_reset_success_message();
138
-        $this->set_instructions(
139
-            esc_html__(
140
-                'Please select a method of payment and provide any necessary billing information before proceeding.',
141
-                'event_espresso'
142
-            )
143
-        );
144
-    }
145
-
146
-
147
-    /**
148
-     * @return null
149
-     */
150
-    public function line_item_display()
151
-    {
152
-        return $this->line_item_display;
153
-    }
154
-
155
-
156
-    /**
157
-     * @param null $line_item_display
158
-     */
159
-    public function set_line_item_display($line_item_display)
160
-    {
161
-        $this->line_item_display = $line_item_display;
162
-    }
163
-
164
-
165
-    /**
166
-     * @return boolean
167
-     */
168
-    public function handle_IPN_in_this_request()
169
-    {
170
-        return $this->handle_IPN_in_this_request;
171
-    }
172
-
173
-
174
-    /**
175
-     * @param boolean $handle_IPN_in_this_request
176
-     */
177
-    public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
-    {
179
-        $this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
-    }
181
-
182
-
183
-    /**
184
-     * translate_js_strings
185
-     *
186
-     * @return void
187
-     */
188
-    public function translate_js_strings()
189
-    {
190
-        EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
-            'Please select a method of payment in order to continue.',
192
-            'event_espresso'
193
-        );
194
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
-            'A valid method of payment could not be determined. Please refresh the page and try again.',
196
-            'event_espresso'
197
-        );
198
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
-            'Forwarding to Secure Payment Provider.',
200
-            'event_espresso'
201
-        );
202
-    }
203
-
204
-
205
-    /**
206
-     * enqueue_styles_and_scripts
207
-     *
208
-     * @return void
209
-     * @throws EE_Error
210
-     * @throws InvalidArgumentException
211
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
212
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
213
-     */
214
-    public function enqueue_styles_and_scripts()
215
-    {
216
-        $transaction = $this->checkout->transaction;
217
-        //if the transaction isn't set or nothing is owed on it, don't enqueue any JS
218
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
219
-            return;
220
-        }
221
-        foreach (EEM_Payment_Method::instance()->get_all_for_transaction($transaction, EEM_Payment_Method::scope_cart) as $payment_method) {
222
-            $type_obj = $payment_method->type_obj();
223
-            if ($type_obj instanceof EE_PMT_Base) {
224
-                $billing_form = $type_obj->generate_new_billing_form($transaction);
225
-                if ($billing_form instanceof EE_Form_Section_Proper) {
226
-                    $billing_form->enqueue_js();
227
-                }
228
-            }
229
-        }
230
-    }
231
-
232
-
233
-    /**
234
-     * initialize_reg_step
235
-     *
236
-     * @return bool
237
-     * @throws EE_Error
238
-     * @throws InvalidArgumentException
239
-     * @throws ReflectionException
240
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
241
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
242
-     */
243
-    public function initialize_reg_step()
244
-    {
245
-        // TODO: if /when we implement donations, then this will need overriding
246
-        if (// don't need payment options for:
247
-            // 	registrations made via the admin
248
-            // 	completed transactions
249
-            // 	overpaid transactions
250
-            // 	$ 0.00 transactions (no payment required)
251
-            ! $this->checkout->payment_required()
252
-            // but do NOT remove if current action being called belongs to this reg step
253
-            && ! is_callable(array($this, $this->checkout->action))
254
-            && ! $this->completed()
255
-        ) {
256
-            // and if so, then we no longer need the Payment Options step
257
-            if ($this->is_current_step()) {
258
-                $this->checkout->generate_reg_form = false;
259
-            }
260
-            $this->checkout->remove_reg_step($this->_slug);
261
-            // DEBUG LOG
262
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
263
-            return false;
264
-        }
265
-        // load EEM_Payment_Method
266
-        EE_Registry::instance()->load_model('Payment_Method');
267
-        // get all active payment methods
268
-        $this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
269
-            $this->checkout->transaction,
270
-            EEM_Payment_Method::scope_cart
271
-        );
272
-        return true;
273
-    }
274
-
275
-
276
-    /**
277
-     * @return EE_Form_Section_Proper
278
-     * @throws EE_Error
279
-     * @throws InvalidArgumentException
280
-     * @throws ReflectionException
281
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
282
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
283
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
284
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
285
-     */
286
-    public function generate_reg_form()
287
-    {
288
-        // reset in case someone changes their mind
289
-        $this->_reset_selected_method_of_payment();
290
-        // set some defaults
291
-        $this->checkout->selected_method_of_payment = 'payments_closed';
292
-        $registrations_requiring_payment            = array();
293
-        $registrations_for_free_events              = array();
294
-        $registrations_requiring_pre_approval       = array();
295
-        $sold_out_events                            = array();
296
-        $insufficient_spaces_available              = array();
297
-        $no_payment_required                        = true;
298
-        // loop thru registrations to gather info
299
-        $registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
300
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
301
-            $registrations,
302
-            $this->checkout->revisit
303
-        );
304
-        foreach ($registrations as $REG_ID => $registration) {
305
-            /** @var $registration EE_Registration */
306
-            // has this registration lost it's space ?
307
-            if (isset($ejected_registrations[ $REG_ID ])) {
308
-                if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
309
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
310
-                } else {
311
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
312
-                }
313
-                continue;
314
-            }
315
-            // event requires admin approval
316
-            if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
317
-                // add event to list of events with pre-approval reg status
318
-                $registrations_requiring_pre_approval[$REG_ID] = $registration;
319
-                do_action(
320
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
321
-                    $registration->event(),
322
-                    $this
323
-                );
324
-                continue;
325
-            }
326
-            if ($this->checkout->revisit
327
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
328
-                && (
329
-                    $registration->event()->is_sold_out()
330
-                    || $registration->event()->is_sold_out(true)
331
-                )
332
-            ) {
333
-                // add event to list of events that are sold out
334
-                $sold_out_events[$registration->event()->ID()] = $registration->event();
335
-                do_action(
336
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
337
-                    $registration->event(),
338
-                    $this
339
-                );
340
-                continue;
341
-            }
342
-            // are they allowed to pay now and is there monies owing?
343
-            if ($registration->owes_monies_and_can_pay()) {
344
-                $registrations_requiring_payment[$REG_ID] = $registration;
345
-                do_action(
346
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
347
-                    $registration->event(),
348
-                    $this
349
-                );
350
-            } elseif (! $this->checkout->revisit
351
-                && $registration->status_ID() !== EEM_Registration::status_id_not_approved
352
-                && $registration->ticket()->is_free()
353
-            ) {
354
-                $registrations_for_free_events[$registration->event()->ID()] = $registration;
355
-            }
356
-        }
357
-        $subsections = array();
358
-        // now decide which template to load
359
-        if (! empty($sold_out_events)) {
360
-            $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
361
-        }
362
-        if (! empty($insufficient_spaces_available)) {
363
-            $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
364
-                $insufficient_spaces_available
365
-            );
366
-        }
367
-        if (! empty($registrations_requiring_pre_approval)) {
368
-            $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
369
-                $registrations_requiring_pre_approval
370
-            );
371
-        }
372
-        if (! empty($registrations_for_free_events)) {
373
-            $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
374
-        }
375
-        if (! empty($registrations_requiring_payment)) {
376
-            if ($this->checkout->amount_owing > 0) {
377
-                // autoload Line_Item_Display classes
378
-                EEH_Autoloader::register_line_item_filter_autoloaders();
379
-                $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
380
-                    apply_filters(
381
-                        'FHEE__SPCO__EE_Line_Item_Filter_Collection',
382
-                        new EE_Line_Item_Filter_Collection()
383
-                    ),
384
-                    $this->checkout->cart->get_grand_total()
385
-                );
386
-                /** @var EE_Line_Item $filtered_line_item_tree */
387
-                $filtered_line_item_tree = $line_item_filter_processor->process();
388
-                EEH_Autoloader::register_line_item_display_autoloaders();
389
-                $this->set_line_item_display(new EE_Line_Item_Display('spco'));
390
-                $subsections['payment_options'] = $this->_display_payment_options(
391
-                    $this->line_item_display->display_line_item(
392
-                        $filtered_line_item_tree,
393
-                        array('registrations' => $registrations)
394
-                    )
395
-                );
396
-                $this->checkout->amount_owing   = $filtered_line_item_tree->total();
397
-                $this->_apply_registration_payments_to_amount_owing($registrations);
398
-            }
399
-            $no_payment_required = false;
400
-        } else {
401
-            $this->_hide_reg_step_submit_button_if_revisit();
402
-        }
403
-        $this->_save_selected_method_of_payment();
404
-
405
-        $subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
406
-        $subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
407
-
408
-        return new EE_Form_Section_Proper(
409
-            array(
410
-                'name'            => $this->reg_form_name(),
411
-                'html_id'         => $this->reg_form_name(),
412
-                'subsections'     => $subsections,
413
-                'layout_strategy' => new EE_No_Layout(),
414
-            )
415
-        );
416
-    }
417
-
418
-
419
-    /**
420
-     * add line item filters required for this reg step
421
-     * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
422
-     *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
423
-     *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
424
-     *        payment options reg step, can apply these filters via the following: apply_filters(
425
-     *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
426
-     *        filter collection by passing that instead of instantiating a new collection
427
-     *
428
-     * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
429
-     * @return EE_Line_Item_Filter_Collection
430
-     * @throws EE_Error
431
-     * @throws InvalidArgumentException
432
-     * @throws ReflectionException
433
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
434
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
435
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
436
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
437
-     */
438
-    public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
439
-    {
440
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
441
-            return $line_item_filter_collection;
442
-        }
443
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
444
-            return $line_item_filter_collection;
445
-        }
446
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
447
-            return $line_item_filter_collection;
448
-        }
449
-        $line_item_filter_collection->add(
450
-            new EE_Billable_Line_Item_Filter(
451
-                EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
452
-                    EE_Registry::instance()->SSN->checkout()->transaction->registrations(
453
-                        EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
454
-                    )
455
-                )
456
-            )
457
-        );
458
-        $line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
459
-        return $line_item_filter_collection;
460
-    }
461
-
462
-
463
-    /**
464
-     * remove_ejected_registrations
465
-     * if a registrant has lost their potential space at an event due to lack of payment,
466
-     * then this method removes them from the list of registrations being paid for during this request
467
-     *
468
-     * @param \EE_Registration[] $registrations
469
-     * @return EE_Registration[]
470
-     * @throws EE_Error
471
-     * @throws InvalidArgumentException
472
-     * @throws ReflectionException
473
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
474
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
475
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
476
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
477
-     */
478
-    public static function remove_ejected_registrations(array $registrations)
479
-    {
480
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
481
-            $registrations,
482
-            EE_Registry::instance()->SSN->checkout()->revisit
483
-        );
484
-        foreach ($registrations as $REG_ID => $registration) {
485
-            // has this registration lost it's space ?
486
-            if (isset($ejected_registrations[$REG_ID])) {
487
-                unset($registrations[$REG_ID]);
488
-                continue;
489
-            }
490
-        }
491
-        return $registrations;
492
-    }
493
-
494
-
495
-    /**
496
-     * find_registrations_that_lost_their_space
497
-     * If a registrant chooses an offline payment method like Invoice,
498
-     * then no space is reserved for them at the event until they fully pay fo that site
499
-     * (unless the event's default reg status is set to APPROVED)
500
-     * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
501
-     * then this method will determine which registrations have lost the ability to complete the reg process.
502
-     *
503
-     * @param \EE_Registration[] $registrations
504
-     * @param bool               $revisit
505
-     * @return array
506
-     * @throws EE_Error
507
-     * @throws InvalidArgumentException
508
-     * @throws ReflectionException
509
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
510
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
511
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
512
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
513
-     */
514
-    public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
515
-    {
516
-        // registrations per event
517
-        $event_reg_count = array();
518
-        // spaces left per event
519
-        $event_spaces_remaining = array();
520
-        // tickets left sorted by ID
521
-        $tickets_remaining = array();
522
-        // registrations that have lost their space
523
-        $ejected_registrations = array();
524
-        foreach ($registrations as $REG_ID => $registration) {
525
-            if ($registration->status_ID() === EEM_Registration::status_id_approved
526
-                || apply_filters(
527
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
528
-                    false,
529
-                    $registration,
530
-                    $revisit
531
-                )
532
-            ) {
533
-                continue;
534
-            }
535
-            $EVT_ID = $registration->event_ID();
536
-            $ticket = $registration->ticket();
537
-            if (! isset($tickets_remaining[$ticket->ID()])) {
538
-                $tickets_remaining[$ticket->ID()] = $ticket->remaining();
539
-            }
540
-            if ($tickets_remaining[$ticket->ID()] > 0) {
541
-                if (! isset($event_reg_count[$EVT_ID])) {
542
-                    $event_reg_count[$EVT_ID] = 0;
543
-                }
544
-                $event_reg_count[$EVT_ID]++;
545
-                if (! isset($event_spaces_remaining[$EVT_ID])) {
546
-                    $event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
547
-                }
548
-            }
549
-            if ($revisit
550
-                && ($tickets_remaining[$ticket->ID()] === 0
551
-                    || $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
552
-                )
553
-            ) {
554
-                $ejected_registrations[$REG_ID] = $registration->event();
555
-                if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
556
-                    /** @type EE_Registration_Processor $registration_processor */
557
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
558
-                    // at this point, we should have enough details about the registrant to consider the registration
559
-                    // NOT incomplete
560
-                    $registration_processor->manually_update_registration_status(
561
-                        $registration,
562
-                        EEM_Registration::status_id_wait_list
563
-                    );
564
-                }
565
-            }
566
-        }
567
-        return $ejected_registrations;
568
-    }
569
-
570
-
571
-    /**
572
-     * _hide_reg_step_submit_button
573
-     * removes the html for the reg step submit button
574
-     * by replacing it with an empty string via filter callback
575
-     *
576
-     * @return void
577
-     */
578
-    protected function _adjust_registration_status_if_event_old_sold()
579
-    {
580
-    }
581
-
582
-
583
-    /**
584
-     * _hide_reg_step_submit_button
585
-     * removes the html for the reg step submit button
586
-     * by replacing it with an empty string via filter callback
587
-     *
588
-     * @return void
589
-     */
590
-    protected function _hide_reg_step_submit_button_if_revisit()
591
-    {
592
-        if ($this->checkout->revisit) {
593
-            add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
594
-        }
595
-    }
596
-
597
-
598
-    /**
599
-     * sold_out_events
600
-     * displays notices regarding events that have sold out since hte registrant first signed up
601
-     *
602
-     * @param \EE_Event[] $sold_out_events_array
603
-     * @return \EE_Form_Section_Proper
604
-     * @throws \EE_Error
605
-     */
606
-    private function _sold_out_events($sold_out_events_array = array())
607
-    {
608
-        // set some defaults
609
-        $this->checkout->selected_method_of_payment = 'events_sold_out';
610
-        $sold_out_events                            = '';
611
-        foreach ($sold_out_events_array as $sold_out_event) {
612
-            $sold_out_events .= EEH_HTML::li(
613
-                EEH_HTML::span(
614
-                    '  ' . $sold_out_event->name(),
615
-                    '',
616
-                    'dashicons dashicons-marker ee-icon-size-16 pink-text'
617
-                )
618
-            );
619
-        }
620
-        return new EE_Form_Section_Proper(
621
-            array(
622
-                'layout_strategy' => new EE_Template_Layout(
623
-                    array(
624
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
625
-                                                  . $this->_slug
626
-                                                  . DS
627
-                                                  . 'sold_out_events.template.php',
628
-                        'template_args'        => apply_filters(
629
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
630
-                            array(
631
-                                'sold_out_events'     => $sold_out_events,
632
-                                'sold_out_events_msg' => apply_filters(
633
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
634
-                                    sprintf(
635
-                                        esc_html__(
636
-                                            'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
637
-                                            'event_espresso'
638
-                                        ),
639
-                                        '<strong>',
640
-                                        '</strong>',
641
-                                        '<br />'
642
-                                    )
643
-                                ),
644
-                            )
645
-                        ),
646
-                    )
647
-                ),
648
-            )
649
-        );
650
-    }
651
-
652
-
653
-    /**
654
-     * _insufficient_spaces_available
655
-     * displays notices regarding events that do not have enough remaining spaces
656
-     * to satisfy the current number of registrations looking to pay
657
-     *
658
-     * @param \EE_Event[] $insufficient_spaces_events_array
659
-     * @return \EE_Form_Section_Proper
660
-     * @throws \EE_Error
661
-     */
662
-    private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
663
-    {
664
-        // set some defaults
665
-        $this->checkout->selected_method_of_payment = 'invoice';
666
-        $insufficient_space_events                  = '';
667
-        foreach ($insufficient_spaces_events_array as $event) {
668
-            if ($event instanceof EE_Event) {
669
-                $insufficient_space_events .= EEH_HTML::li(
670
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
671
-                );
672
-            }
673
-        }
674
-        return new EE_Form_Section_Proper(
675
-            array(
676
-                'subsections'     => array(
677
-                    'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
678
-                    'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
679
-                ),
680
-                'layout_strategy' => new EE_Template_Layout(
681
-                    array(
682
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
683
-                                                  . $this->_slug
684
-                                                  . DS
685
-                                                  . 'sold_out_events.template.php',
686
-                        'template_args'        => apply_filters(
687
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
688
-                            array(
689
-                                'sold_out_events'     => $insufficient_space_events,
690
-                                'sold_out_events_msg' => apply_filters(
691
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
692
-                                    esc_html__(
693
-                                        'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
694
-                                        'event_espresso'
695
-                                    )
696
-                                ),
697
-                            )
698
-                        ),
699
-                    )
700
-                ),
701
-            )
702
-        );
703
-    }
704
-
705
-
706
-    /**
707
-     * registrations_requiring_pre_approval
708
-     *
709
-     * @param array $registrations_requiring_pre_approval
710
-     * @return EE_Form_Section_Proper
711
-     * @throws EE_Error
712
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
713
-     */
714
-    private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
715
-    {
716
-        $events_requiring_pre_approval = '';
717
-        foreach ($registrations_requiring_pre_approval as $registration) {
718
-            if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
719
-                $events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
720
-                    EEH_HTML::span(
721
-                        '',
722
-                        '',
723
-                        'dashicons dashicons-marker ee-icon-size-16 orange-text'
724
-                    )
725
-                    . EEH_HTML::span($registration->event()->name(), '', 'orange-text')
726
-                );
727
-            }
728
-        }
729
-        return new EE_Form_Section_Proper(
730
-            array(
731
-                'layout_strategy' => new EE_Template_Layout(
732
-                    array(
733
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
734
-                                                  . $this->_slug
735
-                                                  . DS
736
-                                                  . 'events_requiring_pre_approval.template.php', // layout_template
737
-                        'template_args'        => apply_filters(
738
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
739
-                            array(
740
-                                'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
741
-                                'events_requiring_pre_approval_msg' => apply_filters(
742
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
743
-                                    esc_html__(
744
-                                        'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
745
-                                        'event_espresso'
746
-                                    )
747
-                                ),
748
-                            )
749
-                        ),
750
-                    )
751
-                ),
752
-            )
753
-        );
754
-    }
755
-
756
-
757
-    /**
758
-     * _no_payment_required
759
-     *
760
-     * @param \EE_Event[] $registrations_for_free_events
761
-     * @return \EE_Form_Section_Proper
762
-     * @throws \EE_Error
763
-     */
764
-    private function _no_payment_required($registrations_for_free_events = array())
765
-    {
766
-        // set some defaults
767
-        $this->checkout->selected_method_of_payment = 'no_payment_required';
768
-        // generate no_payment_required form
769
-        return new EE_Form_Section_Proper(
770
-            array(
771
-                'layout_strategy' => new EE_Template_Layout(
772
-                    array(
773
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
774
-                                                  . $this->_slug
775
-                                                  . DS
776
-                                                  . 'no_payment_required.template.php', // layout_template
777
-                        'template_args'        => apply_filters(
778
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
779
-                            array(
780
-                                'revisit'                       => $this->checkout->revisit,
781
-                                'registrations'                 => array(),
782
-                                'ticket_count'                  => array(),
783
-                                'registrations_for_free_events' => $registrations_for_free_events,
784
-                                'no_payment_required_msg'       => EEH_HTML::p(
785
-                                    esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
786
-                                ),
787
-                            )
788
-                        ),
789
-                    )
790
-                ),
791
-            )
792
-        );
793
-    }
794
-
795
-
796
-    /**
797
-     * _display_payment_options
798
-     *
799
-     * @param string $transaction_details
800
-     * @return EE_Form_Section_Proper
801
-     * @throws EE_Error
802
-     * @throws InvalidArgumentException
803
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
804
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
805
-     */
806
-    private function _display_payment_options($transaction_details = '')
807
-    {
808
-        // has method_of_payment been set by no-js user?
809
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
810
-        // build payment options form
811
-        return apply_filters(
812
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
813
-            new EE_Form_Section_Proper(
814
-                array(
815
-                    'subsections'     => array(
816
-                        'before_payment_options' => apply_filters(
817
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
818
-                            new EE_Form_Section_Proper(
819
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
820
-                            )
821
-                        ),
822
-                        'payment_options'        => $this->_setup_payment_options(),
823
-                        'after_payment_options'  => apply_filters(
824
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
825
-                            new EE_Form_Section_Proper(
826
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
827
-                            )
828
-                        ),
829
-                    ),
830
-                    'layout_strategy' => new EE_Template_Layout(
831
-                        array(
832
-                            'layout_template_file' => $this->_template,
833
-                            'template_args'        => apply_filters(
834
-                                'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
835
-                                array(
836
-                                    'reg_count'                 => $this->line_item_display->total_items(),
837
-                                    'transaction_details'       => $transaction_details,
838
-                                    'available_payment_methods' => array(),
839
-                                )
840
-                            ),
841
-                        )
842
-                    ),
843
-                )
844
-            )
845
-        );
846
-    }
847
-
848
-
849
-    /**
850
-     * _extra_hidden_inputs
851
-     *
852
-     * @param bool $no_payment_required
853
-     * @return \EE_Form_Section_Proper
854
-     * @throws \EE_Error
855
-     */
856
-    private function _extra_hidden_inputs($no_payment_required = true)
857
-    {
858
-        return new EE_Form_Section_Proper(
859
-            array(
860
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
861
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
862
-                'subsections'     => array(
863
-                    'spco_no_payment_required' => new EE_Hidden_Input(
864
-                        array(
865
-                            'normalization_strategy' => new EE_Boolean_Normalization(),
866
-                            'html_name'              => 'spco_no_payment_required',
867
-                            'html_id'                => 'spco-no-payment-required-payment_options',
868
-                            'default'                => $no_payment_required,
869
-                        )
870
-                    ),
871
-                    'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
872
-                        array(
873
-                            'normalization_strategy' => new EE_Int_Normalization(),
874
-                            'html_name'              => 'spco_transaction_id',
875
-                            'html_id'                => 'spco-transaction-id',
876
-                            'default'                => $this->checkout->transaction->ID(),
877
-                        )
878
-                    ),
879
-                ),
880
-            )
881
-        );
882
-    }
883
-
884
-
885
-    /**
886
-     *    _apply_registration_payments_to_amount_owing
887
-     *
888
-     * @access protected
889
-     * @param array $registrations
890
-     * @throws EE_Error
891
-     */
892
-    protected function _apply_registration_payments_to_amount_owing(array $registrations)
893
-    {
894
-        $payments = array();
895
-        foreach ($registrations as $registration) {
896
-            if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
897
-                $payments += $registration->registration_payments();
898
-            }
899
-        }
900
-        if (! empty($payments)) {
901
-            foreach ($payments as $payment) {
902
-                if ($payment instanceof EE_Registration_Payment) {
903
-                    $this->checkout->amount_owing -= $payment->amount();
904
-                }
905
-            }
906
-        }
907
-    }
908
-
909
-
910
-    /**
911
-     *    _reset_selected_method_of_payment
912
-     *
913
-     * @access    private
914
-     * @param    bool $force_reset
915
-     * @return void
916
-     * @throws InvalidArgumentException
917
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
918
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
919
-     */
920
-    private function _reset_selected_method_of_payment($force_reset = false)
921
-    {
922
-        $reset_payment_method = $force_reset
923
-            ? true
924
-            : sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
925
-        if ($reset_payment_method) {
926
-            $this->checkout->selected_method_of_payment = null;
927
-            $this->checkout->payment_method             = null;
928
-            $this->checkout->billing_form               = null;
929
-            $this->_save_selected_method_of_payment();
930
-        }
931
-    }
932
-
933
-
934
-    /**
935
-     * _save_selected_method_of_payment
936
-     * stores the selected_method_of_payment in the session
937
-     * so that it's available for all subsequent requests including AJAX
938
-     *
939
-     * @access        private
940
-     * @param string $selected_method_of_payment
941
-     * @return void
942
-     * @throws InvalidArgumentException
943
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
944
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
945
-     */
946
-    private function _save_selected_method_of_payment($selected_method_of_payment = '')
947
-    {
948
-        $selected_method_of_payment = ! empty($selected_method_of_payment)
949
-            ? $selected_method_of_payment
950
-            : $this->checkout->selected_method_of_payment;
951
-        EE_Registry::instance()->SSN->set_session_data(
952
-            array('selected_method_of_payment' => $selected_method_of_payment)
953
-        );
954
-    }
955
-
956
-
957
-    /**
958
-     * _setup_payment_options
959
-     *
960
-     * @return EE_Form_Section_Proper
961
-     * @throws EE_Error
962
-     * @throws InvalidArgumentException
963
-     * @throws ReflectionException
964
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
965
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
966
-     */
967
-    public function _setup_payment_options()
968
-    {
969
-        // load payment method classes
970
-        $this->checkout->available_payment_methods = $this->_get_available_payment_methods();
971
-        if (empty($this->checkout->available_payment_methods)) {
972
-            EE_Error::add_error(
973
-                apply_filters(
974
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
975
-                    sprintf(
976
-                        esc_html__(
977
-                            'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
978
-                            'event_espresso'
979
-                        ),
980
-                        '<br>',
981
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
982
-                    )
983
-                ),
984
-                __FILE__,
985
-                __FUNCTION__,
986
-                __LINE__
987
-            );
988
-        }
989
-        // switch up header depending on number of available payment methods
990
-        $payment_method_header     = count($this->checkout->available_payment_methods) > 1
991
-            ? apply_filters(
992
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
993
-                esc_html__('Please Select Your Method of Payment', 'event_espresso')
994
-            )
995
-            : apply_filters(
996
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
997
-                esc_html__('Method of Payment', 'event_espresso')
998
-            );
999
-        $available_payment_methods = array(
1000
-            // display the "Payment Method" header
1001
-            'payment_method_header' => new EE_Form_Section_HTML(
1002
-                EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr')
1003
-            ),
1004
-        );
1005
-        // the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1006
-        $available_payment_method_options = array();
1007
-        $default_payment_method_option    = array();
1008
-        // additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1009
-        $payment_methods_billing_info = array(
1010
-            new EE_Form_Section_HTML(
1011
-                EEH_HTML::div('<br />', '', '', 'clear:both;')
1012
-            ),
1013
-        );
1014
-        // loop through payment methods
1015
-        foreach ($this->checkout->available_payment_methods as $payment_method) {
1016
-            if ($payment_method instanceof EE_Payment_Method) {
1017
-                $payment_method_button = EEH_HTML::img(
1018
-                    $payment_method->button_url(),
1019
-                    $payment_method->name(),
1020
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1021
-                    'spco-payment-method-btn-img'
1022
-                );
1023
-                // check if any payment methods are set as default
1024
-                // if payment method is already selected OR nothing is selected and this payment method should be
1025
-                // open_by_default
1026
-                if (($this->checkout->selected_method_of_payment === $payment_method->slug())
1027
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1028
-                ) {
1029
-                    $this->checkout->selected_method_of_payment = $payment_method->slug();
1030
-                    $this->_save_selected_method_of_payment();
1031
-                    $default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1032
-                } else {
1033
-                    $available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1034
-                }
1035
-                $payment_methods_billing_info[$payment_method->slug() . '-info'] = $this->_payment_method_billing_info(
1036
-                    $payment_method
1037
-                );
1038
-            }
1039
-        }
1040
-        // prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1041
-        // of PMs
1042
-        $available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1043
-        // now generate the actual form  inputs
1044
-        $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1045
-            $available_payment_method_options
1046
-        );
1047
-        $available_payment_methods                              += $payment_methods_billing_info;
1048
-        // build the available payment methods form
1049
-        return new EE_Form_Section_Proper(
1050
-            array(
1051
-                'html_id'         => 'spco-available-methods-of-payment-dv',
1052
-                'subsections'     => $available_payment_methods,
1053
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1054
-            )
1055
-        );
1056
-    }
1057
-
1058
-
1059
-    /**
1060
-     * _get_available_payment_methods
1061
-     *
1062
-     * @return EE_Payment_Method[]
1063
-     * @throws EE_Error
1064
-     * @throws InvalidArgumentException
1065
-     * @throws ReflectionException
1066
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1067
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1068
-     */
1069
-    protected function _get_available_payment_methods()
1070
-    {
1071
-        if (! empty($this->checkout->available_payment_methods)) {
1072
-            return $this->checkout->available_payment_methods;
1073
-        }
1074
-        $available_payment_methods = array();
1075
-        // load EEM_Payment_Method
1076
-        EE_Registry::instance()->load_model('Payment_Method');
1077
-        /** @type EEM_Payment_Method $EEM_Payment_Method */
1078
-        $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1079
-        // get all active payment methods
1080
-        $payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1081
-            $this->checkout->transaction,
1082
-            EEM_Payment_Method::scope_cart
1083
-        );
1084
-        foreach ($payment_methods as $payment_method) {
1085
-            if ($payment_method instanceof EE_Payment_Method) {
1086
-                $available_payment_methods[$payment_method->slug()] = $payment_method;
1087
-            }
1088
-        }
1089
-        return $available_payment_methods;
1090
-    }
1091
-
1092
-
1093
-    /**
1094
-     *    _available_payment_method_inputs
1095
-     *
1096
-     * @access    private
1097
-     * @param    array $available_payment_method_options
1098
-     * @return    \EE_Form_Section_Proper
1099
-     */
1100
-    private function _available_payment_method_inputs($available_payment_method_options = array())
1101
-    {
1102
-        // generate inputs
1103
-        return new EE_Form_Section_Proper(
1104
-            array(
1105
-                'html_id'         => 'ee-available-payment-method-inputs',
1106
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1107
-                'subsections'     => array(
1108
-                    '' => new EE_Radio_Button_Input(
1109
-                        $available_payment_method_options,
1110
-                        array(
1111
-                            'html_name'          => 'selected_method_of_payment',
1112
-                            'html_class'         => 'spco-payment-method',
1113
-                            'default'            => $this->checkout->selected_method_of_payment,
1114
-                            'label_size'         => 11,
1115
-                            'enforce_label_size' => true,
1116
-                        )
1117
-                    ),
1118
-                ),
1119
-            )
1120
-        );
1121
-    }
1122
-
1123
-
1124
-    /**
1125
-     *    _payment_method_billing_info
1126
-     *
1127
-     * @access    private
1128
-     * @param    EE_Payment_Method $payment_method
1129
-     * @return EE_Form_Section_Proper
1130
-     * @throws EE_Error
1131
-     * @throws InvalidArgumentException
1132
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1133
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1134
-     */
1135
-    private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1136
-    {
1137
-        $currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1138
-            ? true
1139
-            : false;
1140
-        // generate the billing form for payment method
1141
-        $billing_form                 = $currently_selected
1142
-            ? $this->_get_billing_form_for_payment_method($payment_method)
1143
-            : new EE_Form_Section_HTML();
1144
-        $this->checkout->billing_form = $currently_selected
1145
-            ? $billing_form
1146
-            : $this->checkout->billing_form;
1147
-        // it's all in the details
1148
-        $info_html = EEH_HTML::h3(
1149
-            esc_html__('Important information regarding your payment', 'event_espresso'),
1150
-            '',
1151
-            'spco-payment-method-hdr'
1152
-        );
1153
-        // add some info regarding the step, either from what's saved in the admin,
1154
-        // or a default string depending on whether the PM has a billing form or not
1155
-        if ($payment_method->description()) {
1156
-            $payment_method_info = $payment_method->description();
1157
-        } elseif ($billing_form instanceof EE_Billing_Info_Form) {
1158
-            $payment_method_info = sprintf(
1159
-                esc_html__(
1160
-                    'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1161
-                    'event_espresso'
1162
-                ),
1163
-                $this->submit_button_text()
1164
-            );
1165
-        } else {
1166
-            $payment_method_info = sprintf(
1167
-                esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1168
-                $this->submit_button_text()
1169
-            );
1170
-        }
1171
-        $info_html .= EEH_HTML::p(
1172
-            apply_filters(
1173
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1174
-                $payment_method_info
1175
-            ),
1176
-            '',
1177
-            'spco-payment-method-desc ee-attention'
1178
-        );
1179
-        return new EE_Form_Section_Proper(
1180
-            array(
1181
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1182
-                'html_class'      => 'spco-payment-method-info-dv',
1183
-                // only display the selected or default PM
1184
-                'html_style'      => $currently_selected ? '' : 'display:none;',
1185
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1186
-                'subsections'     => array(
1187
-                    'info'         => new EE_Form_Section_HTML($info_html),
1188
-                    'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1189
-                ),
1190
-            )
1191
-        );
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * get_billing_form_html_for_payment_method
1197
-     *
1198
-     * @access public
1199
-     * @return string
1200
-     * @throws EE_Error
1201
-     * @throws InvalidArgumentException
1202
-     * @throws ReflectionException
1203
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1204
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1205
-     */
1206
-    public function get_billing_form_html_for_payment_method()
1207
-    {
1208
-        // how have they chosen to pay?
1209
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1210
-        $this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1211
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1212
-            return false;
1213
-        }
1214
-        if (apply_filters(
1215
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1216
-            false
1217
-        )) {
1218
-            EE_Error::add_success(
1219
-                apply_filters(
1220
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1221
-                    sprintf(
1222
-                        esc_html__(
1223
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1224
-                            'event_espresso'
1225
-                        ),
1226
-                        $this->checkout->payment_method->name()
1227
-                    )
1228
-                )
1229
-            );
1230
-        }
1231
-        // now generate billing form for selected method of payment
1232
-        $payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1233
-        // fill form with attendee info if applicable
1234
-        if ($payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1235
-            && $this->checkout->transaction_has_primary_registrant()
1236
-        ) {
1237
-            $payment_method_billing_form->populate_from_attendee(
1238
-                $this->checkout->transaction->primary_registration()->attendee()
1239
-            );
1240
-        }
1241
-        // and debug content
1242
-        if ($payment_method_billing_form instanceof EE_Billing_Info_Form
1243
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1244
-        ) {
1245
-            $payment_method_billing_form =
1246
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1247
-                    $payment_method_billing_form
1248
-                );
1249
-        }
1250
-        $billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1251
-            ? $payment_method_billing_form->get_html()
1252
-            : '';
1253
-        $this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1254
-        // localize validation rules for main form
1255
-        $this->checkout->current_step->reg_form->localize_validation_rules();
1256
-        $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1257
-        return true;
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * _get_billing_form_for_payment_method
1263
-     *
1264
-     * @access private
1265
-     * @param EE_Payment_Method $payment_method
1266
-     * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1267
-     * @throws EE_Error
1268
-     * @throws InvalidArgumentException
1269
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1270
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1271
-     */
1272
-    private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1273
-    {
1274
-        $billing_form = $payment_method->type_obj()->billing_form(
1275
-            $this->checkout->transaction,
1276
-            array('amount_owing' => $this->checkout->amount_owing)
1277
-        );
1278
-        if ($billing_form instanceof EE_Billing_Info_Form) {
1279
-            if (apply_filters(
1280
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1281
-                false
1282
-            )
1283
-                && EE_Registry::instance()->REQ->is_set('payment_method')
1284
-            ) {
1285
-                EE_Error::add_success(
1286
-                    apply_filters(
1287
-                        'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1288
-                        sprintf(
1289
-                            esc_html__(
1290
-                                'You have selected "%s" as your method of payment. Please note the important payment information below.',
1291
-                                'event_espresso'
1292
-                            ),
1293
-                            $payment_method->name()
1294
-                        )
1295
-                    )
1296
-                );
1297
-            }
1298
-            return apply_filters(
1299
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1300
-                $billing_form,
1301
-                $payment_method
1302
-            );
1303
-        }
1304
-        // no actual billing form, so return empty HTML form section
1305
-        return new EE_Form_Section_HTML();
1306
-    }
1307
-
1308
-
1309
-    /**
1310
-     * _get_selected_method_of_payment
1311
-     *
1312
-     * @access private
1313
-     * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1314
-     *                          is not found in the incoming request
1315
-     * @param string  $request_param
1316
-     * @return NULL|string
1317
-     * @throws EE_Error
1318
-     * @throws InvalidArgumentException
1319
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1320
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1321
-     */
1322
-    private function _get_selected_method_of_payment(
1323
-        $required = false,
1324
-        $request_param = 'selected_method_of_payment'
1325
-    ) {
1326
-        // is selected_method_of_payment set in the request ?
1327
-        $selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1328
-        if ($selected_method_of_payment) {
1329
-            // sanitize it
1330
-            $selected_method_of_payment = is_array($selected_method_of_payment)
1331
-                ? array_shift($selected_method_of_payment)
1332
-                : $selected_method_of_payment;
1333
-            $selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1334
-            // store it in the session so that it's available for all subsequent requests including AJAX
1335
-            $this->_save_selected_method_of_payment($selected_method_of_payment);
1336
-        } else {
1337
-            // or is is set in the session ?
1338
-            $selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1339
-                'selected_method_of_payment'
1340
-            );
1341
-        }
1342
-        // do ya really really gotta have it?
1343
-        if (empty($selected_method_of_payment) && $required) {
1344
-            EE_Error::add_error(
1345
-                sprintf(
1346
-                    esc_html__(
1347
-                        'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1348
-                        'event_espresso'
1349
-                    ),
1350
-                    '<br/>',
1351
-                    '<br/>',
1352
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
1353
-                ),
1354
-                __FILE__,
1355
-                __FUNCTION__,
1356
-                __LINE__
1357
-            );
1358
-            return null;
1359
-        }
1360
-        return $selected_method_of_payment;
1361
-    }
1362
-
1363
-
1364
-
1365
-
1366
-
1367
-
1368
-    /********************************************************************************************************/
1369
-    /***********************************  SWITCH PAYMENT METHOD  ************************************/
1370
-    /********************************************************************************************************/
1371
-    /**
1372
-     * switch_payment_method
1373
-     *
1374
-     * @access public
1375
-     * @return string
1376
-     * @throws EE_Error
1377
-     * @throws InvalidArgumentException
1378
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1379
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1380
-     */
1381
-    public function switch_payment_method()
1382
-    {
1383
-        if (! $this->_verify_payment_method_is_set()) {
1384
-            return false;
1385
-        }
1386
-        if (apply_filters(
1387
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1388
-            false
1389
-        )) {
1390
-            EE_Error::add_success(
1391
-                apply_filters(
1392
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1393
-                    sprintf(
1394
-                        esc_html__(
1395
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1396
-                            'event_espresso'
1397
-                        ),
1398
-                        $this->checkout->payment_method->name()
1399
-                    )
1400
-                )
1401
-            );
1402
-        }
1403
-        // generate billing form for selected method of payment if it hasn't been done already
1404
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1405
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1406
-                $this->checkout->payment_method
1407
-            );
1408
-        }
1409
-        // fill form with attendee info if applicable
1410
-        if (apply_filters(
1411
-            'FHEE__populate_billing_form_fields_from_attendee',
1412
-            (
1413
-                $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1414
-                && $this->checkout->transaction_has_primary_registrant()
1415
-            ),
1416
-            $this->checkout->billing_form,
1417
-            $this->checkout->transaction
1418
-        )
1419
-        ) {
1420
-            $this->checkout->billing_form->populate_from_attendee(
1421
-                $this->checkout->transaction->primary_registration()->attendee()
1422
-            );
1423
-        }
1424
-        // and debug content
1425
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form
1426
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1427
-        ) {
1428
-            $this->checkout->billing_form =
1429
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1430
-                    $this->checkout->billing_form
1431
-                );
1432
-        }
1433
-        // get html and validation rules for form
1434
-        if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1435
-            $this->checkout->json_response->set_return_data(
1436
-                array('payment_method_info' => $this->checkout->billing_form->get_html())
1437
-            );
1438
-            // localize validation rules for main form
1439
-            $this->checkout->billing_form->localize_validation_rules(true);
1440
-            $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1441
-        } else {
1442
-            $this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1443
-        }
1444
-        //prevents advancement to next step
1445
-        $this->checkout->continue_reg = false;
1446
-        return true;
1447
-    }
1448
-
1449
-
1450
-    /**
1451
-     * _verify_payment_method_is_set
1452
-     *
1453
-     * @return bool
1454
-     * @throws EE_Error
1455
-     * @throws InvalidArgumentException
1456
-     * @throws ReflectionException
1457
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1458
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1459
-     */
1460
-    protected function _verify_payment_method_is_set()
1461
-    {
1462
-        // generate billing form for selected method of payment if it hasn't been done already
1463
-        if (empty($this->checkout->selected_method_of_payment)) {
1464
-            // how have they chosen to pay?
1465
-            $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1466
-        } else {
1467
-            // choose your own adventure based on method_of_payment
1468
-            switch ($this->checkout->selected_method_of_payment) {
1469
-                case 'events_sold_out' :
1470
-                    EE_Error::add_attention(
1471
-                        apply_filters(
1472
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1473
-                            esc_html__(
1474
-                                'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1475
-                                'event_espresso'
1476
-                            )
1477
-                        ),
1478
-                        __FILE__, __FUNCTION__, __LINE__
1479
-                    );
1480
-                    return false;
1481
-                    break;
1482
-                case 'payments_closed' :
1483
-                    EE_Error::add_attention(
1484
-                        apply_filters(
1485
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1486
-                            esc_html__(
1487
-                                'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1488
-                                'event_espresso'
1489
-                            )
1490
-                        ),
1491
-                        __FILE__, __FUNCTION__, __LINE__
1492
-                    );
1493
-                    return false;
1494
-                    break;
1495
-                case 'no_payment_required' :
1496
-                    EE_Error::add_attention(
1497
-                        apply_filters(
1498
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1499
-                            esc_html__(
1500
-                                'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1501
-                                'event_espresso'
1502
-                            )
1503
-                        ),
1504
-                        __FILE__, __FUNCTION__, __LINE__
1505
-                    );
1506
-                    return false;
1507
-                    break;
1508
-                default:
1509
-            }
1510
-        }
1511
-        // verify payment method
1512
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1513
-            // get payment method for selected method of payment
1514
-            $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1515
-        }
1516
-        return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1517
-    }
1518
-
1519
-
1520
-
1521
-    /********************************************************************************************************/
1522
-    /***************************************  SAVE PAYER DETAILS  ****************************************/
1523
-    /********************************************************************************************************/
1524
-    /**
1525
-     * save_payer_details_via_ajax
1526
-     *
1527
-     * @return void
1528
-     * @throws EE_Error
1529
-     * @throws InvalidArgumentException
1530
-     * @throws ReflectionException
1531
-     * @throws RuntimeException
1532
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1533
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1534
-     */
1535
-    public function save_payer_details_via_ajax()
1536
-    {
1537
-        if (! $this->_verify_payment_method_is_set()) {
1538
-            return;
1539
-        }
1540
-        // generate billing form for selected method of payment if it hasn't been done already
1541
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1542
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1543
-                $this->checkout->payment_method
1544
-            );
1545
-        }
1546
-        // generate primary attendee from payer info if applicable
1547
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1548
-            $attendee = $this->_create_attendee_from_request_data();
1549
-            if ($attendee instanceof EE_Attendee) {
1550
-                foreach ($this->checkout->transaction->registrations() as $registration) {
1551
-                    if ($registration->is_primary_registrant()) {
1552
-                        $this->checkout->primary_attendee_obj = $attendee;
1553
-                        $registration->_add_relation_to($attendee, 'Attendee');
1554
-                        $registration->set_attendee_id($attendee->ID());
1555
-                        $registration->update_cache_after_object_save('Attendee', $attendee);
1556
-                    }
1557
-                }
1558
-            }
1559
-        }
1560
-    }
1561
-
1562
-
1563
-    /**
1564
-     * create_attendee_from_request_data
1565
-     * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1566
-     *
1567
-     * @return EE_Attendee
1568
-     * @throws EE_Error
1569
-     * @throws InvalidArgumentException
1570
-     * @throws ReflectionException
1571
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1572
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1573
-     */
1574
-    protected function _create_attendee_from_request_data()
1575
-    {
1576
-        // get State ID
1577
-        $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1578
-        if (! empty($STA_ID)) {
1579
-            // can we get state object from name ?
1580
-            EE_Registry::instance()->load_model('State');
1581
-            $state  = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1582
-            $STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1583
-        }
1584
-        // get Country ISO
1585
-        $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1586
-        if (! empty($CNT_ISO)) {
1587
-            // can we get country object from name ?
1588
-            EE_Registry::instance()->load_model('Country');
1589
-            $country = EEM_Country::instance()->get_col(
1590
-                array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1591
-                'CNT_ISO'
1592
-            );
1593
-            $CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1594
-        }
1595
-        // grab attendee data
1596
-        $attendee_data = array(
1597
-            'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1598
-            'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1599
-            'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1600
-            'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1601
-            'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1602
-            'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1603
-            'STA_ID'       => $STA_ID,
1604
-            'CNT_ISO'      => $CNT_ISO,
1605
-            'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1606
-            'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1607
-        );
1608
-        // validate the email address since it is the most important piece of info
1609
-        if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1610
-            EE_Error::add_error(
1611
-                esc_html__('An invalid email address was submitted.', 'event_espresso'),
1612
-                __FILE__,
1613
-                __FUNCTION__,
1614
-                __LINE__
1615
-            );
1616
-        }
1617
-        // does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1618
-        // AND email address
1619
-        if (! empty($attendee_data['ATT_fname'])
1620
-            && ! empty($attendee_data['ATT_lname'])
1621
-            && ! empty($attendee_data['ATT_email'])
1622
-        ) {
1623
-            $existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1624
-                array(
1625
-                    'ATT_fname' => $attendee_data['ATT_fname'],
1626
-                    'ATT_lname' => $attendee_data['ATT_lname'],
1627
-                    'ATT_email' => $attendee_data['ATT_email'],
1628
-                )
1629
-            );
1630
-            if ($existing_attendee instanceof EE_Attendee) {
1631
-                return $existing_attendee;
1632
-            }
1633
-        }
1634
-        // no existing attendee? kk let's create a new one
1635
-        // kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1636
-        // don't exist
1637
-        $attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1638
-            ? $attendee_data['ATT_fname']
1639
-            : $attendee_data['ATT_email'];
1640
-        $attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1641
-            ? $attendee_data['ATT_lname']
1642
-            : $attendee_data['ATT_email'];
1643
-        return EE_Attendee::new_instance($attendee_data);
1644
-    }
1645
-
1646
-
1647
-
1648
-    /********************************************************************************************************/
1649
-    /****************************************  PROCESS REG STEP  *****************************************/
1650
-    /********************************************************************************************************/
1651
-    /**
1652
-     * process_reg_step
1653
-     *
1654
-     * @return bool
1655
-     * @throws EE_Error
1656
-     * @throws InvalidArgumentException
1657
-     * @throws ReflectionException
1658
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1659
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1660
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1661
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1662
-     */
1663
-    public function process_reg_step()
1664
-    {
1665
-        // how have they chosen to pay?
1666
-        $this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1667
-            ? 'no_payment_required'
1668
-            : $this->_get_selected_method_of_payment(true);
1669
-        // choose your own adventure based on method_of_payment
1670
-        switch ($this->checkout->selected_method_of_payment) {
1671
-
1672
-            case 'events_sold_out' :
1673
-                $this->checkout->redirect     = true;
1674
-                $this->checkout->redirect_url = $this->checkout->cancel_page_url;
1675
-                $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1676
-                // mark this reg step as completed
1677
-                $this->set_completed();
1678
-                return false;
1679
-                break;
1680
-
1681
-            case 'payments_closed' :
1682
-                if (apply_filters(
1683
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1684
-                    false
1685
-                )) {
1686
-                    EE_Error::add_success(
1687
-                        esc_html__('no payment required at this time.', 'event_espresso'),
1688
-                        __FILE__,
1689
-                        __FUNCTION__,
1690
-                        __LINE__
1691
-                    );
1692
-                }
1693
-                // mark this reg step as completed
1694
-                $this->set_completed();
1695
-                return true;
1696
-                break;
1697
-
1698
-            case 'no_payment_required' :
1699
-                if (apply_filters(
1700
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1701
-                    false
1702
-                )) {
1703
-                    EE_Error::add_success(
1704
-                        esc_html__('no payment required.', 'event_espresso'),
1705
-                        __FILE__,
1706
-                        __FUNCTION__,
1707
-                        __LINE__
1708
-                    );
1709
-                }
1710
-                // mark this reg step as completed
1711
-                $this->set_completed();
1712
-                return true;
1713
-                break;
1714
-
1715
-            default:
1716
-                $registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1717
-                    EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1718
-                );
1719
-                $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1720
-                    $registrations,
1721
-                    EE_Registry::instance()->SSN->checkout()->revisit
1722
-                );
1723
-                // calculate difference between the two arrays
1724
-                $registrations = array_diff($registrations, $ejected_registrations);
1725
-                if (empty($registrations)) {
1726
-                    $this->_redirect_because_event_sold_out();
1727
-                    return false;
1728
-                }
1729
-                $payment_successful = $this->_process_payment();
1730
-                if ($payment_successful) {
1731
-                    $this->checkout->continue_reg = true;
1732
-                    $this->_maybe_set_completed($this->checkout->payment_method);
1733
-                } else {
1734
-                    $this->checkout->continue_reg = false;
1735
-                }
1736
-                return $payment_successful;
1737
-        }
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * _redirect_because_event_sold_out
1743
-     *
1744
-     * @access protected
1745
-     * @return void
1746
-     */
1747
-    protected function _redirect_because_event_sold_out()
1748
-    {
1749
-        $this->checkout->continue_reg = false;
1750
-        // set redirect URL
1751
-        $this->checkout->redirect_url = add_query_arg(
1752
-            array('e_reg_url_link' => $this->checkout->reg_url_link),
1753
-            $this->checkout->current_step->reg_step_url()
1754
-        );
1755
-        $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1756
-    }
1757
-
1758
-
1759
-    /**
1760
-     * _maybe_set_completed
1761
-     *
1762
-     * @access protected
1763
-     * @param \EE_Payment_Method $payment_method
1764
-     * @return void
1765
-     * @throws \EE_Error
1766
-     */
1767
-    protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1768
-    {
1769
-        switch ($payment_method->type_obj()->payment_occurs()) {
1770
-            case EE_PMT_Base::offsite :
1771
-                break;
1772
-            case EE_PMT_Base::onsite :
1773
-            case EE_PMT_Base::offline :
1774
-                // mark this reg step as completed
1775
-                $this->set_completed();
1776
-                break;
1777
-        }
1778
-    }
1779
-
1780
-
1781
-    /**
1782
-     *    update_reg_step
1783
-     *    this is the final step after a user  revisits the site to retry a payment
1784
-     *
1785
-     * @return bool
1786
-     * @throws EE_Error
1787
-     * @throws InvalidArgumentException
1788
-     * @throws ReflectionException
1789
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1790
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1791
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1792
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1793
-     */
1794
-    public function update_reg_step()
1795
-    {
1796
-        $success = true;
1797
-        // if payment required
1798
-        if ($this->checkout->transaction->total() > 0) {
1799
-            do_action(
1800
-                'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1801
-                $this->checkout->transaction
1802
-            );
1803
-            // attempt payment via payment method
1804
-            $success = $this->process_reg_step();
1805
-        }
1806
-        if ($success && ! $this->checkout->redirect) {
1807
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1808
-                $this->checkout->transaction->ID()
1809
-            );
1810
-            // set return URL
1811
-            $this->checkout->redirect_url = add_query_arg(
1812
-                array('e_reg_url_link' => $this->checkout->reg_url_link),
1813
-                $this->checkout->thank_you_page_url
1814
-            );
1815
-        }
1816
-        return $success;
1817
-    }
1818
-
1819
-
1820
-    /**
1821
-     *    _process_payment
1822
-     *
1823
-     * @access private
1824
-     * @return bool
1825
-     * @throws EE_Error
1826
-     * @throws InvalidArgumentException
1827
-     * @throws ReflectionException
1828
-     * @throws RuntimeException
1829
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1830
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1831
-     */
1832
-    private function _process_payment()
1833
-    {
1834
-        // basically confirm that the event hasn't sold out since they hit the page
1835
-        if (! $this->_last_second_ticket_verifications()) {
1836
-            return false;
1837
-        }
1838
-        // ya gotta make a choice man
1839
-        if (empty($this->checkout->selected_method_of_payment)) {
1840
-            $this->checkout->json_response->set_plz_select_method_of_payment(
1841
-                esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1842
-            );
1843
-            return false;
1844
-        }
1845
-        // get EE_Payment_Method object
1846
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1847
-            return false;
1848
-        }
1849
-        // setup billing form
1850
-        if ($this->checkout->payment_method->is_on_site()) {
1851
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1852
-                $this->checkout->payment_method
1853
-            );
1854
-            // bad billing form ?
1855
-            if (! $this->_billing_form_is_valid()) {
1856
-                return false;
1857
-            }
1858
-        }
1859
-        // ensure primary registrant has been fully processed
1860
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1861
-            return false;
1862
-        }
1863
-        // if session is close to expiring (under 10 minutes by default)
1864
-        if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1865
-            // add some time to session expiration so that payment can be completed
1866
-            EE_Registry::instance()->SSN->extend_expiration();
1867
-        }
1868
-        /** @type EE_Transaction_Processor $transaction_processor */
1869
-        //$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1870
-        // in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1871
-        // for events with a default reg status of Approved
1872
-        // $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1873
-        //      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1874
-        // );
1875
-        // attempt payment
1876
-        $payment = $this->_attempt_payment($this->checkout->payment_method);
1877
-        // process results
1878
-        $payment = $this->_validate_payment($payment);
1879
-        $payment = $this->_post_payment_processing($payment);
1880
-        // verify payment
1881
-        if ($payment instanceof EE_Payment) {
1882
-            // store that for later
1883
-            $this->checkout->payment = $payment;
1884
-            // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1885
-            $this->checkout->transaction->toggle_failed_transaction_status();
1886
-            $payment_status = $payment->status();
1887
-            if (
1888
-                $payment_status === EEM_Payment::status_id_approved
1889
-                || $payment_status === EEM_Payment::status_id_pending
1890
-            ) {
1891
-                return true;
1892
-            } else {
1893
-                return false;
1894
-            }
1895
-        } else if ($payment === true) {
1896
-            // please note that offline payment methods will NOT make a payment,
1897
-            // but instead just mark themselves as the PMD_ID on the transaction, and return true
1898
-            $this->checkout->payment = $payment;
1899
-            return true;
1900
-        }
1901
-        // where's my money?
1902
-        return false;
1903
-    }
1904
-
1905
-
1906
-    /**
1907
-     * _last_second_ticket_verifications
1908
-     *
1909
-     * @access public
1910
-     * @return bool
1911
-     * @throws EE_Error
1912
-     */
1913
-    protected function _last_second_ticket_verifications()
1914
-    {
1915
-        // don't bother re-validating if not a return visit
1916
-        if (! $this->checkout->revisit) {
1917
-            return true;
1918
-        }
1919
-        $registrations = $this->checkout->transaction->registrations();
1920
-        if (empty($registrations)) {
1921
-            return false;
1922
-        }
1923
-        foreach ($registrations as $registration) {
1924
-            if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1925
-                $event = $registration->event_obj();
1926
-                if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1927
-                    EE_Error::add_error(
1928
-                        apply_filters(
1929
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1930
-                            sprintf(
1931
-                                esc_html__(
1932
-                                    'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1933
-                                    'event_espresso'
1934
-                                ),
1935
-                                $event->name()
1936
-                            )
1937
-                        ),
1938
-                        __FILE__,
1939
-                        __FUNCTION__,
1940
-                        __LINE__
1941
-                    );
1942
-                    return false;
1943
-                }
1944
-            }
1945
-        }
1946
-        return true;
1947
-    }
1948
-
1949
-
1950
-    /**
1951
-     * redirect_form
1952
-     *
1953
-     * @access public
1954
-     * @return bool
1955
-     * @throws EE_Error
1956
-     * @throws InvalidArgumentException
1957
-     * @throws ReflectionException
1958
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1959
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1960
-     */
1961
-    public function redirect_form()
1962
-    {
1963
-        $payment_method_billing_info = $this->_payment_method_billing_info(
1964
-            $this->_get_payment_method_for_selected_method_of_payment()
1965
-        );
1966
-        $html                        = $payment_method_billing_info->get_html();
1967
-        $html                        .= $this->checkout->redirect_form;
1968
-        EE_Registry::instance()->REQ->add_output($html);
1969
-        return true;
1970
-    }
1971
-
1972
-
1973
-    /**
1974
-     * _billing_form_is_valid
1975
-     *
1976
-     * @access private
1977
-     * @return bool
1978
-     * @throws \EE_Error
1979
-     */
1980
-    private function _billing_form_is_valid()
1981
-    {
1982
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1983
-            return true;
1984
-        }
1985
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1986
-            if ($this->checkout->billing_form->was_submitted()) {
1987
-                $this->checkout->billing_form->receive_form_submission();
1988
-                if ($this->checkout->billing_form->is_valid()) {
1989
-                    return true;
1990
-                }
1991
-                $validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
1992
-                $error_strings     = array();
1993
-                foreach ($validation_errors as $validation_error) {
1994
-                    if ($validation_error instanceof EE_Validation_Error) {
1995
-                        $form_section = $validation_error->get_form_section();
1996
-                        if ($form_section instanceof EE_Form_Input_Base) {
1997
-                            $label = $form_section->html_label_text();
1998
-                        } elseif ($form_section instanceof EE_Form_Section_Base) {
1999
-                            $label = $form_section->name();
2000
-                        } else {
2001
-                            $label = esc_html__('Validation Error', 'event_espresso');
2002
-                        }
2003
-                        $error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2004
-                    }
2005
-                }
2006
-                EE_Error::add_error(
2007
-                    sprintf(
2008
-                        esc_html__(
2009
-                            'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2010
-                            'event_espresso'
2011
-                        ),
2012
-                        '<br/>',
2013
-                        implode('<br/>', $error_strings)
2014
-                    ),
2015
-                    __FILE__,
2016
-                    __FUNCTION__,
2017
-                    __LINE__
2018
-                );
2019
-            } else {
2020
-                EE_Error::add_error(
2021
-                    esc_html__(
2022
-                        'The billing form was not submitted or something prevented it\'s submission.',
2023
-                        'event_espresso'
2024
-                    ),
2025
-                    __FILE__,
2026
-                    __FUNCTION__,
2027
-                    __LINE__
2028
-                );
2029
-            }
2030
-        } else {
2031
-            EE_Error::add_error(
2032
-                esc_html__('The submitted billing form is invalid possibly due to a technical reason.', 'event_espresso'),
2033
-                __FILE__,
2034
-                __FUNCTION__,
2035
-                __LINE__
2036
-            );
2037
-        }
2038
-        return false;
2039
-    }
2040
-
2041
-
2042
-    /**
2043
-     * _setup_primary_registrant_prior_to_payment
2044
-     * ensures that the primary registrant has a valid attendee object created with the critical details populated
2045
-     * (first & last name & email) and that both the transaction object and primary registration object have been saved
2046
-     * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2047
-     * yet)
2048
-     *
2049
-     * @access private
2050
-     * @return bool
2051
-     * @throws EE_Error
2052
-     * @throws InvalidArgumentException
2053
-     * @throws ReflectionException
2054
-     * @throws RuntimeException
2055
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2056
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2057
-     */
2058
-    private function _setup_primary_registrant_prior_to_payment()
2059
-    {
2060
-        // check if transaction has a primary registrant and that it has a related Attendee object
2061
-        // if not, then we need to at least gather some primary registrant data before attempting payment
2062
-        if (
2063
-            $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2064
-            && ! $this->checkout->transaction_has_primary_registrant()
2065
-            && ! $this->_capture_primary_registration_data_from_billing_form()
2066
-        ) {
2067
-            return false;
2068
-        }
2069
-        // because saving an object clears it's cache, we need to do the chevy shuffle
2070
-        // grab the primary_registration object
2071
-        $primary_registration = $this->checkout->transaction->primary_registration();
2072
-        // at this point we'll consider a TXN to not have been failed
2073
-        $this->checkout->transaction->toggle_failed_transaction_status();
2074
-        // save the TXN ( which clears cached copy of primary_registration)
2075
-        $this->checkout->transaction->save();
2076
-        // grab TXN ID and save it to the primary_registration
2077
-        $primary_registration->set_transaction_id($this->checkout->transaction->ID());
2078
-        // save what we have so far
2079
-        $primary_registration->save();
2080
-        return true;
2081
-    }
2082
-
2083
-
2084
-    /**
2085
-     * _capture_primary_registration_data_from_billing_form
2086
-     *
2087
-     * @access private
2088
-     * @return bool
2089
-     * @throws EE_Error
2090
-     * @throws InvalidArgumentException
2091
-     * @throws ReflectionException
2092
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2093
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2094
-     */
2095
-    private function _capture_primary_registration_data_from_billing_form()
2096
-    {
2097
-        // convert billing form data into an attendee
2098
-        $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2099
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2100
-            EE_Error::add_error(
2101
-                sprintf(
2102
-                    esc_html__(
2103
-                        'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2104
-                        'event_espresso'
2105
-                    ),
2106
-                    '<br/>',
2107
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2108
-                ),
2109
-                __FILE__,
2110
-                __FUNCTION__,
2111
-                __LINE__
2112
-            );
2113
-            return false;
2114
-        }
2115
-        $primary_registration = $this->checkout->transaction->primary_registration();
2116
-        if (! $primary_registration instanceof EE_Registration) {
2117
-            EE_Error::add_error(
2118
-                sprintf(
2119
-                    esc_html__(
2120
-                        'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2121
-                        'event_espresso'
2122
-                    ),
2123
-                    '<br/>',
2124
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2125
-                ),
2126
-                __FILE__,
2127
-                __FUNCTION__,
2128
-                __LINE__
2129
-            );
2130
-            return false;
2131
-        }
2132
-        if (! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2133
-              instanceof
2134
-              EE_Attendee
2135
-        ) {
2136
-            EE_Error::add_error(
2137
-                sprintf(
2138
-                    esc_html__(
2139
-                        'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2140
-                        'event_espresso'
2141
-                    ),
2142
-                    '<br/>',
2143
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2144
-                ),
2145
-                __FILE__,
2146
-                __FUNCTION__,
2147
-                __LINE__
2148
-            );
2149
-            return false;
2150
-        }
2151
-        /** @type EE_Registration_Processor $registration_processor */
2152
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2153
-        // at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2154
-        $registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2155
-        return true;
2156
-    }
2157
-
2158
-
2159
-    /**
2160
-     * _get_payment_method_for_selected_method_of_payment
2161
-     * retrieves a valid payment method
2162
-     *
2163
-     * @access public
2164
-     * @return EE_Payment_Method
2165
-     * @throws EE_Error
2166
-     * @throws InvalidArgumentException
2167
-     * @throws ReflectionException
2168
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2169
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2170
-     */
2171
-    private function _get_payment_method_for_selected_method_of_payment()
2172
-    {
2173
-        if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2174
-            $this->_redirect_because_event_sold_out();
2175
-            return null;
2176
-        }
2177
-        // get EE_Payment_Method object
2178
-        if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2179
-            $payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2180
-        } else {
2181
-            // load EEM_Payment_Method
2182
-            EE_Registry::instance()->load_model('Payment_Method');
2183
-            /** @type EEM_Payment_Method $EEM_Payment_Method */
2184
-            $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2185
-            $payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2186
-        }
2187
-        // verify $payment_method
2188
-        if (! $payment_method instanceof EE_Payment_Method) {
2189
-            // not a payment
2190
-            EE_Error::add_error(
2191
-                sprintf(
2192
-                    esc_html__(
2193
-                        'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2194
-                        'event_espresso'
2195
-                    ),
2196
-                    '<br/>',
2197
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2198
-                ),
2199
-                __FILE__,
2200
-                __FUNCTION__,
2201
-                __LINE__
2202
-            );
2203
-            return null;
2204
-        }
2205
-        // and verify it has a valid Payment_Method Type object
2206
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2207
-            // not a payment
2208
-            EE_Error::add_error(
2209
-                sprintf(
2210
-                    esc_html__(
2211
-                        'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2212
-                        'event_espresso'
2213
-                    ),
2214
-                    '<br/>',
2215
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2216
-                ),
2217
-                __FILE__,
2218
-                __FUNCTION__,
2219
-                __LINE__
2220
-            );
2221
-            return null;
2222
-        }
2223
-        return $payment_method;
2224
-    }
2225
-
2226
-
2227
-    /**
2228
-     *    _attempt_payment
2229
-     *
2230
-     * @access    private
2231
-     * @type    EE_Payment_Method $payment_method
2232
-     * @return mixed EE_Payment | boolean
2233
-     * @throws EE_Error
2234
-     * @throws InvalidArgumentException
2235
-     * @throws ReflectionException
2236
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2237
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2238
-     */
2239
-    private function _attempt_payment(EE_Payment_Method $payment_method)
2240
-    {
2241
-        $payment = null;
2242
-        $this->checkout->transaction->save();
2243
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2244
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2245
-            return false;
2246
-        }
2247
-        try {
2248
-            $payment_processor->set_revisit($this->checkout->revisit);
2249
-            // generate payment object
2250
-            $payment = $payment_processor->process_payment(
2251
-                $payment_method,
2252
-                $this->checkout->transaction,
2253
-                $this->checkout->amount_owing,
2254
-                $this->checkout->billing_form,
2255
-                $this->_get_return_url($payment_method),
2256
-                'CART',
2257
-                $this->checkout->admin_request,
2258
-                true,
2259
-                $this->reg_step_url()
2260
-            );
2261
-        } catch (Exception $e) {
2262
-            $this->_handle_payment_processor_exception($e);
2263
-        }
2264
-        return $payment;
2265
-    }
2266
-
2267
-
2268
-    /**
2269
-     * _handle_payment_processor_exception
2270
-     *
2271
-     * @access protected
2272
-     * @param \Exception $e
2273
-     * @return void
2274
-     * @throws EE_Error
2275
-     * @throws InvalidArgumentException
2276
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2277
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2278
-     */
2279
-    protected function _handle_payment_processor_exception(Exception $e)
2280
-    {
2281
-        EE_Error::add_error(
2282
-            sprintf(
2283
-                esc_html__(
2284
-                    'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2285
-                    'event_espresso'
2286
-                ),
2287
-                '<br/>',
2288
-                EE_Registry::instance()->CFG->organization->get_pretty('email'),
2289
-                $e->getMessage(),
2290
-                $e->getFile(),
2291
-                $e->getLine()
2292
-            ),
2293
-            __FILE__,
2294
-            __FUNCTION__,
2295
-            __LINE__
2296
-        );
2297
-    }
2298
-
2299
-
2300
-    /**
2301
-     * _get_return_url
2302
-     *
2303
-     * @access protected
2304
-     * @param \EE_Payment_Method $payment_method
2305
-     * @return string
2306
-     * @throws \EE_Error
2307
-     */
2308
-    protected function _get_return_url(EE_Payment_Method $payment_method)
2309
-    {
2310
-        $return_url = '';
2311
-        switch ($payment_method->type_obj()->payment_occurs()) {
2312
-            case EE_PMT_Base::offsite :
2313
-                $return_url = add_query_arg(
2314
-                    array(
2315
-                        'action'                     => 'process_gateway_response',
2316
-                        'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2317
-                        'spco_txn'                   => $this->checkout->transaction->ID(),
2318
-                    ),
2319
-                    $this->reg_step_url()
2320
-                );
2321
-                break;
2322
-            case EE_PMT_Base::onsite :
2323
-            case EE_PMT_Base::offline :
2324
-                $return_url = $this->checkout->next_step->reg_step_url();
2325
-                break;
2326
-        }
2327
-        return $return_url;
2328
-    }
2329
-
2330
-
2331
-    /**
2332
-     * _validate_payment
2333
-     *
2334
-     * @access private
2335
-     * @param EE_Payment $payment
2336
-     * @return EE_Payment|FALSE
2337
-     * @throws EE_Error
2338
-     * @throws InvalidArgumentException
2339
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2340
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2341
-     */
2342
-    private function _validate_payment($payment = null)
2343
-    {
2344
-        if ($this->checkout->payment_method->is_off_line()) {
2345
-            return true;
2346
-        }
2347
-        // verify payment object
2348
-        if (! $payment instanceof EE_Payment) {
2349
-            // not a payment
2350
-            EE_Error::add_error(
2351
-                sprintf(
2352
-                    esc_html__(
2353
-                        'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2354
-                        'event_espresso'
2355
-                    ),
2356
-                    '<br/>',
2357
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2358
-                ),
2359
-                __FILE__,
2360
-                __FUNCTION__,
2361
-                __LINE__
2362
-            );
2363
-            return false;
2364
-        }
2365
-        return $payment;
2366
-    }
2367
-
2368
-
2369
-    /**
2370
-     * _post_payment_processing
2371
-     *
2372
-     * @access private
2373
-     * @param EE_Payment|bool $payment
2374
-     * @return bool
2375
-     * @throws EE_Error
2376
-     * @throws InvalidArgumentException
2377
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2378
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2379
-     */
2380
-    private function _post_payment_processing($payment = null)
2381
-    {
2382
-        // Off-Line payment?
2383
-        if ($payment === true) {
2384
-            //$this->_setup_redirect_for_next_step();
2385
-            return true;
2386
-            // On-Site payment?
2387
-        } else if ($this->checkout->payment_method->is_on_site()) {
2388
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2389
-                //$this->_setup_redirect_for_next_step();
2390
-                $this->checkout->continue_reg = false;
2391
-            }
2392
-            // Off-Site payment?
2393
-        } else if ($this->checkout->payment_method->is_off_site()) {
2394
-            // if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2395
-            if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2396
-                do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2397
-                $this->checkout->redirect      = true;
2398
-                $this->checkout->redirect_form = $payment->redirect_form();
2399
-                $this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2400
-                // set JSON response
2401
-                $this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2402
-                // and lastly, let's bump the payment status to pending
2403
-                $payment->set_status(EEM_Payment::status_id_pending);
2404
-                $payment->save();
2405
-            } else {
2406
-                // not a payment
2407
-                $this->checkout->continue_reg = false;
2408
-                EE_Error::add_error(
2409
-                    sprintf(
2410
-                        esc_html__(
2411
-                            'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2412
-                            'event_espresso'
2413
-                        ),
2414
-                        '<br/>',
2415
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
2416
-                    ),
2417
-                    __FILE__,
2418
-                    __FUNCTION__,
2419
-                    __LINE__
2420
-                );
2421
-            }
2422
-        } else {
2423
-            // ummm ya... not Off-Line, not On-Site, not off-Site ????
2424
-            $this->checkout->continue_reg = false;
2425
-            return false;
2426
-        }
2427
-        return $payment;
2428
-    }
2429
-
2430
-
2431
-    /**
2432
-     *    _process_payment_status
2433
-     *
2434
-     * @access private
2435
-     * @type    EE_Payment $payment
2436
-     * @param string       $payment_occurs
2437
-     * @return bool
2438
-     * @throws EE_Error
2439
-     * @throws InvalidArgumentException
2440
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2441
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2442
-     */
2443
-    private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2444
-    {
2445
-        // off-line payment? carry on
2446
-        if ($payment_occurs === EE_PMT_Base::offline) {
2447
-            return true;
2448
-        }
2449
-        // verify payment validity
2450
-        if ($payment instanceof EE_Payment) {
2451
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2452
-            $msg = $payment->gateway_response();
2453
-            // check results
2454
-            switch ($payment->status()) {
2455
-                // good payment
2456
-                case EEM_Payment::status_id_approved :
2457
-                    EE_Error::add_success(
2458
-                        esc_html__('Your payment was processed successfully.', 'event_espresso'),
2459
-                        __FILE__,
2460
-                        __FUNCTION__,
2461
-                        __LINE__
2462
-                    );
2463
-                    return true;
2464
-                    break;
2465
-                // slow payment
2466
-                case EEM_Payment::status_id_pending :
2467
-                    if (empty($msg)) {
2468
-                        $msg = esc_html__(
2469
-                            'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2470
-                            'event_espresso'
2471
-                        );
2472
-                    }
2473
-                    EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2474
-                    return true;
2475
-                    break;
2476
-                // don't wanna payment
2477
-                case EEM_Payment::status_id_cancelled :
2478
-                    if (empty($msg)) {
2479
-                        $msg = _n(
2480
-                            'Payment cancelled. Please try again.',
2481
-                            'Payment cancelled. Please try again or select another method of payment.',
2482
-                            count($this->checkout->available_payment_methods),
2483
-                            'event_espresso'
2484
-                        );
2485
-                    }
2486
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2487
-                    return false;
2488
-                    break;
2489
-                // not enough payment
2490
-                case EEM_Payment::status_id_declined :
2491
-                    if (empty($msg)) {
2492
-                        $msg = _n(
2493
-                            'We\'re sorry but your payment was declined. Please try again.',
2494
-                            'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2495
-                            count($this->checkout->available_payment_methods),
2496
-                            'event_espresso'
2497
-                        );
2498
-                    }
2499
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2500
-                    return false;
2501
-                    break;
2502
-                // bad payment
2503
-                case EEM_Payment::status_id_failed :
2504
-                    if (! empty($msg)) {
2505
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2506
-                        return false;
2507
-                    }
2508
-                    // default to error below
2509
-                    break;
2510
-            }
2511
-        }
2512
-        // off-site payment gateway responses are too unreliable, so let's just assume that
2513
-        // the payment processing is just running slower than the registrant's request
2514
-        if ($payment_occurs === EE_PMT_Base::offsite) {
2515
-            return true;
2516
-        }
2517
-        EE_Error::add_error(
2518
-            sprintf(
2519
-                esc_html__(
2520
-                    'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2521
-                    'event_espresso'
2522
-                ),
2523
-                '<br/>',
2524
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
2525
-            ),
2526
-            __FILE__,
2527
-            __FUNCTION__,
2528
-            __LINE__
2529
-        );
2530
-        return false;
2531
-    }
2532
-
2533
-
2534
-
2535
-
2536
-
2537
-
2538
-    /********************************************************************************************************/
2539
-    /**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2540
-    /********************************************************************************************************/
2541
-    /**
2542
-     * process_gateway_response
2543
-     * this is the return point for Off-Site Payment Methods
2544
-     * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2545
-     * otherwise, it will load up the last payment made for the TXN.
2546
-     * If the payment retrieved looks good, it will then either:
2547
-     *    complete the current step and allow advancement to the next reg step
2548
-     *        or present the payment options again
2549
-     *
2550
-     * @access private
2551
-     * @return EE_Payment|FALSE
2552
-     * @throws EE_Error
2553
-     * @throws InvalidArgumentException
2554
-     * @throws ReflectionException
2555
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2556
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2557
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2558
-     */
2559
-    public function process_gateway_response()
2560
-    {
2561
-        $payment = null;
2562
-        // how have they chosen to pay?
2563
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2564
-        // get EE_Payment_Method object
2565
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2566
-            $this->checkout->continue_reg = false;
2567
-            return false;
2568
-        }
2569
-        if (! $this->checkout->payment_method->is_off_site()) {
2570
-            return false;
2571
-        }
2572
-        $this->_validate_offsite_return();
2573
-        // DEBUG LOG
2574
-        //$this->checkout->log(
2575
-        //	__CLASS__, __FUNCTION__, __LINE__,
2576
-        //	array(
2577
-        //		'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2578
-        //		'payment_method' => $this->checkout->payment_method,
2579
-        //	),
2580
-        //	true
2581
-        //);
2582
-        // verify TXN
2583
-        if ($this->checkout->transaction instanceof EE_Transaction) {
2584
-            $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2585
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2586
-                $this->checkout->continue_reg = false;
2587
-                return false;
2588
-            }
2589
-            $payment = $this->_process_off_site_payment($gateway);
2590
-            $payment = $this->_process_cancelled_payments($payment);
2591
-            $payment = $this->_validate_payment($payment);
2592
-            // if payment was not declined by the payment gateway or cancelled by the registrant
2593
-            if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2594
-                //$this->_setup_redirect_for_next_step();
2595
-                // store that for later
2596
-                $this->checkout->payment = $payment;
2597
-                // mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2598
-                // because we will complete this step during the IPN processing then
2599
-                if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2600
-                    $this->set_completed();
2601
-                }
2602
-                return true;
2603
-            }
2604
-        }
2605
-        // DEBUG LOG
2606
-        //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2607
-        //	array( 'payment' => $payment )
2608
-        //);
2609
-        $this->checkout->continue_reg = false;
2610
-        return false;
2611
-    }
2612
-
2613
-
2614
-    /**
2615
-     * _validate_return
2616
-     *
2617
-     * @access private
2618
-     * @return void
2619
-     * @throws EE_Error
2620
-     * @throws InvalidArgumentException
2621
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2622
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2623
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2624
-     */
2625
-    private function _validate_offsite_return()
2626
-    {
2627
-        $TXN_ID = (int)EE_Registry::instance()->REQ->get('spco_txn', 0);
2628
-        if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
-            // Houston... we might have a problem
2630
-            $invalid_TXN = false;
2631
-            // first gather some info
2632
-            $valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
-            $primary_registrant = $valid_TXN instanceof EE_Transaction
2634
-                ? $valid_TXN->primary_registration()
2635
-                : null;
2636
-            // let's start by retrieving the cart for this TXN
2637
-            $cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
-            if ($cart instanceof EE_Cart) {
2639
-                // verify that the current cart has tickets
2640
-                $tickets = $cart->get_tickets();
2641
-                if (empty($tickets)) {
2642
-                    $invalid_TXN = true;
2643
-                }
2644
-            } else {
2645
-                $invalid_TXN = true;
2646
-            }
2647
-            $valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
-                ? $primary_registrant->session_ID()
2649
-                : null;
2650
-            // validate current Session ID and compare against valid TXN session ID
2651
-            if (
2652
-                $invalid_TXN // if this is already true, then skip other checks
2653
-                || EE_Session::instance()->id() === null
2654
-                || (
2655
-                    // WARNING !!!
2656
-                    // this could be PayPal sending back duplicate requests (ya they do that)
2657
-                    // or it **could** mean someone is simply registering AGAIN after having just done so
2658
-                    // so now we need to determine if this current TXN looks valid or not
2659
-                    // and whether this reg step has even been started ?
2660
-                    EE_Session::instance()->id() === $valid_TXN_SID
2661
-                    // really? you're half way through this reg step, but you never started it ?
2662
-                    && $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
-                )
2664
-            ) {
2665
-                $invalid_TXN = true;
2666
-            }
2667
-            if ($invalid_TXN) {
2668
-                // is the valid TXN completed ?
2669
-                if ($valid_TXN instanceof EE_Transaction) {
2670
-                    // has this step even been started ?
2671
-                    $reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
-                    if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
-                        // so it **looks** like this is a double request from PayPal
2674
-                        // so let's try to pick up where we left off
2675
-                        $this->checkout->transaction = $valid_TXN;
2676
-                        $this->checkout->refresh_all_entities(true);
2677
-                        return;
2678
-                    }
2679
-                }
2680
-                // you appear to be lost?
2681
-                $this->_redirect_wayward_request($primary_registrant);
2682
-            }
2683
-        }
2684
-    }
2685
-
2686
-
2687
-    /**
2688
-     * _redirect_wayward_request
2689
-     *
2690
-     * @access private
2691
-     * @param \EE_Registration|null $primary_registrant
2692
-     * @return bool
2693
-     * @throws EE_Error
2694
-     * @throws InvalidArgumentException
2695
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2696
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2697
-     */
2698
-    private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
-    {
2700
-        if (! $primary_registrant instanceof EE_Registration) {
2701
-            // try redirecting based on the current TXN
2702
-            $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
-                ? $this->checkout->transaction->primary_registration()
2704
-                : null;
2705
-        }
2706
-        if (! $primary_registrant instanceof EE_Registration) {
2707
-            EE_Error::add_error(
2708
-                sprintf(
2709
-                    esc_html__(
2710
-                        'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
-                        'event_espresso'
2712
-                    ),
2713
-                    '<br/>',
2714
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
-                ),
2716
-                __FILE__,
2717
-                __FUNCTION__,
2718
-                __LINE__
2719
-            );
2720
-            return false;
2721
-        }
2722
-        // make sure transaction is not locked
2723
-        $this->checkout->transaction->unlock();
2724
-        wp_safe_redirect(
2725
-            add_query_arg(
2726
-                array(
2727
-                    'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
-                ),
2729
-                $this->checkout->thank_you_page_url
2730
-            )
2731
-        );
2732
-        exit();
2733
-    }
2734
-
2735
-
2736
-    /**
2737
-     * _process_off_site_payment
2738
-     *
2739
-     * @access private
2740
-     * @param \EE_Offsite_Gateway $gateway
2741
-     * @return EE_Payment
2742
-     * @throws EE_Error
2743
-     * @throws InvalidArgumentException
2744
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2745
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2746
-     */
2747
-    private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
-    {
2749
-        try {
2750
-            $request_data = \EE_Registry::instance()->REQ->params();
2751
-            // if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2752
-            $this->set_handle_IPN_in_this_request(
2753
-                $gateway->handle_IPN_in_this_request($request_data, false)
2754
-            );
2755
-            if ($this->handle_IPN_in_this_request()) {
2756
-                // get payment details and process results
2757
-                /** @type EE_Payment_Processor $payment_processor */
2758
-                $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2759
-                $payment           = $payment_processor->process_ipn(
2760
-                    $request_data,
2761
-                    $this->checkout->transaction,
2762
-                    $this->checkout->payment_method,
2763
-                    true,
2764
-                    false
2765
-                );
2766
-                //$payment_source = 'process_ipn';
2767
-            } else {
2768
-                $payment = $this->checkout->transaction->last_payment();
2769
-                //$payment_source = 'last_payment';
2770
-            }
2771
-        } catch (Exception $e) {
2772
-            // let's just eat the exception and try to move on using any previously set payment info
2773
-            $payment = $this->checkout->transaction->last_payment();
2774
-            //$payment_source = 'last_payment after Exception';
2775
-            // but if we STILL don't have a payment object
2776
-            if (! $payment instanceof EE_Payment) {
2777
-                // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778
-                $this->_handle_payment_processor_exception($e);
2779
-            }
2780
-        }
2781
-        // DEBUG LOG
2782
-        //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2783
-        //	array(
2784
-        //		'process_ipn_payment' => $payment,
2785
-        //		'payment_source'      => $payment_source,
2786
-        //	)
2787
-        //);
2788
-        return $payment;
2789
-    }
2790
-
2791
-
2792
-    /**
2793
-     * _process_cancelled_payments
2794
-     * just makes sure that the payment status gets updated correctly
2795
-     * so tha tan error isn't generated during payment validation
2796
-     *
2797
-     * @access private
2798
-     * @param EE_Payment $payment
2799
-     * @return EE_Payment | FALSE
2800
-     * @throws \EE_Error
2801
-     */
2802
-    private function _process_cancelled_payments($payment = null)
2803
-    {
2804
-        if (
2805
-            $payment instanceof EE_Payment
2806
-            && isset($_REQUEST['ee_cancel_payment'])
2807
-            && $payment->status() === EEM_Payment::status_id_failed
2808
-        ) {
2809
-            $payment->set_status(EEM_Payment::status_id_cancelled);
2810
-        }
2811
-        return $payment;
2812
-    }
2813
-
2814
-
2815
-    /**
2816
-     *    get_transaction_details_for_gateways
2817
-     *
2818
-     * @access    public
2819
-     * @return int
2820
-     * @throws EE_Error
2821
-     * @throws InvalidArgumentException
2822
-     * @throws ReflectionException
2823
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2824
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2825
-     */
2826
-    public function get_transaction_details_for_gateways()
2827
-    {
2828
-        $txn_details = array();
2829
-        // ya gotta make a choice man
2830
-        if (empty($this->checkout->selected_method_of_payment)) {
2831
-            $txn_details = array(
2832
-                'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2833
-            );
2834
-        }
2835
-        // get EE_Payment_Method object
2836
-        if (
2837
-            empty($txn_details)
2838
-            &&
2839
-            ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2840
-        ) {
2841
-            $txn_details = array(
2842
-                'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2843
-                'error'                      => esc_html__(
2844
-                    'A valid Payment Method could not be determined.',
2845
-                    'event_espresso'
2846
-                ),
2847
-            );
2848
-        }
2849
-        if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2850
-            $return_url  = $this->_get_return_url($this->checkout->payment_method);
2851
-            $txn_details = array(
2852
-                'TXN_ID'         => $this->checkout->transaction->ID(),
2853
-                'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2854
-                'TXN_total'      => $this->checkout->transaction->total(),
2855
-                'TXN_paid'       => $this->checkout->transaction->paid(),
2856
-                'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2857
-                'STS_ID'         => $this->checkout->transaction->status_ID(),
2858
-                'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2859
-                'payment_amount' => $this->checkout->amount_owing,
2860
-                'return_url'     => $return_url,
2861
-                'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2862
-                'notify_url'     => EE_Config::instance()->core->txn_page_url(
2863
-                    array(
2864
-                        'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2865
-                        'ee_payment_method' => $this->checkout->payment_method->slug(),
2866
-                    )
2867
-                ),
2868
-            );
2869
-        }
2870
-        echo wp_json_encode($txn_details);
2871
-        exit();
2872
-    }
2873
-
2874
-
2875
-    /**
2876
-     *    __sleep
2877
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2878
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2879
-     * reg form, because if needed, it will be regenerated anyways
2880
-     *
2881
-     * @return array
2882
-     */
2883
-    public function __sleep()
2884
-    {
2885
-        // remove the reg form and the checkout
2886
-        return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2887
-    }
18
+	/**
19
+	 * @access protected
20
+	 * @var EE_Line_Item_Display $Line_Item_Display
21
+	 */
22
+	protected $line_item_display;
23
+
24
+	/**
25
+	 * @access protected
26
+	 * @var boolean $handle_IPN_in_this_request
27
+	 */
28
+	protected $handle_IPN_in_this_request = false;
29
+
30
+
31
+	/**
32
+	 *    set_hooks - for hooking into EE Core, other modules, etc
33
+	 *
34
+	 * @access    public
35
+	 * @return    void
36
+	 */
37
+	public static function set_hooks()
38
+	{
39
+		add_filter(
40
+			'FHEE__SPCO__EE_Line_Item_Filter_Collection',
41
+			array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
42
+		);
43
+		add_action(
44
+			'wp_ajax_switch_spco_billing_form',
45
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
46
+		);
47
+		add_action(
48
+			'wp_ajax_nopriv_switch_spco_billing_form',
49
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
50
+		);
51
+		add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
52
+		add_action(
53
+			'wp_ajax_nopriv_save_payer_details',
54
+			array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
55
+		);
56
+		add_action(
57
+			'wp_ajax_get_transaction_details_for_gateways',
58
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
59
+		);
60
+		add_action(
61
+			'wp_ajax_nopriv_get_transaction_details_for_gateways',
62
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
63
+		);
64
+		add_filter(
65
+			'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
66
+			array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
67
+			10,
68
+			1
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 *    ajax switch_spco_billing_form
75
+	 *
76
+	 * @throws \EE_Error
77
+	 */
78
+	public static function switch_spco_billing_form()
79
+	{
80
+		EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
81
+	}
82
+
83
+
84
+	/**
85
+	 *    ajax save_payer_details
86
+	 *
87
+	 * @throws \EE_Error
88
+	 */
89
+	public static function save_payer_details()
90
+	{
91
+		EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
+	}
93
+
94
+
95
+	/**
96
+	 *    ajax get_transaction_details
97
+	 *
98
+	 * @throws \EE_Error
99
+	 */
100
+	public static function get_transaction_details()
101
+	{
102
+		EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
103
+	}
104
+
105
+
106
+	/**
107
+	 * bypass_recaptcha_for_load_payment_method
108
+	 *
109
+	 * @access public
110
+	 * @return array
111
+	 * @throws InvalidArgumentException
112
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
113
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
114
+	 */
115
+	public static function bypass_recaptcha_for_load_payment_method()
116
+	{
117
+		return array(
118
+			'EESID'  => EE_Registry::instance()->SSN->id(),
119
+			'step'   => 'payment_options',
120
+			'action' => 'spco_billing_form',
121
+		);
122
+	}
123
+
124
+
125
+	/**
126
+	 *    class constructor
127
+	 *
128
+	 * @access    public
129
+	 * @param    EE_Checkout $checkout
130
+	 */
131
+	public function __construct(EE_Checkout $checkout)
132
+	{
133
+		$this->_slug     = 'payment_options';
134
+		$this->_name     = esc_html__('Payment Options', 'event_espresso');
135
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'payment_options_main.template.php';
136
+		$this->checkout  = $checkout;
137
+		$this->_reset_success_message();
138
+		$this->set_instructions(
139
+			esc_html__(
140
+				'Please select a method of payment and provide any necessary billing information before proceeding.',
141
+				'event_espresso'
142
+			)
143
+		);
144
+	}
145
+
146
+
147
+	/**
148
+	 * @return null
149
+	 */
150
+	public function line_item_display()
151
+	{
152
+		return $this->line_item_display;
153
+	}
154
+
155
+
156
+	/**
157
+	 * @param null $line_item_display
158
+	 */
159
+	public function set_line_item_display($line_item_display)
160
+	{
161
+		$this->line_item_display = $line_item_display;
162
+	}
163
+
164
+
165
+	/**
166
+	 * @return boolean
167
+	 */
168
+	public function handle_IPN_in_this_request()
169
+	{
170
+		return $this->handle_IPN_in_this_request;
171
+	}
172
+
173
+
174
+	/**
175
+	 * @param boolean $handle_IPN_in_this_request
176
+	 */
177
+	public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
+	{
179
+		$this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
+	}
181
+
182
+
183
+	/**
184
+	 * translate_js_strings
185
+	 *
186
+	 * @return void
187
+	 */
188
+	public function translate_js_strings()
189
+	{
190
+		EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
+			'Please select a method of payment in order to continue.',
192
+			'event_espresso'
193
+		);
194
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
+			'A valid method of payment could not be determined. Please refresh the page and try again.',
196
+			'event_espresso'
197
+		);
198
+		EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
+			'Forwarding to Secure Payment Provider.',
200
+			'event_espresso'
201
+		);
202
+	}
203
+
204
+
205
+	/**
206
+	 * enqueue_styles_and_scripts
207
+	 *
208
+	 * @return void
209
+	 * @throws EE_Error
210
+	 * @throws InvalidArgumentException
211
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
212
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
213
+	 */
214
+	public function enqueue_styles_and_scripts()
215
+	{
216
+		$transaction = $this->checkout->transaction;
217
+		//if the transaction isn't set or nothing is owed on it, don't enqueue any JS
218
+		if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
219
+			return;
220
+		}
221
+		foreach (EEM_Payment_Method::instance()->get_all_for_transaction($transaction, EEM_Payment_Method::scope_cart) as $payment_method) {
222
+			$type_obj = $payment_method->type_obj();
223
+			if ($type_obj instanceof EE_PMT_Base) {
224
+				$billing_form = $type_obj->generate_new_billing_form($transaction);
225
+				if ($billing_form instanceof EE_Form_Section_Proper) {
226
+					$billing_form->enqueue_js();
227
+				}
228
+			}
229
+		}
230
+	}
231
+
232
+
233
+	/**
234
+	 * initialize_reg_step
235
+	 *
236
+	 * @return bool
237
+	 * @throws EE_Error
238
+	 * @throws InvalidArgumentException
239
+	 * @throws ReflectionException
240
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
241
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
242
+	 */
243
+	public function initialize_reg_step()
244
+	{
245
+		// TODO: if /when we implement donations, then this will need overriding
246
+		if (// don't need payment options for:
247
+			// 	registrations made via the admin
248
+			// 	completed transactions
249
+			// 	overpaid transactions
250
+			// 	$ 0.00 transactions (no payment required)
251
+			! $this->checkout->payment_required()
252
+			// but do NOT remove if current action being called belongs to this reg step
253
+			&& ! is_callable(array($this, $this->checkout->action))
254
+			&& ! $this->completed()
255
+		) {
256
+			// and if so, then we no longer need the Payment Options step
257
+			if ($this->is_current_step()) {
258
+				$this->checkout->generate_reg_form = false;
259
+			}
260
+			$this->checkout->remove_reg_step($this->_slug);
261
+			// DEBUG LOG
262
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
263
+			return false;
264
+		}
265
+		// load EEM_Payment_Method
266
+		EE_Registry::instance()->load_model('Payment_Method');
267
+		// get all active payment methods
268
+		$this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
269
+			$this->checkout->transaction,
270
+			EEM_Payment_Method::scope_cart
271
+		);
272
+		return true;
273
+	}
274
+
275
+
276
+	/**
277
+	 * @return EE_Form_Section_Proper
278
+	 * @throws EE_Error
279
+	 * @throws InvalidArgumentException
280
+	 * @throws ReflectionException
281
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
282
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
283
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
284
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
285
+	 */
286
+	public function generate_reg_form()
287
+	{
288
+		// reset in case someone changes their mind
289
+		$this->_reset_selected_method_of_payment();
290
+		// set some defaults
291
+		$this->checkout->selected_method_of_payment = 'payments_closed';
292
+		$registrations_requiring_payment            = array();
293
+		$registrations_for_free_events              = array();
294
+		$registrations_requiring_pre_approval       = array();
295
+		$sold_out_events                            = array();
296
+		$insufficient_spaces_available              = array();
297
+		$no_payment_required                        = true;
298
+		// loop thru registrations to gather info
299
+		$registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
300
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
301
+			$registrations,
302
+			$this->checkout->revisit
303
+		);
304
+		foreach ($registrations as $REG_ID => $registration) {
305
+			/** @var $registration EE_Registration */
306
+			// has this registration lost it's space ?
307
+			if (isset($ejected_registrations[ $REG_ID ])) {
308
+				if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
309
+					$sold_out_events[ $registration->event()->ID() ] = $registration->event();
310
+				} else {
311
+					$insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
312
+				}
313
+				continue;
314
+			}
315
+			// event requires admin approval
316
+			if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
317
+				// add event to list of events with pre-approval reg status
318
+				$registrations_requiring_pre_approval[$REG_ID] = $registration;
319
+				do_action(
320
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
321
+					$registration->event(),
322
+					$this
323
+				);
324
+				continue;
325
+			}
326
+			if ($this->checkout->revisit
327
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
328
+				&& (
329
+					$registration->event()->is_sold_out()
330
+					|| $registration->event()->is_sold_out(true)
331
+				)
332
+			) {
333
+				// add event to list of events that are sold out
334
+				$sold_out_events[$registration->event()->ID()] = $registration->event();
335
+				do_action(
336
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
337
+					$registration->event(),
338
+					$this
339
+				);
340
+				continue;
341
+			}
342
+			// are they allowed to pay now and is there monies owing?
343
+			if ($registration->owes_monies_and_can_pay()) {
344
+				$registrations_requiring_payment[$REG_ID] = $registration;
345
+				do_action(
346
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
347
+					$registration->event(),
348
+					$this
349
+				);
350
+			} elseif (! $this->checkout->revisit
351
+				&& $registration->status_ID() !== EEM_Registration::status_id_not_approved
352
+				&& $registration->ticket()->is_free()
353
+			) {
354
+				$registrations_for_free_events[$registration->event()->ID()] = $registration;
355
+			}
356
+		}
357
+		$subsections = array();
358
+		// now decide which template to load
359
+		if (! empty($sold_out_events)) {
360
+			$subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
361
+		}
362
+		if (! empty($insufficient_spaces_available)) {
363
+			$subsections['insufficient_space'] = $this->_insufficient_spaces_available(
364
+				$insufficient_spaces_available
365
+			);
366
+		}
367
+		if (! empty($registrations_requiring_pre_approval)) {
368
+			$subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
369
+				$registrations_requiring_pre_approval
370
+			);
371
+		}
372
+		if (! empty($registrations_for_free_events)) {
373
+			$subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
374
+		}
375
+		if (! empty($registrations_requiring_payment)) {
376
+			if ($this->checkout->amount_owing > 0) {
377
+				// autoload Line_Item_Display classes
378
+				EEH_Autoloader::register_line_item_filter_autoloaders();
379
+				$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
380
+					apply_filters(
381
+						'FHEE__SPCO__EE_Line_Item_Filter_Collection',
382
+						new EE_Line_Item_Filter_Collection()
383
+					),
384
+					$this->checkout->cart->get_grand_total()
385
+				);
386
+				/** @var EE_Line_Item $filtered_line_item_tree */
387
+				$filtered_line_item_tree = $line_item_filter_processor->process();
388
+				EEH_Autoloader::register_line_item_display_autoloaders();
389
+				$this->set_line_item_display(new EE_Line_Item_Display('spco'));
390
+				$subsections['payment_options'] = $this->_display_payment_options(
391
+					$this->line_item_display->display_line_item(
392
+						$filtered_line_item_tree,
393
+						array('registrations' => $registrations)
394
+					)
395
+				);
396
+				$this->checkout->amount_owing   = $filtered_line_item_tree->total();
397
+				$this->_apply_registration_payments_to_amount_owing($registrations);
398
+			}
399
+			$no_payment_required = false;
400
+		} else {
401
+			$this->_hide_reg_step_submit_button_if_revisit();
402
+		}
403
+		$this->_save_selected_method_of_payment();
404
+
405
+		$subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
406
+		$subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
407
+
408
+		return new EE_Form_Section_Proper(
409
+			array(
410
+				'name'            => $this->reg_form_name(),
411
+				'html_id'         => $this->reg_form_name(),
412
+				'subsections'     => $subsections,
413
+				'layout_strategy' => new EE_No_Layout(),
414
+			)
415
+		);
416
+	}
417
+
418
+
419
+	/**
420
+	 * add line item filters required for this reg step
421
+	 * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
422
+	 *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
423
+	 *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
424
+	 *        payment options reg step, can apply these filters via the following: apply_filters(
425
+	 *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
426
+	 *        filter collection by passing that instead of instantiating a new collection
427
+	 *
428
+	 * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
429
+	 * @return EE_Line_Item_Filter_Collection
430
+	 * @throws EE_Error
431
+	 * @throws InvalidArgumentException
432
+	 * @throws ReflectionException
433
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
434
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
435
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
436
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
437
+	 */
438
+	public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
439
+	{
440
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
441
+			return $line_item_filter_collection;
442
+		}
443
+		if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
444
+			return $line_item_filter_collection;
445
+		}
446
+		if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
447
+			return $line_item_filter_collection;
448
+		}
449
+		$line_item_filter_collection->add(
450
+			new EE_Billable_Line_Item_Filter(
451
+				EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
452
+					EE_Registry::instance()->SSN->checkout()->transaction->registrations(
453
+						EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
454
+					)
455
+				)
456
+			)
457
+		);
458
+		$line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
459
+		return $line_item_filter_collection;
460
+	}
461
+
462
+
463
+	/**
464
+	 * remove_ejected_registrations
465
+	 * if a registrant has lost their potential space at an event due to lack of payment,
466
+	 * then this method removes them from the list of registrations being paid for during this request
467
+	 *
468
+	 * @param \EE_Registration[] $registrations
469
+	 * @return EE_Registration[]
470
+	 * @throws EE_Error
471
+	 * @throws InvalidArgumentException
472
+	 * @throws ReflectionException
473
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
474
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
475
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
476
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
477
+	 */
478
+	public static function remove_ejected_registrations(array $registrations)
479
+	{
480
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
481
+			$registrations,
482
+			EE_Registry::instance()->SSN->checkout()->revisit
483
+		);
484
+		foreach ($registrations as $REG_ID => $registration) {
485
+			// has this registration lost it's space ?
486
+			if (isset($ejected_registrations[$REG_ID])) {
487
+				unset($registrations[$REG_ID]);
488
+				continue;
489
+			}
490
+		}
491
+		return $registrations;
492
+	}
493
+
494
+
495
+	/**
496
+	 * find_registrations_that_lost_their_space
497
+	 * If a registrant chooses an offline payment method like Invoice,
498
+	 * then no space is reserved for them at the event until they fully pay fo that site
499
+	 * (unless the event's default reg status is set to APPROVED)
500
+	 * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
501
+	 * then this method will determine which registrations have lost the ability to complete the reg process.
502
+	 *
503
+	 * @param \EE_Registration[] $registrations
504
+	 * @param bool               $revisit
505
+	 * @return array
506
+	 * @throws EE_Error
507
+	 * @throws InvalidArgumentException
508
+	 * @throws ReflectionException
509
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
510
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
511
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
512
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
513
+	 */
514
+	public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
515
+	{
516
+		// registrations per event
517
+		$event_reg_count = array();
518
+		// spaces left per event
519
+		$event_spaces_remaining = array();
520
+		// tickets left sorted by ID
521
+		$tickets_remaining = array();
522
+		// registrations that have lost their space
523
+		$ejected_registrations = array();
524
+		foreach ($registrations as $REG_ID => $registration) {
525
+			if ($registration->status_ID() === EEM_Registration::status_id_approved
526
+				|| apply_filters(
527
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
528
+					false,
529
+					$registration,
530
+					$revisit
531
+				)
532
+			) {
533
+				continue;
534
+			}
535
+			$EVT_ID = $registration->event_ID();
536
+			$ticket = $registration->ticket();
537
+			if (! isset($tickets_remaining[$ticket->ID()])) {
538
+				$tickets_remaining[$ticket->ID()] = $ticket->remaining();
539
+			}
540
+			if ($tickets_remaining[$ticket->ID()] > 0) {
541
+				if (! isset($event_reg_count[$EVT_ID])) {
542
+					$event_reg_count[$EVT_ID] = 0;
543
+				}
544
+				$event_reg_count[$EVT_ID]++;
545
+				if (! isset($event_spaces_remaining[$EVT_ID])) {
546
+					$event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
547
+				}
548
+			}
549
+			if ($revisit
550
+				&& ($tickets_remaining[$ticket->ID()] === 0
551
+					|| $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
552
+				)
553
+			) {
554
+				$ejected_registrations[$REG_ID] = $registration->event();
555
+				if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
556
+					/** @type EE_Registration_Processor $registration_processor */
557
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
558
+					// at this point, we should have enough details about the registrant to consider the registration
559
+					// NOT incomplete
560
+					$registration_processor->manually_update_registration_status(
561
+						$registration,
562
+						EEM_Registration::status_id_wait_list
563
+					);
564
+				}
565
+			}
566
+		}
567
+		return $ejected_registrations;
568
+	}
569
+
570
+
571
+	/**
572
+	 * _hide_reg_step_submit_button
573
+	 * removes the html for the reg step submit button
574
+	 * by replacing it with an empty string via filter callback
575
+	 *
576
+	 * @return void
577
+	 */
578
+	protected function _adjust_registration_status_if_event_old_sold()
579
+	{
580
+	}
581
+
582
+
583
+	/**
584
+	 * _hide_reg_step_submit_button
585
+	 * removes the html for the reg step submit button
586
+	 * by replacing it with an empty string via filter callback
587
+	 *
588
+	 * @return void
589
+	 */
590
+	protected function _hide_reg_step_submit_button_if_revisit()
591
+	{
592
+		if ($this->checkout->revisit) {
593
+			add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
594
+		}
595
+	}
596
+
597
+
598
+	/**
599
+	 * sold_out_events
600
+	 * displays notices regarding events that have sold out since hte registrant first signed up
601
+	 *
602
+	 * @param \EE_Event[] $sold_out_events_array
603
+	 * @return \EE_Form_Section_Proper
604
+	 * @throws \EE_Error
605
+	 */
606
+	private function _sold_out_events($sold_out_events_array = array())
607
+	{
608
+		// set some defaults
609
+		$this->checkout->selected_method_of_payment = 'events_sold_out';
610
+		$sold_out_events                            = '';
611
+		foreach ($sold_out_events_array as $sold_out_event) {
612
+			$sold_out_events .= EEH_HTML::li(
613
+				EEH_HTML::span(
614
+					'  ' . $sold_out_event->name(),
615
+					'',
616
+					'dashicons dashicons-marker ee-icon-size-16 pink-text'
617
+				)
618
+			);
619
+		}
620
+		return new EE_Form_Section_Proper(
621
+			array(
622
+				'layout_strategy' => new EE_Template_Layout(
623
+					array(
624
+						'layout_template_file' => SPCO_REG_STEPS_PATH
625
+												  . $this->_slug
626
+												  . DS
627
+												  . 'sold_out_events.template.php',
628
+						'template_args'        => apply_filters(
629
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
630
+							array(
631
+								'sold_out_events'     => $sold_out_events,
632
+								'sold_out_events_msg' => apply_filters(
633
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
634
+									sprintf(
635
+										esc_html__(
636
+											'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
637
+											'event_espresso'
638
+										),
639
+										'<strong>',
640
+										'</strong>',
641
+										'<br />'
642
+									)
643
+								),
644
+							)
645
+						),
646
+					)
647
+				),
648
+			)
649
+		);
650
+	}
651
+
652
+
653
+	/**
654
+	 * _insufficient_spaces_available
655
+	 * displays notices regarding events that do not have enough remaining spaces
656
+	 * to satisfy the current number of registrations looking to pay
657
+	 *
658
+	 * @param \EE_Event[] $insufficient_spaces_events_array
659
+	 * @return \EE_Form_Section_Proper
660
+	 * @throws \EE_Error
661
+	 */
662
+	private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
663
+	{
664
+		// set some defaults
665
+		$this->checkout->selected_method_of_payment = 'invoice';
666
+		$insufficient_space_events                  = '';
667
+		foreach ($insufficient_spaces_events_array as $event) {
668
+			if ($event instanceof EE_Event) {
669
+				$insufficient_space_events .= EEH_HTML::li(
670
+					EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
671
+				);
672
+			}
673
+		}
674
+		return new EE_Form_Section_Proper(
675
+			array(
676
+				'subsections'     => array(
677
+					'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
678
+					'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
679
+				),
680
+				'layout_strategy' => new EE_Template_Layout(
681
+					array(
682
+						'layout_template_file' => SPCO_REG_STEPS_PATH
683
+												  . $this->_slug
684
+												  . DS
685
+												  . 'sold_out_events.template.php',
686
+						'template_args'        => apply_filters(
687
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
688
+							array(
689
+								'sold_out_events'     => $insufficient_space_events,
690
+								'sold_out_events_msg' => apply_filters(
691
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
692
+									esc_html__(
693
+										'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
694
+										'event_espresso'
695
+									)
696
+								),
697
+							)
698
+						),
699
+					)
700
+				),
701
+			)
702
+		);
703
+	}
704
+
705
+
706
+	/**
707
+	 * registrations_requiring_pre_approval
708
+	 *
709
+	 * @param array $registrations_requiring_pre_approval
710
+	 * @return EE_Form_Section_Proper
711
+	 * @throws EE_Error
712
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
713
+	 */
714
+	private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
715
+	{
716
+		$events_requiring_pre_approval = '';
717
+		foreach ($registrations_requiring_pre_approval as $registration) {
718
+			if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
719
+				$events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
720
+					EEH_HTML::span(
721
+						'',
722
+						'',
723
+						'dashicons dashicons-marker ee-icon-size-16 orange-text'
724
+					)
725
+					. EEH_HTML::span($registration->event()->name(), '', 'orange-text')
726
+				);
727
+			}
728
+		}
729
+		return new EE_Form_Section_Proper(
730
+			array(
731
+				'layout_strategy' => new EE_Template_Layout(
732
+					array(
733
+						'layout_template_file' => SPCO_REG_STEPS_PATH
734
+												  . $this->_slug
735
+												  . DS
736
+												  . 'events_requiring_pre_approval.template.php', // layout_template
737
+						'template_args'        => apply_filters(
738
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
739
+							array(
740
+								'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
741
+								'events_requiring_pre_approval_msg' => apply_filters(
742
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
743
+									esc_html__(
744
+										'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
745
+										'event_espresso'
746
+									)
747
+								),
748
+							)
749
+						),
750
+					)
751
+				),
752
+			)
753
+		);
754
+	}
755
+
756
+
757
+	/**
758
+	 * _no_payment_required
759
+	 *
760
+	 * @param \EE_Event[] $registrations_for_free_events
761
+	 * @return \EE_Form_Section_Proper
762
+	 * @throws \EE_Error
763
+	 */
764
+	private function _no_payment_required($registrations_for_free_events = array())
765
+	{
766
+		// set some defaults
767
+		$this->checkout->selected_method_of_payment = 'no_payment_required';
768
+		// generate no_payment_required form
769
+		return new EE_Form_Section_Proper(
770
+			array(
771
+				'layout_strategy' => new EE_Template_Layout(
772
+					array(
773
+						'layout_template_file' => SPCO_REG_STEPS_PATH
774
+												  . $this->_slug
775
+												  . DS
776
+												  . 'no_payment_required.template.php', // layout_template
777
+						'template_args'        => apply_filters(
778
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
779
+							array(
780
+								'revisit'                       => $this->checkout->revisit,
781
+								'registrations'                 => array(),
782
+								'ticket_count'                  => array(),
783
+								'registrations_for_free_events' => $registrations_for_free_events,
784
+								'no_payment_required_msg'       => EEH_HTML::p(
785
+									esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
786
+								),
787
+							)
788
+						),
789
+					)
790
+				),
791
+			)
792
+		);
793
+	}
794
+
795
+
796
+	/**
797
+	 * _display_payment_options
798
+	 *
799
+	 * @param string $transaction_details
800
+	 * @return EE_Form_Section_Proper
801
+	 * @throws EE_Error
802
+	 * @throws InvalidArgumentException
803
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
804
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
805
+	 */
806
+	private function _display_payment_options($transaction_details = '')
807
+	{
808
+		// has method_of_payment been set by no-js user?
809
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
810
+		// build payment options form
811
+		return apply_filters(
812
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
813
+			new EE_Form_Section_Proper(
814
+				array(
815
+					'subsections'     => array(
816
+						'before_payment_options' => apply_filters(
817
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
818
+							new EE_Form_Section_Proper(
819
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
820
+							)
821
+						),
822
+						'payment_options'        => $this->_setup_payment_options(),
823
+						'after_payment_options'  => apply_filters(
824
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
825
+							new EE_Form_Section_Proper(
826
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
827
+							)
828
+						),
829
+					),
830
+					'layout_strategy' => new EE_Template_Layout(
831
+						array(
832
+							'layout_template_file' => $this->_template,
833
+							'template_args'        => apply_filters(
834
+								'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
835
+								array(
836
+									'reg_count'                 => $this->line_item_display->total_items(),
837
+									'transaction_details'       => $transaction_details,
838
+									'available_payment_methods' => array(),
839
+								)
840
+							),
841
+						)
842
+					),
843
+				)
844
+			)
845
+		);
846
+	}
847
+
848
+
849
+	/**
850
+	 * _extra_hidden_inputs
851
+	 *
852
+	 * @param bool $no_payment_required
853
+	 * @return \EE_Form_Section_Proper
854
+	 * @throws \EE_Error
855
+	 */
856
+	private function _extra_hidden_inputs($no_payment_required = true)
857
+	{
858
+		return new EE_Form_Section_Proper(
859
+			array(
860
+				'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
861
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
862
+				'subsections'     => array(
863
+					'spco_no_payment_required' => new EE_Hidden_Input(
864
+						array(
865
+							'normalization_strategy' => new EE_Boolean_Normalization(),
866
+							'html_name'              => 'spco_no_payment_required',
867
+							'html_id'                => 'spco-no-payment-required-payment_options',
868
+							'default'                => $no_payment_required,
869
+						)
870
+					),
871
+					'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
872
+						array(
873
+							'normalization_strategy' => new EE_Int_Normalization(),
874
+							'html_name'              => 'spco_transaction_id',
875
+							'html_id'                => 'spco-transaction-id',
876
+							'default'                => $this->checkout->transaction->ID(),
877
+						)
878
+					),
879
+				),
880
+			)
881
+		);
882
+	}
883
+
884
+
885
+	/**
886
+	 *    _apply_registration_payments_to_amount_owing
887
+	 *
888
+	 * @access protected
889
+	 * @param array $registrations
890
+	 * @throws EE_Error
891
+	 */
892
+	protected function _apply_registration_payments_to_amount_owing(array $registrations)
893
+	{
894
+		$payments = array();
895
+		foreach ($registrations as $registration) {
896
+			if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
897
+				$payments += $registration->registration_payments();
898
+			}
899
+		}
900
+		if (! empty($payments)) {
901
+			foreach ($payments as $payment) {
902
+				if ($payment instanceof EE_Registration_Payment) {
903
+					$this->checkout->amount_owing -= $payment->amount();
904
+				}
905
+			}
906
+		}
907
+	}
908
+
909
+
910
+	/**
911
+	 *    _reset_selected_method_of_payment
912
+	 *
913
+	 * @access    private
914
+	 * @param    bool $force_reset
915
+	 * @return void
916
+	 * @throws InvalidArgumentException
917
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
918
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
919
+	 */
920
+	private function _reset_selected_method_of_payment($force_reset = false)
921
+	{
922
+		$reset_payment_method = $force_reset
923
+			? true
924
+			: sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
925
+		if ($reset_payment_method) {
926
+			$this->checkout->selected_method_of_payment = null;
927
+			$this->checkout->payment_method             = null;
928
+			$this->checkout->billing_form               = null;
929
+			$this->_save_selected_method_of_payment();
930
+		}
931
+	}
932
+
933
+
934
+	/**
935
+	 * _save_selected_method_of_payment
936
+	 * stores the selected_method_of_payment in the session
937
+	 * so that it's available for all subsequent requests including AJAX
938
+	 *
939
+	 * @access        private
940
+	 * @param string $selected_method_of_payment
941
+	 * @return void
942
+	 * @throws InvalidArgumentException
943
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
944
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
945
+	 */
946
+	private function _save_selected_method_of_payment($selected_method_of_payment = '')
947
+	{
948
+		$selected_method_of_payment = ! empty($selected_method_of_payment)
949
+			? $selected_method_of_payment
950
+			: $this->checkout->selected_method_of_payment;
951
+		EE_Registry::instance()->SSN->set_session_data(
952
+			array('selected_method_of_payment' => $selected_method_of_payment)
953
+		);
954
+	}
955
+
956
+
957
+	/**
958
+	 * _setup_payment_options
959
+	 *
960
+	 * @return EE_Form_Section_Proper
961
+	 * @throws EE_Error
962
+	 * @throws InvalidArgumentException
963
+	 * @throws ReflectionException
964
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
965
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
966
+	 */
967
+	public function _setup_payment_options()
968
+	{
969
+		// load payment method classes
970
+		$this->checkout->available_payment_methods = $this->_get_available_payment_methods();
971
+		if (empty($this->checkout->available_payment_methods)) {
972
+			EE_Error::add_error(
973
+				apply_filters(
974
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
975
+					sprintf(
976
+						esc_html__(
977
+							'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
978
+							'event_espresso'
979
+						),
980
+						'<br>',
981
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
982
+					)
983
+				),
984
+				__FILE__,
985
+				__FUNCTION__,
986
+				__LINE__
987
+			);
988
+		}
989
+		// switch up header depending on number of available payment methods
990
+		$payment_method_header     = count($this->checkout->available_payment_methods) > 1
991
+			? apply_filters(
992
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
993
+				esc_html__('Please Select Your Method of Payment', 'event_espresso')
994
+			)
995
+			: apply_filters(
996
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
997
+				esc_html__('Method of Payment', 'event_espresso')
998
+			);
999
+		$available_payment_methods = array(
1000
+			// display the "Payment Method" header
1001
+			'payment_method_header' => new EE_Form_Section_HTML(
1002
+				EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr')
1003
+			),
1004
+		);
1005
+		// the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1006
+		$available_payment_method_options = array();
1007
+		$default_payment_method_option    = array();
1008
+		// additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1009
+		$payment_methods_billing_info = array(
1010
+			new EE_Form_Section_HTML(
1011
+				EEH_HTML::div('<br />', '', '', 'clear:both;')
1012
+			),
1013
+		);
1014
+		// loop through payment methods
1015
+		foreach ($this->checkout->available_payment_methods as $payment_method) {
1016
+			if ($payment_method instanceof EE_Payment_Method) {
1017
+				$payment_method_button = EEH_HTML::img(
1018
+					$payment_method->button_url(),
1019
+					$payment_method->name(),
1020
+					'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1021
+					'spco-payment-method-btn-img'
1022
+				);
1023
+				// check if any payment methods are set as default
1024
+				// if payment method is already selected OR nothing is selected and this payment method should be
1025
+				// open_by_default
1026
+				if (($this->checkout->selected_method_of_payment === $payment_method->slug())
1027
+					|| (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1028
+				) {
1029
+					$this->checkout->selected_method_of_payment = $payment_method->slug();
1030
+					$this->_save_selected_method_of_payment();
1031
+					$default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1032
+				} else {
1033
+					$available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1034
+				}
1035
+				$payment_methods_billing_info[$payment_method->slug() . '-info'] = $this->_payment_method_billing_info(
1036
+					$payment_method
1037
+				);
1038
+			}
1039
+		}
1040
+		// prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1041
+		// of PMs
1042
+		$available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1043
+		// now generate the actual form  inputs
1044
+		$available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1045
+			$available_payment_method_options
1046
+		);
1047
+		$available_payment_methods                              += $payment_methods_billing_info;
1048
+		// build the available payment methods form
1049
+		return new EE_Form_Section_Proper(
1050
+			array(
1051
+				'html_id'         => 'spco-available-methods-of-payment-dv',
1052
+				'subsections'     => $available_payment_methods,
1053
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1054
+			)
1055
+		);
1056
+	}
1057
+
1058
+
1059
+	/**
1060
+	 * _get_available_payment_methods
1061
+	 *
1062
+	 * @return EE_Payment_Method[]
1063
+	 * @throws EE_Error
1064
+	 * @throws InvalidArgumentException
1065
+	 * @throws ReflectionException
1066
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1067
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1068
+	 */
1069
+	protected function _get_available_payment_methods()
1070
+	{
1071
+		if (! empty($this->checkout->available_payment_methods)) {
1072
+			return $this->checkout->available_payment_methods;
1073
+		}
1074
+		$available_payment_methods = array();
1075
+		// load EEM_Payment_Method
1076
+		EE_Registry::instance()->load_model('Payment_Method');
1077
+		/** @type EEM_Payment_Method $EEM_Payment_Method */
1078
+		$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1079
+		// get all active payment methods
1080
+		$payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1081
+			$this->checkout->transaction,
1082
+			EEM_Payment_Method::scope_cart
1083
+		);
1084
+		foreach ($payment_methods as $payment_method) {
1085
+			if ($payment_method instanceof EE_Payment_Method) {
1086
+				$available_payment_methods[$payment_method->slug()] = $payment_method;
1087
+			}
1088
+		}
1089
+		return $available_payment_methods;
1090
+	}
1091
+
1092
+
1093
+	/**
1094
+	 *    _available_payment_method_inputs
1095
+	 *
1096
+	 * @access    private
1097
+	 * @param    array $available_payment_method_options
1098
+	 * @return    \EE_Form_Section_Proper
1099
+	 */
1100
+	private function _available_payment_method_inputs($available_payment_method_options = array())
1101
+	{
1102
+		// generate inputs
1103
+		return new EE_Form_Section_Proper(
1104
+			array(
1105
+				'html_id'         => 'ee-available-payment-method-inputs',
1106
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1107
+				'subsections'     => array(
1108
+					'' => new EE_Radio_Button_Input(
1109
+						$available_payment_method_options,
1110
+						array(
1111
+							'html_name'          => 'selected_method_of_payment',
1112
+							'html_class'         => 'spco-payment-method',
1113
+							'default'            => $this->checkout->selected_method_of_payment,
1114
+							'label_size'         => 11,
1115
+							'enforce_label_size' => true,
1116
+						)
1117
+					),
1118
+				),
1119
+			)
1120
+		);
1121
+	}
1122
+
1123
+
1124
+	/**
1125
+	 *    _payment_method_billing_info
1126
+	 *
1127
+	 * @access    private
1128
+	 * @param    EE_Payment_Method $payment_method
1129
+	 * @return EE_Form_Section_Proper
1130
+	 * @throws EE_Error
1131
+	 * @throws InvalidArgumentException
1132
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1133
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1134
+	 */
1135
+	private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1136
+	{
1137
+		$currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1138
+			? true
1139
+			: false;
1140
+		// generate the billing form for payment method
1141
+		$billing_form                 = $currently_selected
1142
+			? $this->_get_billing_form_for_payment_method($payment_method)
1143
+			: new EE_Form_Section_HTML();
1144
+		$this->checkout->billing_form = $currently_selected
1145
+			? $billing_form
1146
+			: $this->checkout->billing_form;
1147
+		// it's all in the details
1148
+		$info_html = EEH_HTML::h3(
1149
+			esc_html__('Important information regarding your payment', 'event_espresso'),
1150
+			'',
1151
+			'spco-payment-method-hdr'
1152
+		);
1153
+		// add some info regarding the step, either from what's saved in the admin,
1154
+		// or a default string depending on whether the PM has a billing form or not
1155
+		if ($payment_method->description()) {
1156
+			$payment_method_info = $payment_method->description();
1157
+		} elseif ($billing_form instanceof EE_Billing_Info_Form) {
1158
+			$payment_method_info = sprintf(
1159
+				esc_html__(
1160
+					'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1161
+					'event_espresso'
1162
+				),
1163
+				$this->submit_button_text()
1164
+			);
1165
+		} else {
1166
+			$payment_method_info = sprintf(
1167
+				esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1168
+				$this->submit_button_text()
1169
+			);
1170
+		}
1171
+		$info_html .= EEH_HTML::p(
1172
+			apply_filters(
1173
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1174
+				$payment_method_info
1175
+			),
1176
+			'',
1177
+			'spco-payment-method-desc ee-attention'
1178
+		);
1179
+		return new EE_Form_Section_Proper(
1180
+			array(
1181
+				'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1182
+				'html_class'      => 'spco-payment-method-info-dv',
1183
+				// only display the selected or default PM
1184
+				'html_style'      => $currently_selected ? '' : 'display:none;',
1185
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1186
+				'subsections'     => array(
1187
+					'info'         => new EE_Form_Section_HTML($info_html),
1188
+					'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1189
+				),
1190
+			)
1191
+		);
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * get_billing_form_html_for_payment_method
1197
+	 *
1198
+	 * @access public
1199
+	 * @return string
1200
+	 * @throws EE_Error
1201
+	 * @throws InvalidArgumentException
1202
+	 * @throws ReflectionException
1203
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1204
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1205
+	 */
1206
+	public function get_billing_form_html_for_payment_method()
1207
+	{
1208
+		// how have they chosen to pay?
1209
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1210
+		$this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1211
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1212
+			return false;
1213
+		}
1214
+		if (apply_filters(
1215
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1216
+			false
1217
+		)) {
1218
+			EE_Error::add_success(
1219
+				apply_filters(
1220
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1221
+					sprintf(
1222
+						esc_html__(
1223
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1224
+							'event_espresso'
1225
+						),
1226
+						$this->checkout->payment_method->name()
1227
+					)
1228
+				)
1229
+			);
1230
+		}
1231
+		// now generate billing form for selected method of payment
1232
+		$payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1233
+		// fill form with attendee info if applicable
1234
+		if ($payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1235
+			&& $this->checkout->transaction_has_primary_registrant()
1236
+		) {
1237
+			$payment_method_billing_form->populate_from_attendee(
1238
+				$this->checkout->transaction->primary_registration()->attendee()
1239
+			);
1240
+		}
1241
+		// and debug content
1242
+		if ($payment_method_billing_form instanceof EE_Billing_Info_Form
1243
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1244
+		) {
1245
+			$payment_method_billing_form =
1246
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1247
+					$payment_method_billing_form
1248
+				);
1249
+		}
1250
+		$billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1251
+			? $payment_method_billing_form->get_html()
1252
+			: '';
1253
+		$this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1254
+		// localize validation rules for main form
1255
+		$this->checkout->current_step->reg_form->localize_validation_rules();
1256
+		$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1257
+		return true;
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * _get_billing_form_for_payment_method
1263
+	 *
1264
+	 * @access private
1265
+	 * @param EE_Payment_Method $payment_method
1266
+	 * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1267
+	 * @throws EE_Error
1268
+	 * @throws InvalidArgumentException
1269
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1270
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1271
+	 */
1272
+	private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1273
+	{
1274
+		$billing_form = $payment_method->type_obj()->billing_form(
1275
+			$this->checkout->transaction,
1276
+			array('amount_owing' => $this->checkout->amount_owing)
1277
+		);
1278
+		if ($billing_form instanceof EE_Billing_Info_Form) {
1279
+			if (apply_filters(
1280
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1281
+				false
1282
+			)
1283
+				&& EE_Registry::instance()->REQ->is_set('payment_method')
1284
+			) {
1285
+				EE_Error::add_success(
1286
+					apply_filters(
1287
+						'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1288
+						sprintf(
1289
+							esc_html__(
1290
+								'You have selected "%s" as your method of payment. Please note the important payment information below.',
1291
+								'event_espresso'
1292
+							),
1293
+							$payment_method->name()
1294
+						)
1295
+					)
1296
+				);
1297
+			}
1298
+			return apply_filters(
1299
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1300
+				$billing_form,
1301
+				$payment_method
1302
+			);
1303
+		}
1304
+		// no actual billing form, so return empty HTML form section
1305
+		return new EE_Form_Section_HTML();
1306
+	}
1307
+
1308
+
1309
+	/**
1310
+	 * _get_selected_method_of_payment
1311
+	 *
1312
+	 * @access private
1313
+	 * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1314
+	 *                          is not found in the incoming request
1315
+	 * @param string  $request_param
1316
+	 * @return NULL|string
1317
+	 * @throws EE_Error
1318
+	 * @throws InvalidArgumentException
1319
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1320
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1321
+	 */
1322
+	private function _get_selected_method_of_payment(
1323
+		$required = false,
1324
+		$request_param = 'selected_method_of_payment'
1325
+	) {
1326
+		// is selected_method_of_payment set in the request ?
1327
+		$selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1328
+		if ($selected_method_of_payment) {
1329
+			// sanitize it
1330
+			$selected_method_of_payment = is_array($selected_method_of_payment)
1331
+				? array_shift($selected_method_of_payment)
1332
+				: $selected_method_of_payment;
1333
+			$selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1334
+			// store it in the session so that it's available for all subsequent requests including AJAX
1335
+			$this->_save_selected_method_of_payment($selected_method_of_payment);
1336
+		} else {
1337
+			// or is is set in the session ?
1338
+			$selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1339
+				'selected_method_of_payment'
1340
+			);
1341
+		}
1342
+		// do ya really really gotta have it?
1343
+		if (empty($selected_method_of_payment) && $required) {
1344
+			EE_Error::add_error(
1345
+				sprintf(
1346
+					esc_html__(
1347
+						'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1348
+						'event_espresso'
1349
+					),
1350
+					'<br/>',
1351
+					'<br/>',
1352
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
1353
+				),
1354
+				__FILE__,
1355
+				__FUNCTION__,
1356
+				__LINE__
1357
+			);
1358
+			return null;
1359
+		}
1360
+		return $selected_method_of_payment;
1361
+	}
1362
+
1363
+
1364
+
1365
+
1366
+
1367
+
1368
+	/********************************************************************************************************/
1369
+	/***********************************  SWITCH PAYMENT METHOD  ************************************/
1370
+	/********************************************************************************************************/
1371
+	/**
1372
+	 * switch_payment_method
1373
+	 *
1374
+	 * @access public
1375
+	 * @return string
1376
+	 * @throws EE_Error
1377
+	 * @throws InvalidArgumentException
1378
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1379
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1380
+	 */
1381
+	public function switch_payment_method()
1382
+	{
1383
+		if (! $this->_verify_payment_method_is_set()) {
1384
+			return false;
1385
+		}
1386
+		if (apply_filters(
1387
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1388
+			false
1389
+		)) {
1390
+			EE_Error::add_success(
1391
+				apply_filters(
1392
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1393
+					sprintf(
1394
+						esc_html__(
1395
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1396
+							'event_espresso'
1397
+						),
1398
+						$this->checkout->payment_method->name()
1399
+					)
1400
+				)
1401
+			);
1402
+		}
1403
+		// generate billing form for selected method of payment if it hasn't been done already
1404
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1405
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1406
+				$this->checkout->payment_method
1407
+			);
1408
+		}
1409
+		// fill form with attendee info if applicable
1410
+		if (apply_filters(
1411
+			'FHEE__populate_billing_form_fields_from_attendee',
1412
+			(
1413
+				$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1414
+				&& $this->checkout->transaction_has_primary_registrant()
1415
+			),
1416
+			$this->checkout->billing_form,
1417
+			$this->checkout->transaction
1418
+		)
1419
+		) {
1420
+			$this->checkout->billing_form->populate_from_attendee(
1421
+				$this->checkout->transaction->primary_registration()->attendee()
1422
+			);
1423
+		}
1424
+		// and debug content
1425
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form
1426
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1427
+		) {
1428
+			$this->checkout->billing_form =
1429
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1430
+					$this->checkout->billing_form
1431
+				);
1432
+		}
1433
+		// get html and validation rules for form
1434
+		if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1435
+			$this->checkout->json_response->set_return_data(
1436
+				array('payment_method_info' => $this->checkout->billing_form->get_html())
1437
+			);
1438
+			// localize validation rules for main form
1439
+			$this->checkout->billing_form->localize_validation_rules(true);
1440
+			$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1441
+		} else {
1442
+			$this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1443
+		}
1444
+		//prevents advancement to next step
1445
+		$this->checkout->continue_reg = false;
1446
+		return true;
1447
+	}
1448
+
1449
+
1450
+	/**
1451
+	 * _verify_payment_method_is_set
1452
+	 *
1453
+	 * @return bool
1454
+	 * @throws EE_Error
1455
+	 * @throws InvalidArgumentException
1456
+	 * @throws ReflectionException
1457
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1458
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1459
+	 */
1460
+	protected function _verify_payment_method_is_set()
1461
+	{
1462
+		// generate billing form for selected method of payment if it hasn't been done already
1463
+		if (empty($this->checkout->selected_method_of_payment)) {
1464
+			// how have they chosen to pay?
1465
+			$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1466
+		} else {
1467
+			// choose your own adventure based on method_of_payment
1468
+			switch ($this->checkout->selected_method_of_payment) {
1469
+				case 'events_sold_out' :
1470
+					EE_Error::add_attention(
1471
+						apply_filters(
1472
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1473
+							esc_html__(
1474
+								'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1475
+								'event_espresso'
1476
+							)
1477
+						),
1478
+						__FILE__, __FUNCTION__, __LINE__
1479
+					);
1480
+					return false;
1481
+					break;
1482
+				case 'payments_closed' :
1483
+					EE_Error::add_attention(
1484
+						apply_filters(
1485
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1486
+							esc_html__(
1487
+								'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1488
+								'event_espresso'
1489
+							)
1490
+						),
1491
+						__FILE__, __FUNCTION__, __LINE__
1492
+					);
1493
+					return false;
1494
+					break;
1495
+				case 'no_payment_required' :
1496
+					EE_Error::add_attention(
1497
+						apply_filters(
1498
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1499
+							esc_html__(
1500
+								'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1501
+								'event_espresso'
1502
+							)
1503
+						),
1504
+						__FILE__, __FUNCTION__, __LINE__
1505
+					);
1506
+					return false;
1507
+					break;
1508
+				default:
1509
+			}
1510
+		}
1511
+		// verify payment method
1512
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1513
+			// get payment method for selected method of payment
1514
+			$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1515
+		}
1516
+		return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1517
+	}
1518
+
1519
+
1520
+
1521
+	/********************************************************************************************************/
1522
+	/***************************************  SAVE PAYER DETAILS  ****************************************/
1523
+	/********************************************************************************************************/
1524
+	/**
1525
+	 * save_payer_details_via_ajax
1526
+	 *
1527
+	 * @return void
1528
+	 * @throws EE_Error
1529
+	 * @throws InvalidArgumentException
1530
+	 * @throws ReflectionException
1531
+	 * @throws RuntimeException
1532
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1533
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1534
+	 */
1535
+	public function save_payer_details_via_ajax()
1536
+	{
1537
+		if (! $this->_verify_payment_method_is_set()) {
1538
+			return;
1539
+		}
1540
+		// generate billing form for selected method of payment if it hasn't been done already
1541
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1542
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1543
+				$this->checkout->payment_method
1544
+			);
1545
+		}
1546
+		// generate primary attendee from payer info if applicable
1547
+		if (! $this->checkout->transaction_has_primary_registrant()) {
1548
+			$attendee = $this->_create_attendee_from_request_data();
1549
+			if ($attendee instanceof EE_Attendee) {
1550
+				foreach ($this->checkout->transaction->registrations() as $registration) {
1551
+					if ($registration->is_primary_registrant()) {
1552
+						$this->checkout->primary_attendee_obj = $attendee;
1553
+						$registration->_add_relation_to($attendee, 'Attendee');
1554
+						$registration->set_attendee_id($attendee->ID());
1555
+						$registration->update_cache_after_object_save('Attendee', $attendee);
1556
+					}
1557
+				}
1558
+			}
1559
+		}
1560
+	}
1561
+
1562
+
1563
+	/**
1564
+	 * create_attendee_from_request_data
1565
+	 * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1566
+	 *
1567
+	 * @return EE_Attendee
1568
+	 * @throws EE_Error
1569
+	 * @throws InvalidArgumentException
1570
+	 * @throws ReflectionException
1571
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1572
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1573
+	 */
1574
+	protected function _create_attendee_from_request_data()
1575
+	{
1576
+		// get State ID
1577
+		$STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1578
+		if (! empty($STA_ID)) {
1579
+			// can we get state object from name ?
1580
+			EE_Registry::instance()->load_model('State');
1581
+			$state  = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1582
+			$STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1583
+		}
1584
+		// get Country ISO
1585
+		$CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1586
+		if (! empty($CNT_ISO)) {
1587
+			// can we get country object from name ?
1588
+			EE_Registry::instance()->load_model('Country');
1589
+			$country = EEM_Country::instance()->get_col(
1590
+				array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1591
+				'CNT_ISO'
1592
+			);
1593
+			$CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1594
+		}
1595
+		// grab attendee data
1596
+		$attendee_data = array(
1597
+			'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1598
+			'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1599
+			'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1600
+			'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1601
+			'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1602
+			'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1603
+			'STA_ID'       => $STA_ID,
1604
+			'CNT_ISO'      => $CNT_ISO,
1605
+			'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1606
+			'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1607
+		);
1608
+		// validate the email address since it is the most important piece of info
1609
+		if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1610
+			EE_Error::add_error(
1611
+				esc_html__('An invalid email address was submitted.', 'event_espresso'),
1612
+				__FILE__,
1613
+				__FUNCTION__,
1614
+				__LINE__
1615
+			);
1616
+		}
1617
+		// does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1618
+		// AND email address
1619
+		if (! empty($attendee_data['ATT_fname'])
1620
+			&& ! empty($attendee_data['ATT_lname'])
1621
+			&& ! empty($attendee_data['ATT_email'])
1622
+		) {
1623
+			$existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1624
+				array(
1625
+					'ATT_fname' => $attendee_data['ATT_fname'],
1626
+					'ATT_lname' => $attendee_data['ATT_lname'],
1627
+					'ATT_email' => $attendee_data['ATT_email'],
1628
+				)
1629
+			);
1630
+			if ($existing_attendee instanceof EE_Attendee) {
1631
+				return $existing_attendee;
1632
+			}
1633
+		}
1634
+		// no existing attendee? kk let's create a new one
1635
+		// kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1636
+		// don't exist
1637
+		$attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1638
+			? $attendee_data['ATT_fname']
1639
+			: $attendee_data['ATT_email'];
1640
+		$attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1641
+			? $attendee_data['ATT_lname']
1642
+			: $attendee_data['ATT_email'];
1643
+		return EE_Attendee::new_instance($attendee_data);
1644
+	}
1645
+
1646
+
1647
+
1648
+	/********************************************************************************************************/
1649
+	/****************************************  PROCESS REG STEP  *****************************************/
1650
+	/********************************************************************************************************/
1651
+	/**
1652
+	 * process_reg_step
1653
+	 *
1654
+	 * @return bool
1655
+	 * @throws EE_Error
1656
+	 * @throws InvalidArgumentException
1657
+	 * @throws ReflectionException
1658
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1659
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1660
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1661
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1662
+	 */
1663
+	public function process_reg_step()
1664
+	{
1665
+		// how have they chosen to pay?
1666
+		$this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1667
+			? 'no_payment_required'
1668
+			: $this->_get_selected_method_of_payment(true);
1669
+		// choose your own adventure based on method_of_payment
1670
+		switch ($this->checkout->selected_method_of_payment) {
1671
+
1672
+			case 'events_sold_out' :
1673
+				$this->checkout->redirect     = true;
1674
+				$this->checkout->redirect_url = $this->checkout->cancel_page_url;
1675
+				$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1676
+				// mark this reg step as completed
1677
+				$this->set_completed();
1678
+				return false;
1679
+				break;
1680
+
1681
+			case 'payments_closed' :
1682
+				if (apply_filters(
1683
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1684
+					false
1685
+				)) {
1686
+					EE_Error::add_success(
1687
+						esc_html__('no payment required at this time.', 'event_espresso'),
1688
+						__FILE__,
1689
+						__FUNCTION__,
1690
+						__LINE__
1691
+					);
1692
+				}
1693
+				// mark this reg step as completed
1694
+				$this->set_completed();
1695
+				return true;
1696
+				break;
1697
+
1698
+			case 'no_payment_required' :
1699
+				if (apply_filters(
1700
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1701
+					false
1702
+				)) {
1703
+					EE_Error::add_success(
1704
+						esc_html__('no payment required.', 'event_espresso'),
1705
+						__FILE__,
1706
+						__FUNCTION__,
1707
+						__LINE__
1708
+					);
1709
+				}
1710
+				// mark this reg step as completed
1711
+				$this->set_completed();
1712
+				return true;
1713
+				break;
1714
+
1715
+			default:
1716
+				$registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1717
+					EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1718
+				);
1719
+				$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1720
+					$registrations,
1721
+					EE_Registry::instance()->SSN->checkout()->revisit
1722
+				);
1723
+				// calculate difference between the two arrays
1724
+				$registrations = array_diff($registrations, $ejected_registrations);
1725
+				if (empty($registrations)) {
1726
+					$this->_redirect_because_event_sold_out();
1727
+					return false;
1728
+				}
1729
+				$payment_successful = $this->_process_payment();
1730
+				if ($payment_successful) {
1731
+					$this->checkout->continue_reg = true;
1732
+					$this->_maybe_set_completed($this->checkout->payment_method);
1733
+				} else {
1734
+					$this->checkout->continue_reg = false;
1735
+				}
1736
+				return $payment_successful;
1737
+		}
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * _redirect_because_event_sold_out
1743
+	 *
1744
+	 * @access protected
1745
+	 * @return void
1746
+	 */
1747
+	protected function _redirect_because_event_sold_out()
1748
+	{
1749
+		$this->checkout->continue_reg = false;
1750
+		// set redirect URL
1751
+		$this->checkout->redirect_url = add_query_arg(
1752
+			array('e_reg_url_link' => $this->checkout->reg_url_link),
1753
+			$this->checkout->current_step->reg_step_url()
1754
+		);
1755
+		$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1756
+	}
1757
+
1758
+
1759
+	/**
1760
+	 * _maybe_set_completed
1761
+	 *
1762
+	 * @access protected
1763
+	 * @param \EE_Payment_Method $payment_method
1764
+	 * @return void
1765
+	 * @throws \EE_Error
1766
+	 */
1767
+	protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1768
+	{
1769
+		switch ($payment_method->type_obj()->payment_occurs()) {
1770
+			case EE_PMT_Base::offsite :
1771
+				break;
1772
+			case EE_PMT_Base::onsite :
1773
+			case EE_PMT_Base::offline :
1774
+				// mark this reg step as completed
1775
+				$this->set_completed();
1776
+				break;
1777
+		}
1778
+	}
1779
+
1780
+
1781
+	/**
1782
+	 *    update_reg_step
1783
+	 *    this is the final step after a user  revisits the site to retry a payment
1784
+	 *
1785
+	 * @return bool
1786
+	 * @throws EE_Error
1787
+	 * @throws InvalidArgumentException
1788
+	 * @throws ReflectionException
1789
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1790
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1791
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1792
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1793
+	 */
1794
+	public function update_reg_step()
1795
+	{
1796
+		$success = true;
1797
+		// if payment required
1798
+		if ($this->checkout->transaction->total() > 0) {
1799
+			do_action(
1800
+				'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1801
+				$this->checkout->transaction
1802
+			);
1803
+			// attempt payment via payment method
1804
+			$success = $this->process_reg_step();
1805
+		}
1806
+		if ($success && ! $this->checkout->redirect) {
1807
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1808
+				$this->checkout->transaction->ID()
1809
+			);
1810
+			// set return URL
1811
+			$this->checkout->redirect_url = add_query_arg(
1812
+				array('e_reg_url_link' => $this->checkout->reg_url_link),
1813
+				$this->checkout->thank_you_page_url
1814
+			);
1815
+		}
1816
+		return $success;
1817
+	}
1818
+
1819
+
1820
+	/**
1821
+	 *    _process_payment
1822
+	 *
1823
+	 * @access private
1824
+	 * @return bool
1825
+	 * @throws EE_Error
1826
+	 * @throws InvalidArgumentException
1827
+	 * @throws ReflectionException
1828
+	 * @throws RuntimeException
1829
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1830
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1831
+	 */
1832
+	private function _process_payment()
1833
+	{
1834
+		// basically confirm that the event hasn't sold out since they hit the page
1835
+		if (! $this->_last_second_ticket_verifications()) {
1836
+			return false;
1837
+		}
1838
+		// ya gotta make a choice man
1839
+		if (empty($this->checkout->selected_method_of_payment)) {
1840
+			$this->checkout->json_response->set_plz_select_method_of_payment(
1841
+				esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1842
+			);
1843
+			return false;
1844
+		}
1845
+		// get EE_Payment_Method object
1846
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1847
+			return false;
1848
+		}
1849
+		// setup billing form
1850
+		if ($this->checkout->payment_method->is_on_site()) {
1851
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1852
+				$this->checkout->payment_method
1853
+			);
1854
+			// bad billing form ?
1855
+			if (! $this->_billing_form_is_valid()) {
1856
+				return false;
1857
+			}
1858
+		}
1859
+		// ensure primary registrant has been fully processed
1860
+		if (! $this->_setup_primary_registrant_prior_to_payment()) {
1861
+			return false;
1862
+		}
1863
+		// if session is close to expiring (under 10 minutes by default)
1864
+		if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1865
+			// add some time to session expiration so that payment can be completed
1866
+			EE_Registry::instance()->SSN->extend_expiration();
1867
+		}
1868
+		/** @type EE_Transaction_Processor $transaction_processor */
1869
+		//$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1870
+		// in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1871
+		// for events with a default reg status of Approved
1872
+		// $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1873
+		//      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1874
+		// );
1875
+		// attempt payment
1876
+		$payment = $this->_attempt_payment($this->checkout->payment_method);
1877
+		// process results
1878
+		$payment = $this->_validate_payment($payment);
1879
+		$payment = $this->_post_payment_processing($payment);
1880
+		// verify payment
1881
+		if ($payment instanceof EE_Payment) {
1882
+			// store that for later
1883
+			$this->checkout->payment = $payment;
1884
+			// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1885
+			$this->checkout->transaction->toggle_failed_transaction_status();
1886
+			$payment_status = $payment->status();
1887
+			if (
1888
+				$payment_status === EEM_Payment::status_id_approved
1889
+				|| $payment_status === EEM_Payment::status_id_pending
1890
+			) {
1891
+				return true;
1892
+			} else {
1893
+				return false;
1894
+			}
1895
+		} else if ($payment === true) {
1896
+			// please note that offline payment methods will NOT make a payment,
1897
+			// but instead just mark themselves as the PMD_ID on the transaction, and return true
1898
+			$this->checkout->payment = $payment;
1899
+			return true;
1900
+		}
1901
+		// where's my money?
1902
+		return false;
1903
+	}
1904
+
1905
+
1906
+	/**
1907
+	 * _last_second_ticket_verifications
1908
+	 *
1909
+	 * @access public
1910
+	 * @return bool
1911
+	 * @throws EE_Error
1912
+	 */
1913
+	protected function _last_second_ticket_verifications()
1914
+	{
1915
+		// don't bother re-validating if not a return visit
1916
+		if (! $this->checkout->revisit) {
1917
+			return true;
1918
+		}
1919
+		$registrations = $this->checkout->transaction->registrations();
1920
+		if (empty($registrations)) {
1921
+			return false;
1922
+		}
1923
+		foreach ($registrations as $registration) {
1924
+			if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1925
+				$event = $registration->event_obj();
1926
+				if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1927
+					EE_Error::add_error(
1928
+						apply_filters(
1929
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1930
+							sprintf(
1931
+								esc_html__(
1932
+									'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1933
+									'event_espresso'
1934
+								),
1935
+								$event->name()
1936
+							)
1937
+						),
1938
+						__FILE__,
1939
+						__FUNCTION__,
1940
+						__LINE__
1941
+					);
1942
+					return false;
1943
+				}
1944
+			}
1945
+		}
1946
+		return true;
1947
+	}
1948
+
1949
+
1950
+	/**
1951
+	 * redirect_form
1952
+	 *
1953
+	 * @access public
1954
+	 * @return bool
1955
+	 * @throws EE_Error
1956
+	 * @throws InvalidArgumentException
1957
+	 * @throws ReflectionException
1958
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1959
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1960
+	 */
1961
+	public function redirect_form()
1962
+	{
1963
+		$payment_method_billing_info = $this->_payment_method_billing_info(
1964
+			$this->_get_payment_method_for_selected_method_of_payment()
1965
+		);
1966
+		$html                        = $payment_method_billing_info->get_html();
1967
+		$html                        .= $this->checkout->redirect_form;
1968
+		EE_Registry::instance()->REQ->add_output($html);
1969
+		return true;
1970
+	}
1971
+
1972
+
1973
+	/**
1974
+	 * _billing_form_is_valid
1975
+	 *
1976
+	 * @access private
1977
+	 * @return bool
1978
+	 * @throws \EE_Error
1979
+	 */
1980
+	private function _billing_form_is_valid()
1981
+	{
1982
+		if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1983
+			return true;
1984
+		}
1985
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1986
+			if ($this->checkout->billing_form->was_submitted()) {
1987
+				$this->checkout->billing_form->receive_form_submission();
1988
+				if ($this->checkout->billing_form->is_valid()) {
1989
+					return true;
1990
+				}
1991
+				$validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
1992
+				$error_strings     = array();
1993
+				foreach ($validation_errors as $validation_error) {
1994
+					if ($validation_error instanceof EE_Validation_Error) {
1995
+						$form_section = $validation_error->get_form_section();
1996
+						if ($form_section instanceof EE_Form_Input_Base) {
1997
+							$label = $form_section->html_label_text();
1998
+						} elseif ($form_section instanceof EE_Form_Section_Base) {
1999
+							$label = $form_section->name();
2000
+						} else {
2001
+							$label = esc_html__('Validation Error', 'event_espresso');
2002
+						}
2003
+						$error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2004
+					}
2005
+				}
2006
+				EE_Error::add_error(
2007
+					sprintf(
2008
+						esc_html__(
2009
+							'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2010
+							'event_espresso'
2011
+						),
2012
+						'<br/>',
2013
+						implode('<br/>', $error_strings)
2014
+					),
2015
+					__FILE__,
2016
+					__FUNCTION__,
2017
+					__LINE__
2018
+				);
2019
+			} else {
2020
+				EE_Error::add_error(
2021
+					esc_html__(
2022
+						'The billing form was not submitted or something prevented it\'s submission.',
2023
+						'event_espresso'
2024
+					),
2025
+					__FILE__,
2026
+					__FUNCTION__,
2027
+					__LINE__
2028
+				);
2029
+			}
2030
+		} else {
2031
+			EE_Error::add_error(
2032
+				esc_html__('The submitted billing form is invalid possibly due to a technical reason.', 'event_espresso'),
2033
+				__FILE__,
2034
+				__FUNCTION__,
2035
+				__LINE__
2036
+			);
2037
+		}
2038
+		return false;
2039
+	}
2040
+
2041
+
2042
+	/**
2043
+	 * _setup_primary_registrant_prior_to_payment
2044
+	 * ensures that the primary registrant has a valid attendee object created with the critical details populated
2045
+	 * (first & last name & email) and that both the transaction object and primary registration object have been saved
2046
+	 * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2047
+	 * yet)
2048
+	 *
2049
+	 * @access private
2050
+	 * @return bool
2051
+	 * @throws EE_Error
2052
+	 * @throws InvalidArgumentException
2053
+	 * @throws ReflectionException
2054
+	 * @throws RuntimeException
2055
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2056
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2057
+	 */
2058
+	private function _setup_primary_registrant_prior_to_payment()
2059
+	{
2060
+		// check if transaction has a primary registrant and that it has a related Attendee object
2061
+		// if not, then we need to at least gather some primary registrant data before attempting payment
2062
+		if (
2063
+			$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2064
+			&& ! $this->checkout->transaction_has_primary_registrant()
2065
+			&& ! $this->_capture_primary_registration_data_from_billing_form()
2066
+		) {
2067
+			return false;
2068
+		}
2069
+		// because saving an object clears it's cache, we need to do the chevy shuffle
2070
+		// grab the primary_registration object
2071
+		$primary_registration = $this->checkout->transaction->primary_registration();
2072
+		// at this point we'll consider a TXN to not have been failed
2073
+		$this->checkout->transaction->toggle_failed_transaction_status();
2074
+		// save the TXN ( which clears cached copy of primary_registration)
2075
+		$this->checkout->transaction->save();
2076
+		// grab TXN ID and save it to the primary_registration
2077
+		$primary_registration->set_transaction_id($this->checkout->transaction->ID());
2078
+		// save what we have so far
2079
+		$primary_registration->save();
2080
+		return true;
2081
+	}
2082
+
2083
+
2084
+	/**
2085
+	 * _capture_primary_registration_data_from_billing_form
2086
+	 *
2087
+	 * @access private
2088
+	 * @return bool
2089
+	 * @throws EE_Error
2090
+	 * @throws InvalidArgumentException
2091
+	 * @throws ReflectionException
2092
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2093
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2094
+	 */
2095
+	private function _capture_primary_registration_data_from_billing_form()
2096
+	{
2097
+		// convert billing form data into an attendee
2098
+		$this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2099
+		if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2100
+			EE_Error::add_error(
2101
+				sprintf(
2102
+					esc_html__(
2103
+						'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2104
+						'event_espresso'
2105
+					),
2106
+					'<br/>',
2107
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2108
+				),
2109
+				__FILE__,
2110
+				__FUNCTION__,
2111
+				__LINE__
2112
+			);
2113
+			return false;
2114
+		}
2115
+		$primary_registration = $this->checkout->transaction->primary_registration();
2116
+		if (! $primary_registration instanceof EE_Registration) {
2117
+			EE_Error::add_error(
2118
+				sprintf(
2119
+					esc_html__(
2120
+						'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2121
+						'event_espresso'
2122
+					),
2123
+					'<br/>',
2124
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2125
+				),
2126
+				__FILE__,
2127
+				__FUNCTION__,
2128
+				__LINE__
2129
+			);
2130
+			return false;
2131
+		}
2132
+		if (! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2133
+			  instanceof
2134
+			  EE_Attendee
2135
+		) {
2136
+			EE_Error::add_error(
2137
+				sprintf(
2138
+					esc_html__(
2139
+						'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2140
+						'event_espresso'
2141
+					),
2142
+					'<br/>',
2143
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2144
+				),
2145
+				__FILE__,
2146
+				__FUNCTION__,
2147
+				__LINE__
2148
+			);
2149
+			return false;
2150
+		}
2151
+		/** @type EE_Registration_Processor $registration_processor */
2152
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2153
+		// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2154
+		$registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2155
+		return true;
2156
+	}
2157
+
2158
+
2159
+	/**
2160
+	 * _get_payment_method_for_selected_method_of_payment
2161
+	 * retrieves a valid payment method
2162
+	 *
2163
+	 * @access public
2164
+	 * @return EE_Payment_Method
2165
+	 * @throws EE_Error
2166
+	 * @throws InvalidArgumentException
2167
+	 * @throws ReflectionException
2168
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2169
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2170
+	 */
2171
+	private function _get_payment_method_for_selected_method_of_payment()
2172
+	{
2173
+		if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2174
+			$this->_redirect_because_event_sold_out();
2175
+			return null;
2176
+		}
2177
+		// get EE_Payment_Method object
2178
+		if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2179
+			$payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2180
+		} else {
2181
+			// load EEM_Payment_Method
2182
+			EE_Registry::instance()->load_model('Payment_Method');
2183
+			/** @type EEM_Payment_Method $EEM_Payment_Method */
2184
+			$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2185
+			$payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2186
+		}
2187
+		// verify $payment_method
2188
+		if (! $payment_method instanceof EE_Payment_Method) {
2189
+			// not a payment
2190
+			EE_Error::add_error(
2191
+				sprintf(
2192
+					esc_html__(
2193
+						'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2194
+						'event_espresso'
2195
+					),
2196
+					'<br/>',
2197
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2198
+				),
2199
+				__FILE__,
2200
+				__FUNCTION__,
2201
+				__LINE__
2202
+			);
2203
+			return null;
2204
+		}
2205
+		// and verify it has a valid Payment_Method Type object
2206
+		if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2207
+			// not a payment
2208
+			EE_Error::add_error(
2209
+				sprintf(
2210
+					esc_html__(
2211
+						'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2212
+						'event_espresso'
2213
+					),
2214
+					'<br/>',
2215
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2216
+				),
2217
+				__FILE__,
2218
+				__FUNCTION__,
2219
+				__LINE__
2220
+			);
2221
+			return null;
2222
+		}
2223
+		return $payment_method;
2224
+	}
2225
+
2226
+
2227
+	/**
2228
+	 *    _attempt_payment
2229
+	 *
2230
+	 * @access    private
2231
+	 * @type    EE_Payment_Method $payment_method
2232
+	 * @return mixed EE_Payment | boolean
2233
+	 * @throws EE_Error
2234
+	 * @throws InvalidArgumentException
2235
+	 * @throws ReflectionException
2236
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2237
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2238
+	 */
2239
+	private function _attempt_payment(EE_Payment_Method $payment_method)
2240
+	{
2241
+		$payment = null;
2242
+		$this->checkout->transaction->save();
2243
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2244
+		if (! $payment_processor instanceof EE_Payment_Processor) {
2245
+			return false;
2246
+		}
2247
+		try {
2248
+			$payment_processor->set_revisit($this->checkout->revisit);
2249
+			// generate payment object
2250
+			$payment = $payment_processor->process_payment(
2251
+				$payment_method,
2252
+				$this->checkout->transaction,
2253
+				$this->checkout->amount_owing,
2254
+				$this->checkout->billing_form,
2255
+				$this->_get_return_url($payment_method),
2256
+				'CART',
2257
+				$this->checkout->admin_request,
2258
+				true,
2259
+				$this->reg_step_url()
2260
+			);
2261
+		} catch (Exception $e) {
2262
+			$this->_handle_payment_processor_exception($e);
2263
+		}
2264
+		return $payment;
2265
+	}
2266
+
2267
+
2268
+	/**
2269
+	 * _handle_payment_processor_exception
2270
+	 *
2271
+	 * @access protected
2272
+	 * @param \Exception $e
2273
+	 * @return void
2274
+	 * @throws EE_Error
2275
+	 * @throws InvalidArgumentException
2276
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2277
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2278
+	 */
2279
+	protected function _handle_payment_processor_exception(Exception $e)
2280
+	{
2281
+		EE_Error::add_error(
2282
+			sprintf(
2283
+				esc_html__(
2284
+					'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2285
+					'event_espresso'
2286
+				),
2287
+				'<br/>',
2288
+				EE_Registry::instance()->CFG->organization->get_pretty('email'),
2289
+				$e->getMessage(),
2290
+				$e->getFile(),
2291
+				$e->getLine()
2292
+			),
2293
+			__FILE__,
2294
+			__FUNCTION__,
2295
+			__LINE__
2296
+		);
2297
+	}
2298
+
2299
+
2300
+	/**
2301
+	 * _get_return_url
2302
+	 *
2303
+	 * @access protected
2304
+	 * @param \EE_Payment_Method $payment_method
2305
+	 * @return string
2306
+	 * @throws \EE_Error
2307
+	 */
2308
+	protected function _get_return_url(EE_Payment_Method $payment_method)
2309
+	{
2310
+		$return_url = '';
2311
+		switch ($payment_method->type_obj()->payment_occurs()) {
2312
+			case EE_PMT_Base::offsite :
2313
+				$return_url = add_query_arg(
2314
+					array(
2315
+						'action'                     => 'process_gateway_response',
2316
+						'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2317
+						'spco_txn'                   => $this->checkout->transaction->ID(),
2318
+					),
2319
+					$this->reg_step_url()
2320
+				);
2321
+				break;
2322
+			case EE_PMT_Base::onsite :
2323
+			case EE_PMT_Base::offline :
2324
+				$return_url = $this->checkout->next_step->reg_step_url();
2325
+				break;
2326
+		}
2327
+		return $return_url;
2328
+	}
2329
+
2330
+
2331
+	/**
2332
+	 * _validate_payment
2333
+	 *
2334
+	 * @access private
2335
+	 * @param EE_Payment $payment
2336
+	 * @return EE_Payment|FALSE
2337
+	 * @throws EE_Error
2338
+	 * @throws InvalidArgumentException
2339
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2340
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2341
+	 */
2342
+	private function _validate_payment($payment = null)
2343
+	{
2344
+		if ($this->checkout->payment_method->is_off_line()) {
2345
+			return true;
2346
+		}
2347
+		// verify payment object
2348
+		if (! $payment instanceof EE_Payment) {
2349
+			// not a payment
2350
+			EE_Error::add_error(
2351
+				sprintf(
2352
+					esc_html__(
2353
+						'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2354
+						'event_espresso'
2355
+					),
2356
+					'<br/>',
2357
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2358
+				),
2359
+				__FILE__,
2360
+				__FUNCTION__,
2361
+				__LINE__
2362
+			);
2363
+			return false;
2364
+		}
2365
+		return $payment;
2366
+	}
2367
+
2368
+
2369
+	/**
2370
+	 * _post_payment_processing
2371
+	 *
2372
+	 * @access private
2373
+	 * @param EE_Payment|bool $payment
2374
+	 * @return bool
2375
+	 * @throws EE_Error
2376
+	 * @throws InvalidArgumentException
2377
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2378
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2379
+	 */
2380
+	private function _post_payment_processing($payment = null)
2381
+	{
2382
+		// Off-Line payment?
2383
+		if ($payment === true) {
2384
+			//$this->_setup_redirect_for_next_step();
2385
+			return true;
2386
+			// On-Site payment?
2387
+		} else if ($this->checkout->payment_method->is_on_site()) {
2388
+			if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2389
+				//$this->_setup_redirect_for_next_step();
2390
+				$this->checkout->continue_reg = false;
2391
+			}
2392
+			// Off-Site payment?
2393
+		} else if ($this->checkout->payment_method->is_off_site()) {
2394
+			// if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2395
+			if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2396
+				do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2397
+				$this->checkout->redirect      = true;
2398
+				$this->checkout->redirect_form = $payment->redirect_form();
2399
+				$this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2400
+				// set JSON response
2401
+				$this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2402
+				// and lastly, let's bump the payment status to pending
2403
+				$payment->set_status(EEM_Payment::status_id_pending);
2404
+				$payment->save();
2405
+			} else {
2406
+				// not a payment
2407
+				$this->checkout->continue_reg = false;
2408
+				EE_Error::add_error(
2409
+					sprintf(
2410
+						esc_html__(
2411
+							'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2412
+							'event_espresso'
2413
+						),
2414
+						'<br/>',
2415
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
2416
+					),
2417
+					__FILE__,
2418
+					__FUNCTION__,
2419
+					__LINE__
2420
+				);
2421
+			}
2422
+		} else {
2423
+			// ummm ya... not Off-Line, not On-Site, not off-Site ????
2424
+			$this->checkout->continue_reg = false;
2425
+			return false;
2426
+		}
2427
+		return $payment;
2428
+	}
2429
+
2430
+
2431
+	/**
2432
+	 *    _process_payment_status
2433
+	 *
2434
+	 * @access private
2435
+	 * @type    EE_Payment $payment
2436
+	 * @param string       $payment_occurs
2437
+	 * @return bool
2438
+	 * @throws EE_Error
2439
+	 * @throws InvalidArgumentException
2440
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2441
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2442
+	 */
2443
+	private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2444
+	{
2445
+		// off-line payment? carry on
2446
+		if ($payment_occurs === EE_PMT_Base::offline) {
2447
+			return true;
2448
+		}
2449
+		// verify payment validity
2450
+		if ($payment instanceof EE_Payment) {
2451
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2452
+			$msg = $payment->gateway_response();
2453
+			// check results
2454
+			switch ($payment->status()) {
2455
+				// good payment
2456
+				case EEM_Payment::status_id_approved :
2457
+					EE_Error::add_success(
2458
+						esc_html__('Your payment was processed successfully.', 'event_espresso'),
2459
+						__FILE__,
2460
+						__FUNCTION__,
2461
+						__LINE__
2462
+					);
2463
+					return true;
2464
+					break;
2465
+				// slow payment
2466
+				case EEM_Payment::status_id_pending :
2467
+					if (empty($msg)) {
2468
+						$msg = esc_html__(
2469
+							'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2470
+							'event_espresso'
2471
+						);
2472
+					}
2473
+					EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2474
+					return true;
2475
+					break;
2476
+				// don't wanna payment
2477
+				case EEM_Payment::status_id_cancelled :
2478
+					if (empty($msg)) {
2479
+						$msg = _n(
2480
+							'Payment cancelled. Please try again.',
2481
+							'Payment cancelled. Please try again or select another method of payment.',
2482
+							count($this->checkout->available_payment_methods),
2483
+							'event_espresso'
2484
+						);
2485
+					}
2486
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2487
+					return false;
2488
+					break;
2489
+				// not enough payment
2490
+				case EEM_Payment::status_id_declined :
2491
+					if (empty($msg)) {
2492
+						$msg = _n(
2493
+							'We\'re sorry but your payment was declined. Please try again.',
2494
+							'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2495
+							count($this->checkout->available_payment_methods),
2496
+							'event_espresso'
2497
+						);
2498
+					}
2499
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2500
+					return false;
2501
+					break;
2502
+				// bad payment
2503
+				case EEM_Payment::status_id_failed :
2504
+					if (! empty($msg)) {
2505
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2506
+						return false;
2507
+					}
2508
+					// default to error below
2509
+					break;
2510
+			}
2511
+		}
2512
+		// off-site payment gateway responses are too unreliable, so let's just assume that
2513
+		// the payment processing is just running slower than the registrant's request
2514
+		if ($payment_occurs === EE_PMT_Base::offsite) {
2515
+			return true;
2516
+		}
2517
+		EE_Error::add_error(
2518
+			sprintf(
2519
+				esc_html__(
2520
+					'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2521
+					'event_espresso'
2522
+				),
2523
+				'<br/>',
2524
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
2525
+			),
2526
+			__FILE__,
2527
+			__FUNCTION__,
2528
+			__LINE__
2529
+		);
2530
+		return false;
2531
+	}
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+
2538
+	/********************************************************************************************************/
2539
+	/**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2540
+	/********************************************************************************************************/
2541
+	/**
2542
+	 * process_gateway_response
2543
+	 * this is the return point for Off-Site Payment Methods
2544
+	 * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2545
+	 * otherwise, it will load up the last payment made for the TXN.
2546
+	 * If the payment retrieved looks good, it will then either:
2547
+	 *    complete the current step and allow advancement to the next reg step
2548
+	 *        or present the payment options again
2549
+	 *
2550
+	 * @access private
2551
+	 * @return EE_Payment|FALSE
2552
+	 * @throws EE_Error
2553
+	 * @throws InvalidArgumentException
2554
+	 * @throws ReflectionException
2555
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2556
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2557
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2558
+	 */
2559
+	public function process_gateway_response()
2560
+	{
2561
+		$payment = null;
2562
+		// how have they chosen to pay?
2563
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2564
+		// get EE_Payment_Method object
2565
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2566
+			$this->checkout->continue_reg = false;
2567
+			return false;
2568
+		}
2569
+		if (! $this->checkout->payment_method->is_off_site()) {
2570
+			return false;
2571
+		}
2572
+		$this->_validate_offsite_return();
2573
+		// DEBUG LOG
2574
+		//$this->checkout->log(
2575
+		//	__CLASS__, __FUNCTION__, __LINE__,
2576
+		//	array(
2577
+		//		'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2578
+		//		'payment_method' => $this->checkout->payment_method,
2579
+		//	),
2580
+		//	true
2581
+		//);
2582
+		// verify TXN
2583
+		if ($this->checkout->transaction instanceof EE_Transaction) {
2584
+			$gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2585
+			if (! $gateway instanceof EE_Offsite_Gateway) {
2586
+				$this->checkout->continue_reg = false;
2587
+				return false;
2588
+			}
2589
+			$payment = $this->_process_off_site_payment($gateway);
2590
+			$payment = $this->_process_cancelled_payments($payment);
2591
+			$payment = $this->_validate_payment($payment);
2592
+			// if payment was not declined by the payment gateway or cancelled by the registrant
2593
+			if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2594
+				//$this->_setup_redirect_for_next_step();
2595
+				// store that for later
2596
+				$this->checkout->payment = $payment;
2597
+				// mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2598
+				// because we will complete this step during the IPN processing then
2599
+				if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2600
+					$this->set_completed();
2601
+				}
2602
+				return true;
2603
+			}
2604
+		}
2605
+		// DEBUG LOG
2606
+		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2607
+		//	array( 'payment' => $payment )
2608
+		//);
2609
+		$this->checkout->continue_reg = false;
2610
+		return false;
2611
+	}
2612
+
2613
+
2614
+	/**
2615
+	 * _validate_return
2616
+	 *
2617
+	 * @access private
2618
+	 * @return void
2619
+	 * @throws EE_Error
2620
+	 * @throws InvalidArgumentException
2621
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2622
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2623
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2624
+	 */
2625
+	private function _validate_offsite_return()
2626
+	{
2627
+		$TXN_ID = (int)EE_Registry::instance()->REQ->get('spco_txn', 0);
2628
+		if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
+			// Houston... we might have a problem
2630
+			$invalid_TXN = false;
2631
+			// first gather some info
2632
+			$valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
+			$primary_registrant = $valid_TXN instanceof EE_Transaction
2634
+				? $valid_TXN->primary_registration()
2635
+				: null;
2636
+			// let's start by retrieving the cart for this TXN
2637
+			$cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
+			if ($cart instanceof EE_Cart) {
2639
+				// verify that the current cart has tickets
2640
+				$tickets = $cart->get_tickets();
2641
+				if (empty($tickets)) {
2642
+					$invalid_TXN = true;
2643
+				}
2644
+			} else {
2645
+				$invalid_TXN = true;
2646
+			}
2647
+			$valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
+				? $primary_registrant->session_ID()
2649
+				: null;
2650
+			// validate current Session ID and compare against valid TXN session ID
2651
+			if (
2652
+				$invalid_TXN // if this is already true, then skip other checks
2653
+				|| EE_Session::instance()->id() === null
2654
+				|| (
2655
+					// WARNING !!!
2656
+					// this could be PayPal sending back duplicate requests (ya they do that)
2657
+					// or it **could** mean someone is simply registering AGAIN after having just done so
2658
+					// so now we need to determine if this current TXN looks valid or not
2659
+					// and whether this reg step has even been started ?
2660
+					EE_Session::instance()->id() === $valid_TXN_SID
2661
+					// really? you're half way through this reg step, but you never started it ?
2662
+					&& $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
+				)
2664
+			) {
2665
+				$invalid_TXN = true;
2666
+			}
2667
+			if ($invalid_TXN) {
2668
+				// is the valid TXN completed ?
2669
+				if ($valid_TXN instanceof EE_Transaction) {
2670
+					// has this step even been started ?
2671
+					$reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
+					if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
+						// so it **looks** like this is a double request from PayPal
2674
+						// so let's try to pick up where we left off
2675
+						$this->checkout->transaction = $valid_TXN;
2676
+						$this->checkout->refresh_all_entities(true);
2677
+						return;
2678
+					}
2679
+				}
2680
+				// you appear to be lost?
2681
+				$this->_redirect_wayward_request($primary_registrant);
2682
+			}
2683
+		}
2684
+	}
2685
+
2686
+
2687
+	/**
2688
+	 * _redirect_wayward_request
2689
+	 *
2690
+	 * @access private
2691
+	 * @param \EE_Registration|null $primary_registrant
2692
+	 * @return bool
2693
+	 * @throws EE_Error
2694
+	 * @throws InvalidArgumentException
2695
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2696
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2697
+	 */
2698
+	private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
+	{
2700
+		if (! $primary_registrant instanceof EE_Registration) {
2701
+			// try redirecting based on the current TXN
2702
+			$primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
+				? $this->checkout->transaction->primary_registration()
2704
+				: null;
2705
+		}
2706
+		if (! $primary_registrant instanceof EE_Registration) {
2707
+			EE_Error::add_error(
2708
+				sprintf(
2709
+					esc_html__(
2710
+						'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
+						'event_espresso'
2712
+					),
2713
+					'<br/>',
2714
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
+				),
2716
+				__FILE__,
2717
+				__FUNCTION__,
2718
+				__LINE__
2719
+			);
2720
+			return false;
2721
+		}
2722
+		// make sure transaction is not locked
2723
+		$this->checkout->transaction->unlock();
2724
+		wp_safe_redirect(
2725
+			add_query_arg(
2726
+				array(
2727
+					'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
+				),
2729
+				$this->checkout->thank_you_page_url
2730
+			)
2731
+		);
2732
+		exit();
2733
+	}
2734
+
2735
+
2736
+	/**
2737
+	 * _process_off_site_payment
2738
+	 *
2739
+	 * @access private
2740
+	 * @param \EE_Offsite_Gateway $gateway
2741
+	 * @return EE_Payment
2742
+	 * @throws EE_Error
2743
+	 * @throws InvalidArgumentException
2744
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2745
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2746
+	 */
2747
+	private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
+	{
2749
+		try {
2750
+			$request_data = \EE_Registry::instance()->REQ->params();
2751
+			// if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2752
+			$this->set_handle_IPN_in_this_request(
2753
+				$gateway->handle_IPN_in_this_request($request_data, false)
2754
+			);
2755
+			if ($this->handle_IPN_in_this_request()) {
2756
+				// get payment details and process results
2757
+				/** @type EE_Payment_Processor $payment_processor */
2758
+				$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2759
+				$payment           = $payment_processor->process_ipn(
2760
+					$request_data,
2761
+					$this->checkout->transaction,
2762
+					$this->checkout->payment_method,
2763
+					true,
2764
+					false
2765
+				);
2766
+				//$payment_source = 'process_ipn';
2767
+			} else {
2768
+				$payment = $this->checkout->transaction->last_payment();
2769
+				//$payment_source = 'last_payment';
2770
+			}
2771
+		} catch (Exception $e) {
2772
+			// let's just eat the exception and try to move on using any previously set payment info
2773
+			$payment = $this->checkout->transaction->last_payment();
2774
+			//$payment_source = 'last_payment after Exception';
2775
+			// but if we STILL don't have a payment object
2776
+			if (! $payment instanceof EE_Payment) {
2777
+				// then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778
+				$this->_handle_payment_processor_exception($e);
2779
+			}
2780
+		}
2781
+		// DEBUG LOG
2782
+		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2783
+		//	array(
2784
+		//		'process_ipn_payment' => $payment,
2785
+		//		'payment_source'      => $payment_source,
2786
+		//	)
2787
+		//);
2788
+		return $payment;
2789
+	}
2790
+
2791
+
2792
+	/**
2793
+	 * _process_cancelled_payments
2794
+	 * just makes sure that the payment status gets updated correctly
2795
+	 * so tha tan error isn't generated during payment validation
2796
+	 *
2797
+	 * @access private
2798
+	 * @param EE_Payment $payment
2799
+	 * @return EE_Payment | FALSE
2800
+	 * @throws \EE_Error
2801
+	 */
2802
+	private function _process_cancelled_payments($payment = null)
2803
+	{
2804
+		if (
2805
+			$payment instanceof EE_Payment
2806
+			&& isset($_REQUEST['ee_cancel_payment'])
2807
+			&& $payment->status() === EEM_Payment::status_id_failed
2808
+		) {
2809
+			$payment->set_status(EEM_Payment::status_id_cancelled);
2810
+		}
2811
+		return $payment;
2812
+	}
2813
+
2814
+
2815
+	/**
2816
+	 *    get_transaction_details_for_gateways
2817
+	 *
2818
+	 * @access    public
2819
+	 * @return int
2820
+	 * @throws EE_Error
2821
+	 * @throws InvalidArgumentException
2822
+	 * @throws ReflectionException
2823
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2824
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2825
+	 */
2826
+	public function get_transaction_details_for_gateways()
2827
+	{
2828
+		$txn_details = array();
2829
+		// ya gotta make a choice man
2830
+		if (empty($this->checkout->selected_method_of_payment)) {
2831
+			$txn_details = array(
2832
+				'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2833
+			);
2834
+		}
2835
+		// get EE_Payment_Method object
2836
+		if (
2837
+			empty($txn_details)
2838
+			&&
2839
+			! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2840
+		) {
2841
+			$txn_details = array(
2842
+				'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2843
+				'error'                      => esc_html__(
2844
+					'A valid Payment Method could not be determined.',
2845
+					'event_espresso'
2846
+				),
2847
+			);
2848
+		}
2849
+		if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2850
+			$return_url  = $this->_get_return_url($this->checkout->payment_method);
2851
+			$txn_details = array(
2852
+				'TXN_ID'         => $this->checkout->transaction->ID(),
2853
+				'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2854
+				'TXN_total'      => $this->checkout->transaction->total(),
2855
+				'TXN_paid'       => $this->checkout->transaction->paid(),
2856
+				'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2857
+				'STS_ID'         => $this->checkout->transaction->status_ID(),
2858
+				'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2859
+				'payment_amount' => $this->checkout->amount_owing,
2860
+				'return_url'     => $return_url,
2861
+				'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2862
+				'notify_url'     => EE_Config::instance()->core->txn_page_url(
2863
+					array(
2864
+						'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2865
+						'ee_payment_method' => $this->checkout->payment_method->slug(),
2866
+					)
2867
+				),
2868
+			);
2869
+		}
2870
+		echo wp_json_encode($txn_details);
2871
+		exit();
2872
+	}
2873
+
2874
+
2875
+	/**
2876
+	 *    __sleep
2877
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2878
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2879
+	 * reg form, because if needed, it will be regenerated anyways
2880
+	 *
2881
+	 * @return array
2882
+	 */
2883
+	public function __sleep()
2884
+	{
2885
+		// remove the reg form and the checkout
2886
+		return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2887
+	}
2888 2888
 }
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 2 patches
Indentation   +2433 added lines, -2433 removed lines patch added patch discarded remove patch
@@ -16,2437 +16,2437 @@
 block discarded – undo
16 16
 class Transactions_Admin_Page extends EE_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * @var EE_Transaction
21
-     */
22
-    private $_transaction;
23
-
24
-    /**
25
-     * @var EE_Session
26
-     */
27
-    private $_session;
28
-
29
-    /**
30
-     * @var array $_txn_status
31
-     */
32
-    private static $_txn_status;
33
-
34
-    /**
35
-     * @var array $_pay_status
36
-     */
37
-    private static $_pay_status;
38
-
39
-    /**
40
-     * @var array $_existing_reg_payment_REG_IDs
41
-     */
42
-    protected $_existing_reg_payment_REG_IDs = null;
43
-
44
-
45
-    /**
46
-     * @Constructor
47
-     * @access public
48
-     * @param bool $routing
49
-     * @throws EE_Error
50
-     * @throws InvalidArgumentException
51
-     * @throws ReflectionException
52
-     * @throws InvalidDataTypeException
53
-     * @throws InvalidInterfaceException
54
-     */
55
-    public function __construct($routing = true)
56
-    {
57
-        parent::__construct($routing);
58
-    }
59
-
60
-
61
-    /**
62
-     *    _init_page_props
63
-     *
64
-     * @return void
65
-     */
66
-    protected function _init_page_props()
67
-    {
68
-        $this->page_slug        = TXN_PG_SLUG;
69
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
70
-        $this->_admin_base_url  = TXN_ADMIN_URL;
71
-        $this->_admin_base_path = TXN_ADMIN;
72
-    }
73
-
74
-
75
-    /**
76
-     *    _ajax_hooks
77
-     *
78
-     * @return void
79
-     */
80
-    protected function _ajax_hooks()
81
-    {
82
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
83
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
84
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
85
-    }
86
-
87
-
88
-    /**
89
-     *    _define_page_props
90
-     *
91
-     * @return void
92
-     */
93
-    protected function _define_page_props()
94
-    {
95
-        $this->_admin_page_title = $this->page_label;
96
-        $this->_labels           = array(
97
-            'buttons' => array(
98
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
99
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
100
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
101
-            ),
102
-        );
103
-    }
104
-
105
-
106
-    /**
107
-     *        grab url requests and route them
108
-     *
109
-     * @access private
110
-     * @return void
111
-     * @throws EE_Error
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     */
116
-    public function _set_page_routes()
117
-    {
118
-
119
-        $this->_set_transaction_status_array();
120
-
121
-        $txn_id = ! empty($this->_req_data['TXN_ID'])
122
-                  && ! is_array($this->_req_data['TXN_ID'])
123
-            ? $this->_req_data['TXN_ID']
124
-            : 0;
125
-
126
-        $this->_page_routes = array(
127
-
128
-            'default' => array(
129
-                'func'       => '_transactions_overview_list_table',
130
-                'capability' => 'ee_read_transactions',
131
-            ),
132
-
133
-            'view_transaction' => array(
134
-                'func'       => '_transaction_details',
135
-                'capability' => 'ee_read_transaction',
136
-                'obj_id'     => $txn_id,
137
-            ),
138
-
139
-            'send_payment_reminder' => array(
140
-                'func'       => '_send_payment_reminder',
141
-                'noheader'   => true,
142
-                'capability' => 'ee_send_message',
143
-            ),
144
-
145
-            'espresso_apply_payment' => array(
146
-                'func'       => 'apply_payments_or_refunds',
147
-                'noheader'   => true,
148
-                'capability' => 'ee_edit_payments',
149
-            ),
150
-
151
-            'espresso_apply_refund' => array(
152
-                'func'       => 'apply_payments_or_refunds',
153
-                'noheader'   => true,
154
-                'capability' => 'ee_edit_payments',
155
-            ),
156
-
157
-            'espresso_delete_payment' => array(
158
-                'func'       => 'delete_payment',
159
-                'noheader'   => true,
160
-                'capability' => 'ee_delete_payments',
161
-            ),
162
-
163
-        );
164
-    }
165
-
166
-
167
-    protected function _set_page_config()
168
-    {
169
-        $this->_page_config = array(
170
-            'default'          => array(
171
-                'nav'           => array(
172
-                    'label' => esc_html__('Overview', 'event_espresso'),
173
-                    'order' => 10,
174
-                ),
175
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
176
-                'help_tabs'     => array(
177
-                    'transactions_overview_help_tab'                       => array(
178
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
179
-                        'filename' => 'transactions_overview',
180
-                    ),
181
-                    'transactions_overview_table_column_headings_help_tab' => array(
182
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
183
-                        'filename' => 'transactions_overview_table_column_headings',
184
-                    ),
185
-                    'transactions_overview_views_filters_help_tab'         => array(
186
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
187
-                        'filename' => 'transactions_overview_views_filters_search',
188
-                    ),
189
-                ),
190
-                'help_tour'     => array('Transactions_Overview_Help_Tour'),
191
-                /**
192
-                 * commented out because currently we are not displaying tips for transaction list table status but this
193
-                 * may change in a later iteration so want to keep the code for then.
194
-                 */
195
-                //'qtips' => array( 'Transactions_List_Table_Tips' ),
196
-                'require_nonce' => false,
197
-            ),
198
-            'view_transaction' => array(
199
-                'nav'       => array(
200
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
201
-                    'order'      => 5,
202
-                    'url'        => isset($this->_req_data['TXN_ID'])
203
-                        ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
204
-                        : $this->_admin_base_url,
205
-                    'persistent' => false,
206
-                ),
207
-                'help_tabs' => array(
208
-                    'transactions_view_transaction_help_tab'                                              => array(
209
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
210
-                        'filename' => 'transactions_view_transaction',
211
-                    ),
212
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
213
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
214
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
215
-                    ),
216
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
217
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
218
-                        'filename' => 'transactions_view_transaction_attendees_registered',
219
-                    ),
220
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
221
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
222
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
223
-                    ),
224
-                ),
225
-                'qtips'     => array('Transaction_Details_Tips'),
226
-                'help_tour' => array('Transaction_Details_Help_Tour'),
227
-                'metaboxes' => array('_transaction_details_metaboxes'),
228
-
229
-                'require_nonce' => false,
230
-            ),
231
-        );
232
-    }
233
-
234
-
235
-    /**
236
-     * The below methods aren't used by this class currently
237
-     */
238
-    protected function _add_screen_options()
239
-    {
240
-        //noop
241
-    }
242
-
243
-    protected function _add_feature_pointers()
244
-    {
245
-        //noop
246
-    }
247
-
248
-    public function admin_init()
249
-    {
250
-        // IF a registration was JUST added via the admin...
251
-        if (isset(
252
-            $this->_req_data['redirect_from'],
253
-            $this->_req_data['EVT_ID'],
254
-            $this->_req_data['event_name']
255
-        )) {
256
-            // then set a cookie so that we can block any attempts to use
257
-            // the back button as a way to enter another registration.
258
-            setcookie(
259
-                'ee_registration_added',
260
-                $this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/'
261
-            );
262
-            // and update the global
263
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
264
-        }
265
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
266
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
267
-            'event_espresso'
268
-        );
269
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
270
-            'An error occurred! Please refresh the page and try again.',
271
-            'event_espresso'
272
-        );
273
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
274
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
275
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
276
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
277
-            'This transaction has been overpaid ! Payments Total',
278
-            'event_espresso'
279
-        );
280
-    }
281
-
282
-    public function admin_notices()
283
-    {
284
-        //noop
285
-    }
286
-
287
-    public function admin_footer_scripts()
288
-    {
289
-        //noop
290
-    }
291
-
292
-
293
-    /**
294
-     * _set_transaction_status_array
295
-     * sets list of transaction statuses
296
-     *
297
-     * @access private
298
-     * @return void
299
-     * @throws EE_Error
300
-     * @throws InvalidArgumentException
301
-     * @throws InvalidDataTypeException
302
-     * @throws InvalidInterfaceException
303
-     */
304
-    private function _set_transaction_status_array()
305
-    {
306
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
307
-    }
308
-
309
-
310
-    /**
311
-     * get_transaction_status_array
312
-     * return the transaction status array for wp_list_table
313
-     *
314
-     * @access public
315
-     * @return array
316
-     */
317
-    public function get_transaction_status_array()
318
-    {
319
-        return self::$_txn_status;
320
-    }
321
-
322
-
323
-    /**
324
-     *    get list of payment statuses
325
-     *
326
-     * @access private
327
-     * @return void
328
-     * @throws EE_Error
329
-     * @throws InvalidArgumentException
330
-     * @throws InvalidDataTypeException
331
-     * @throws InvalidInterfaceException
332
-     */
333
-    private function _get_payment_status_array()
334
-    {
335
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
336
-        $this->_template_args['payment_status'] = self::$_pay_status;
337
-
338
-    }
339
-
340
-
341
-    /**
342
-     *    _add_screen_options_default
343
-     *
344
-     * @access protected
345
-     * @return void
346
-     * @throws InvalidArgumentException
347
-     * @throws InvalidDataTypeException
348
-     * @throws InvalidInterfaceException
349
-     */
350
-    protected function _add_screen_options_default()
351
-    {
352
-        $this->_per_page_screen_option();
353
-    }
354
-
355
-
356
-    /**
357
-     * load_scripts_styles
358
-     *
359
-     * @access public
360
-     * @return void
361
-     */
362
-    public function load_scripts_styles()
363
-    {
364
-        //enqueue style
365
-        wp_register_style(
366
-            'espresso_txn',
367
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
368
-            array(),
369
-            EVENT_ESPRESSO_VERSION
370
-        );
371
-        wp_enqueue_style('espresso_txn');
372
-        //scripts
373
-        wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
374
-            'ee_admin_js',
375
-            'ee-datepicker',
376
-            'jquery-ui-datepicker',
377
-            'jquery-ui-draggable',
378
-            'ee-dialog',
379
-            'ee-accounting',
380
-            'ee-serialize-full-array',
381
-        ), EVENT_ESPRESSO_VERSION, true);
382
-        wp_enqueue_script('espresso_txn');
383
-    }
384
-
385
-
386
-    /**
387
-     *    load_scripts_styles_view_transaction
388
-     *
389
-     * @access public
390
-     * @return void
391
-     */
392
-    public function load_scripts_styles_view_transaction()
393
-    {
394
-        //styles
395
-        wp_enqueue_style('espresso-ui-theme');
396
-    }
397
-
398
-
399
-    /**
400
-     *    load_scripts_styles_default
401
-     *
402
-     * @access public
403
-     * @return void
404
-     */
405
-    public function load_scripts_styles_default()
406
-    {
407
-        //styles
408
-        wp_enqueue_style('espresso-ui-theme');
409
-    }
410
-
411
-
412
-    /**
413
-     *    _set_list_table_views_default
414
-     *
415
-     * @access protected
416
-     * @return void
417
-     */
418
-    protected function _set_list_table_views_default()
419
-    {
420
-        $this->_views = array(
421
-            'all'       => array(
422
-                'slug'  => 'all',
423
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
424
-                'count' => 0,
425
-            ),
426
-            'abandoned' => array(
427
-                'slug'  => 'abandoned',
428
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
-                'count' => 0,
430
-            ),
431
-            'failed'    => array(
432
-                'slug'  => 'failed',
433
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
434
-                'count' => 0,
435
-            ),
436
-        );
437
-    }
438
-
439
-
440
-    /**
441
-     * _set_transaction_object
442
-     * This sets the _transaction property for the transaction details screen
443
-     *
444
-     * @access private
445
-     * @return void
446
-     * @throws EE_Error
447
-     * @throws InvalidArgumentException
448
-     * @throws RuntimeException
449
-     * @throws InvalidDataTypeException
450
-     * @throws InvalidInterfaceException
451
-     * @throws ReflectionException
452
-     */
453
-    private function _set_transaction_object()
454
-    {
455
-        if ($this->_transaction instanceof EE_Transaction) {
456
-            return;
457
-        } //get out we've already set the object
458
-
459
-        $TXN_ID = ! empty($this->_req_data['TXN_ID'])
460
-            ? absint($this->_req_data['TXN_ID'])
461
-            : false;
462
-
463
-        //get transaction object
464
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
465
-        $this->_session     = $this->_transaction instanceof EE_Transaction
466
-            ? $this->_transaction->get('TXN_session_data')
467
-            : null;
468
-        $this->_transaction->verify_abandoned_transaction_status();
469
-
470
-        if (! $this->_transaction instanceof EE_Transaction) {
471
-            $error_msg = sprintf(
472
-                esc_html__(
473
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
474
-                    'event_espresso'
475
-                ),
476
-                $TXN_ID
477
-            );
478
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
479
-        }
480
-    }
481
-
482
-
483
-    /**
484
-     *    _transaction_legend_items
485
-     *
486
-     * @access protected
487
-     * @return array
488
-     * @throws EE_Error
489
-     * @throws InvalidArgumentException
490
-     * @throws ReflectionException
491
-     * @throws InvalidDataTypeException
492
-     * @throws InvalidInterfaceException
493
-     */
494
-    protected function _transaction_legend_items()
495
-    {
496
-        EE_Registry::instance()->load_helper('MSG_Template');
497
-        $items = array();
498
-
499
-        if (EE_Registry::instance()->CAP->current_user_can(
500
-            'ee_read_global_messages',
501
-            'view_filtered_messages'
502
-        )) {
503
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
504
-            if (is_array($related_for_icon)
505
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
506
-            ) {
507
-                $items['view_related_messages'] = array(
508
-                    'class' => $related_for_icon['css_class'],
509
-                    'desc'  => $related_for_icon['label'],
510
-                );
511
-            }
512
-        }
513
-
514
-        $items = apply_filters(
515
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
516
-            array_merge(
517
-                $items,
518
-                array(
519
-                    'view_details'          => array(
520
-                        'class' => 'dashicons dashicons-cart',
521
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
522
-                    ),
523
-                    'view_invoice'          => array(
524
-                        'class' => 'dashicons dashicons-media-spreadsheet',
525
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
526
-                    ),
527
-                    'view_receipt'          => array(
528
-                        'class' => 'dashicons dashicons-media-default',
529
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
530
-                    ),
531
-                    'view_registration'     => array(
532
-                        'class' => 'dashicons dashicons-clipboard',
533
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
534
-                    ),
535
-                    'payment_overview_link' => array(
536
-                        'class' => 'dashicons dashicons-money',
537
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
538
-                    ),
539
-                )
540
-            )
541
-        );
542
-
543
-        if (EE_Registry::instance()->CAP->current_user_can(
544
-            'ee_send_message',
545
-            'espresso_transactions_send_payment_reminder'
546
-        )) {
547
-            if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
548
-                $items['send_payment_reminder'] = array(
549
-                    'class' => 'dashicons dashicons-email-alt',
550
-                    'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
551
-                );
552
-            } else {
553
-                $items['blank*'] = array(
554
-                    'class' => '',
555
-                    'desc'  => '',
556
-                );
557
-            }
558
-        } else {
559
-            $items['blank*'] = array(
560
-                'class' => '',
561
-                'desc'  => '',
562
-            );
563
-        }
564
-        $more_items = apply_filters(
565
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
566
-            array(
567
-                'overpaid'   => array(
568
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
569
-                    'desc'  => EEH_Template::pretty_status(
570
-                        EEM_Transaction::overpaid_status_code,
571
-                        false,
572
-                        'sentence'
573
-                    ),
574
-                ),
575
-                'complete'   => array(
576
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
577
-                    'desc'  => EEH_Template::pretty_status(
578
-                        EEM_Transaction::complete_status_code,
579
-                        false,
580
-                        'sentence'
581
-                    ),
582
-                ),
583
-                'incomplete' => array(
584
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
585
-                    'desc'  => EEH_Template::pretty_status(
586
-                        EEM_Transaction::incomplete_status_code,
587
-                        false,
588
-                        'sentence'
589
-                    ),
590
-                ),
591
-                'abandoned'  => array(
592
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
593
-                    'desc'  => EEH_Template::pretty_status(
594
-                        EEM_Transaction::abandoned_status_code,
595
-                        false,
596
-                        'sentence'
597
-                    ),
598
-                ),
599
-                'failed'     => array(
600
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
601
-                    'desc'  => EEH_Template::pretty_status(
602
-                        EEM_Transaction::failed_status_code,
603
-                        false,
604
-                        'sentence'
605
-                    ),
606
-                ),
607
-            )
608
-        );
609
-
610
-        return array_merge($items, $more_items);
611
-    }
612
-
613
-
614
-    /**
615
-     *    _transactions_overview_list_table
616
-     *
617
-     * @access protected
618
-     * @return void
619
-     * @throws DomainException
620
-     * @throws EE_Error
621
-     * @throws InvalidArgumentException
622
-     * @throws InvalidDataTypeException
623
-     * @throws InvalidInterfaceException
624
-     * @throws ReflectionException
625
-     */
626
-    protected function _transactions_overview_list_table()
627
-    {
628
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
629
-        $event = isset($this->_req_data['EVT_ID'])
630
-            ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
631
-            : null;
632
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
633
-            ? sprintf(
634
-                esc_html__(
635
-                    '%sViewing Transactions for the Event: %s%s',
636
-                    'event_espresso'
637
-                ),
638
-                '<h3>',
639
-                '<a href="'
640
-                . EE_Admin_Page::add_query_args_and_nonce(
641
-                    array('action' => 'edit', 'post' => $event->ID()),
642
-                    EVENTS_ADMIN_URL
643
-                )
644
-                . '" title="'
645
-                . esc_attr__(
646
-                    'Click to Edit event',
647
-                    'event_espresso'
648
-                )
649
-                . '">' . $event->get('EVT_name') . '</a>',
650
-                '</h3>'
651
-            )
652
-            : '';
653
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
654
-        $this->display_admin_list_table_page_with_no_sidebar();
655
-    }
656
-
657
-
658
-    /**
659
-     *    _transaction_details
660
-     * generates HTML for the View Transaction Details Admin page
661
-     *
662
-     * @access protected
663
-     * @return void
664
-     * @throws DomainException
665
-     * @throws EE_Error
666
-     * @throws InvalidArgumentException
667
-     * @throws InvalidDataTypeException
668
-     * @throws InvalidInterfaceException
669
-     * @throws RuntimeException
670
-     * @throws ReflectionException
671
-     */
672
-    protected function _transaction_details()
673
-    {
674
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
675
-
676
-        $this->_set_transaction_status_array();
677
-
678
-        $this->_template_args                      = array();
679
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
680
-
681
-        $this->_set_transaction_object();
682
-
683
-        $primary_registration = $this->_transaction->primary_registration();
684
-        $attendee = $primary_registration instanceof EE_Registration
685
-            ? $primary_registration->attendee()
686
-            : null;
687
-
688
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
689
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
690
-
691
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
692
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
693
-
694
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
695
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
696
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
697
-
698
-        $this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
699
-        $this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
700
-
701
-        $amount_due = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
702
-        $this->_template_args['amount_due'] = EEH_Template::format_currency(
703
-            $amount_due,
704
-            true
705
-        );
706
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
707
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
708
-                                                  . $this->_template_args['amount_due'];
709
-        } else {
710
-            $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
711
-        }
712
-        $this->_template_args['amount_due_class'] = '';
713
-
714
-        if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
715
-            // paid in full
716
-            $this->_template_args['amount_due'] = false;
717
-        } elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
718
-            // overpaid
719
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
720
-        } elseif ($this->_transaction->get('TXN_total') > 0
721
-                  && $this->_transaction->get('TXN_paid') > 0
722
-        ) {
723
-            // monies owing
724
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
725
-        } elseif ($this->_transaction->get('TXN_total') > 0
726
-                  && $this->_transaction->get('TXN_paid') == 0
727
-        ) {
728
-            // no payments made yet
729
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
730
-        } elseif ($this->_transaction->get('TXN_total') == 0) {
731
-            // free event
732
-            $this->_template_args['amount_due'] = false;
733
-        }
734
-
735
-        $payment_method = $this->_transaction->payment_method();
736
-
737
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
738
-            ? $payment_method->admin_name()
739
-            : esc_html__('Unknown', 'event_espresso');
740
-
741
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
742
-        // link back to overview
743
-        $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
744
-            ? $_SERVER['HTTP_REFERER']
745
-            : TXN_ADMIN_URL;
746
-
747
-
748
-        // next link
749
-        $next_txn                                 = $this->_transaction->next(
750
-            null,
751
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
752
-            'TXN_ID'
753
-        );
754
-        $this->_template_args['next_transaction'] = $next_txn
755
-            ? $this->_next_link(
756
-                EE_Admin_Page::add_query_args_and_nonce(
757
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
758
-                    TXN_ADMIN_URL
759
-                ),
760
-                'dashicons dashicons-arrow-right ee-icon-size-22'
761
-            )
762
-            : '';
763
-        // previous link
764
-        $previous_txn                                 = $this->_transaction->previous(
765
-            null,
766
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
767
-            'TXN_ID'
768
-        );
769
-        $this->_template_args['previous_transaction'] = $previous_txn
770
-            ? $this->_previous_link(
771
-                EE_Admin_Page::add_query_args_and_nonce(
772
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
773
-                    TXN_ADMIN_URL
774
-                ),
775
-                'dashicons dashicons-arrow-left ee-icon-size-22'
776
-            )
777
-            : '';
778
-
779
-        // were we just redirected here after adding a new registration ???
780
-        if (isset(
781
-            $this->_req_data['redirect_from'],
782
-            $this->_req_data['EVT_ID'],
783
-            $this->_req_data['event_name']
784
-        )) {
785
-            if (EE_Registry::instance()->CAP->current_user_can(
786
-                'ee_edit_registrations',
787
-                'espresso_registrations_new_registration',
788
-                $this->_req_data['EVT_ID']
789
-            )) {
790
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
791
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
792
-                    array(
793
-                        'page'     => 'espresso_registrations',
794
-                        'action'   => 'new_registration',
795
-                        'return'   => 'default',
796
-                        'TXN_ID'   => $this->_transaction->ID(),
797
-                        'event_id' => $this->_req_data['EVT_ID'],
798
-                    ),
799
-                    REG_ADMIN_URL
800
-                );
801
-                $this->_admin_page_title .= '">';
802
-
803
-                $this->_admin_page_title .= sprintf(
804
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
805
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
806
-                );
807
-                $this->_admin_page_title .= '</a>';
808
-            }
809
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
810
-        }
811
-        // grab messages at the last second
812
-        $this->_template_args['notices'] = EE_Error::get_notices();
813
-        // path to template
814
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
815
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
816
-            $template_path,
817
-            $this->_template_args,
818
-            true
819
-        );
820
-
821
-        // the details template wrapper
822
-        $this->display_admin_page_with_sidebar();
823
-
824
-    }
825
-
826
-
827
-    /**
828
-     *        _transaction_details_metaboxes
829
-     *
830
-     * @access protected
831
-     * @return void
832
-     * @throws EE_Error
833
-     * @throws InvalidArgumentException
834
-     * @throws InvalidDataTypeException
835
-     * @throws InvalidInterfaceException
836
-     * @throws RuntimeException
837
-     * @throws ReflectionException
838
-     */
839
-    protected function _transaction_details_metaboxes()
840
-    {
841
-
842
-        $this->_set_transaction_object();
843
-
844
-        add_meta_box(
845
-            'edit-txn-details-mbox',
846
-            esc_html__('Transaction Details', 'event_espresso'),
847
-            array($this, 'txn_details_meta_box'),
848
-            $this->_wp_page_slug,
849
-            'normal',
850
-            'high'
851
-        );
852
-        add_meta_box(
853
-            'edit-txn-attendees-mbox',
854
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
855
-            array($this, 'txn_attendees_meta_box'),
856
-            $this->_wp_page_slug,
857
-            'normal',
858
-            'high',
859
-            array('TXN_ID' => $this->_transaction->ID())
860
-        );
861
-        add_meta_box(
862
-            'edit-txn-registrant-mbox',
863
-            esc_html__('Primary Contact', 'event_espresso'),
864
-            array($this, 'txn_registrant_side_meta_box'),
865
-            $this->_wp_page_slug,
866
-            'side',
867
-            'high'
868
-        );
869
-        add_meta_box(
870
-            'edit-txn-billing-info-mbox',
871
-            esc_html__('Billing Information', 'event_espresso'),
872
-            array($this, 'txn_billing_info_side_meta_box'),
873
-            $this->_wp_page_slug,
874
-            'side',
875
-            'high'
876
-        );
877
-    }
878
-
879
-
880
-    /**
881
-     * Callback for transaction actions metabox.
882
-     *
883
-     * @param EE_Transaction|null $transaction
884
-     * @throws DomainException
885
-     * @throws EE_Error
886
-     * @throws InvalidArgumentException
887
-     * @throws InvalidDataTypeException
888
-     * @throws InvalidInterfaceException
889
-     * @throws ReflectionException
890
-     * @throws RuntimeException
891
-     */
892
-    public function getActionButtons(EE_Transaction $transaction = null)
893
-    {
894
-        $content = '';
895
-        $actions = array();
896
-        if (! $transaction instanceof EE_Transaction) {
897
-            return $content;
898
-        }
899
-        /** @var EE_Registration $primary_registration */
900
-        $primary_registration = $transaction->primary_registration();
901
-        $attendee = $primary_registration instanceof EE_Registration
902
-            ? $primary_registration->attendee()
903
-            : null;
904
-
905
-        if ($attendee instanceof EE_Attendee
906
-            && EE_Registry::instance()->CAP->current_user_can(
907
-                'ee_send_message',
908
-                'espresso_transactions_send_payment_reminder'
909
-            )
910
-        ) {
911
-            $actions['payment_reminder'] =
912
-                EEH_MSG_Template::is_mt_active('payment_reminder')
913
-                && $this->_transaction->get('STS_ID') !== EEM_Transaction::complete_status_code
914
-                && $this->_transaction->get('STS_ID') !== EEM_Transaction::overpaid_status_code
915
-                    ? EEH_Template::get_button_or_link(
916
-                        EE_Admin_Page::add_query_args_and_nonce(
917
-                            array(
918
-                                'action'      => 'send_payment_reminder',
919
-                                'TXN_ID'      => $this->_transaction->ID(),
920
-                                'redirect_to' => 'view_transaction',
921
-                            ),
922
-                            TXN_ADMIN_URL
923
-                        ),
924
-                        esc_html__(' Send Payment Reminder', 'event_espresso'),
925
-                        'button secondary-button',
926
-                        'dashicons dashicons-email-alt'
927
-                    )
928
-                    : '';
929
-        }
930
-
931
-        if ($primary_registration instanceof EE_Registration
932
-            && EEH_MSG_Template::is_mt_active('receipt')
933
-        ) {
934
-            $actions['receipt'] = EEH_Template::get_button_or_link(
935
-                $primary_registration->receipt_url(),
936
-                esc_html__('View Receipt', 'event_espresso'),
937
-                'button secondary-button',
938
-                'dashicons dashicons-media-default'
939
-            );
940
-        }
941
-
942
-        if ($primary_registration instanceof EE_Registration
943
-            && EEH_MSG_Template::is_mt_active('invoice')
944
-        ) {
945
-            $actions['invoice'] = EEH_Template::get_button_or_link(
946
-                $primary_registration->invoice_url(),
947
-                esc_html__('View Invoice', 'event_espresso'),
948
-                'button secondary-button',
949
-                'dashicons dashicons-media-spreadsheet'
950
-            );
951
-        }
952
-        $actions = array_filter(
953
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
954
-        );
955
-        if ($actions) {
956
-            $content = '<ul>';
957
-            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
958
-            $content .= '</uL>';
959
-        }
960
-        return $content;
961
-    }
962
-
963
-
964
-    /**
965
-     * txn_details_meta_box
966
-     * generates HTML for the Transaction main meta box
967
-     *
968
-     * @return void
969
-     * @throws DomainException
970
-     * @throws EE_Error
971
-     * @throws InvalidArgumentException
972
-     * @throws InvalidDataTypeException
973
-     * @throws InvalidInterfaceException
974
-     * @throws RuntimeException
975
-     * @throws ReflectionException
976
-     */
977
-    public function txn_details_meta_box()
978
-    {
979
-        $this->_set_transaction_object();
980
-        $this->_template_args['TXN_ID']   = $this->_transaction->ID();
981
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
982
-            ? $this->_transaction->primary_registration()->attendee()
983
-            : null;
984
-        $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
985
-            'ee_edit_payments',
986
-            'apply_payment_or_refund_from_registration_details'
987
-        );
988
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
989
-            'ee_delete_payments',
990
-            'delete_payment_from_registration_details'
991
-        );
992
-
993
-        //get line table
994
-        EEH_Autoloader::register_line_item_display_autoloaders();
995
-        $Line_Item_Display                       = new EE_Line_Item_Display(
996
-            'admin_table',
997
-            'EE_Admin_Table_Line_Item_Display_Strategy'
998
-        );
999
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1000
-            $this->_transaction->total_line_item()
1001
-        );
1002
-        $this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')
1003
-                                                                      ->get('REG_code');
1004
-
1005
-        // process taxes
1006
-        $taxes                         = $this->_transaction->get_many_related(
1007
-            'Line_Item',
1008
-            array(array('LIN_type' => EEM_Line_Item::type_tax))
1009
-        );
1010
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1011
-
1012
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1013
-            $this->_transaction->get('TXN_total'),
1014
-            false,
1015
-            false
1016
-        );
1017
-        $this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
1018
-        $this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
1019
-
1020
-        // process payment details
1021
-        $payments = $this->_transaction->get_many_related('Payment');
1022
-        if (! empty($payments)) {
1023
-            $this->_template_args['payments']              = $payments;
1024
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1025
-        } else {
1026
-            $this->_template_args['payments']              = false;
1027
-            $this->_template_args['existing_reg_payments'] = array();
1028
-        }
1029
-
1030
-        $this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1031
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1032
-            array('action' => 'espresso_delete_payment'),
1033
-            TXN_ADMIN_URL
1034
-        );
1035
-
1036
-        if (isset($txn_details['invoice_number'])) {
1037
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1038
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1039
-                'Invoice Number',
1040
-                'event_espresso'
1041
-            );
1042
-        }
1043
-
1044
-        $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
1045
-            ->get_first_related('Registration')
1046
-            ->get('REG_session');
1047
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1048
-            'Registration Session',
1049
-            'event_espresso'
1050
-        );
1051
-
1052
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1053
-            ? $this->_session['ip_address']
1054
-            : '';
1055
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1056
-            'Transaction placed from IP',
1057
-            'event_espresso'
1058
-        );
1059
-
1060
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1061
-            ? $this->_session['user_agent']
1062
-            : '';
1063
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1064
-            'Registrant User Agent',
1065
-            'event_espresso'
1066
-        );
1067
-
1068
-        $reg_steps = '<ul>';
1069
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1070
-            if ($reg_step_status === true) {
1071
-                $reg_steps .= '<li style="color:#70cc50">'
1072
-                              . sprintf(
1073
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1074
-                                  ucwords(str_replace('_', ' ', $reg_step))
1075
-                              )
1076
-                              . '</li>';
1077
-            } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1078
-                $reg_steps .= '<li style="color:#2EA2CC">'
1079
-                              . sprintf(
1080
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1081
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1082
-                                  date(
1083
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1084
-                                      ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1085
-                                  )
1086
-                              )
1087
-                              . '</li>';
1088
-            } else {
1089
-                $reg_steps .= '<li style="color:#E76700">'
1090
-                              . sprintf(
1091
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1092
-                                  ucwords(str_replace('_', ' ', $reg_step))
1093
-                              )
1094
-                              . '</li>';
1095
-            }
1096
-        }
1097
-        $reg_steps                                                 .= '</ul>';
1098
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1099
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1100
-            'Registration Step Progress',
1101
-            'event_espresso'
1102
-        );
1103
-
1104
-
1105
-        $this->_get_registrations_to_apply_payment_to();
1106
-        $this->_get_payment_methods($payments);
1107
-        $this->_get_payment_status_array();
1108
-        $this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
1109
-
1110
-        $this->_template_args['transaction_form_url']    = add_query_arg(array(
1111
-            'action'  => 'edit_transaction',
1112
-            'process' => 'transaction',
1113
-        ), TXN_ADMIN_URL);
1114
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(array(
1115
-            'page'   => 'espresso_transactions',
1116
-            'action' => 'espresso_apply_payment',
1117
-        ), WP_AJAX_URL);
1118
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(array(
1119
-            'page'   => 'espresso_transactions',
1120
-            'action' => 'espresso_delete_payment',
1121
-        ), WP_AJAX_URL);
1122
-
1123
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1124
-
1125
-        // 'espresso_delete_payment_nonce'
1126
-
1127
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1128
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1129
-    }
1130
-
1131
-
1132
-    /**
1133
-     * _get_registration_payment_IDs
1134
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1135
-     *
1136
-     * @access protected
1137
-     * @param EE_Payment[] $payments
1138
-     * @return array
1139
-     * @throws EE_Error
1140
-     * @throws InvalidArgumentException
1141
-     * @throws InvalidDataTypeException
1142
-     * @throws InvalidInterfaceException
1143
-     * @throws ReflectionException
1144
-     */
1145
-    protected function _get_registration_payment_IDs($payments = array())
1146
-    {
1147
-        $existing_reg_payments = array();
1148
-        // get all reg payments for these payments
1149
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(array(
1150
-            array(
1151
-                'PAY_ID' => array(
1152
-                    'IN',
1153
-                    array_keys($payments),
1154
-                ),
1155
-            ),
1156
-        ));
1157
-        if (! empty($reg_payments)) {
1158
-            foreach ($payments as $payment) {
1159
-                if (! $payment instanceof EE_Payment) {
1160
-                    continue;
1161
-                } elseif (! isset($existing_reg_payments[$payment->ID()])) {
1162
-                    $existing_reg_payments[$payment->ID()] = array();
1163
-                }
1164
-                foreach ($reg_payments as $reg_payment) {
1165
-                    if ($reg_payment instanceof EE_Registration_Payment
1166
-                        && $reg_payment->payment_ID() === $payment->ID()
1167
-                    ) {
1168
-                        $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
1169
-                    }
1170
-                }
1171
-            }
1172
-        }
1173
-
1174
-        return $existing_reg_payments;
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * _get_registrations_to_apply_payment_to
1180
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1181
-     * which allows the admin to only apply the payment to the specific registrations
1182
-     *
1183
-     * @access protected
1184
-     * @return void
1185
-     * @throws \EE_Error
1186
-     */
1187
-    protected function _get_registrations_to_apply_payment_to()
1188
-    {
1189
-        // we want any registration with an active status (ie: not deleted or cancelled)
1190
-        $query_params                      = array(
1191
-            array(
1192
-                'STS_ID' => array(
1193
-                    'IN',
1194
-                    array(
1195
-                        EEM_Registration::status_id_approved,
1196
-                        EEM_Registration::status_id_pending_payment,
1197
-                        EEM_Registration::status_id_not_approved,
1198
-                    ),
1199
-                ),
1200
-            ),
1201
-        );
1202
-        $registrations_to_apply_payment_to = EEH_HTML::br()
1203
-                                             . EEH_HTML::div(
1204
-                                                 '',
1205
-                                                 'txn-admin-apply-payment-to-registrations-dv',
1206
-                                                 '',
1207
-                                                 'clear: both; margin: 1.5em 0 0; display: none;'
1208
-                                             );
1209
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1210
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1211
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1212
-            EEH_HTML::tr(
1213
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1214
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1215
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1216
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1217
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1218
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1219
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1220
-            )
1221
-        );
1222
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1223
-        // get registrations for TXN
1224
-        $registrations = $this->_transaction->registrations($query_params);
1225
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1226
-        foreach ($registrations as $registration) {
1227
-            if ($registration instanceof EE_Registration) {
1228
-                $attendee_name                     = $registration->attendee() instanceof EE_Attendee
1229
-                    ? $registration->attendee()->full_name()
1230
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1231
-                $owing                             = $registration->final_price() - $registration->paid();
1232
-                $taxable                           = $registration->ticket()->taxable()
1233
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1234
-                    : '';
1235
-                $checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1236
-                    ? ' checked="checked"'
1237
-                    : '';
1238
-                $disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1239
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1240
-                    EEH_HTML::td($registration->ID()) .
1241
-                    EEH_HTML::td($attendee_name) .
1242
-                    EEH_HTML::td(
1243
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1244
-                    ) .
1245
-                    EEH_HTML::td($registration->event_name()) .
1246
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1247
-                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1248
-                    EEH_HTML::td(
1249
-                        '<input type="checkbox" value="' . $registration->ID()
1250
-                        . '" name="txn_admin_payment[registrations]"'
1251
-                        . $checked . $disabled . '>',
1252
-                        '',
1253
-                        'jst-cntr'
1254
-                    ),
1255
-                    'apply-payment-registration-row-' . $registration->ID()
1256
-                );
1257
-            }
1258
-        }
1259
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1260
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1261
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1262
-        $registrations_to_apply_payment_to                         .= EEH_HTML::p(
1263
-            esc_html__(
1264
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1265
-                'event_espresso'
1266
-            ),
1267
-            '',
1268
-            'clear description'
1269
-        );
1270
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1271
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1272
-    }
1273
-
1274
-
1275
-    /**
1276
-     * _get_reg_status_selection
1277
-     *
1278
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1279
-     *         instead of events.
1280
-     * @access protected
1281
-     * @return void
1282
-     * @throws EE_Error
1283
-     */
1284
-    protected function _get_reg_status_selection()
1285
-    {
1286
-        //first get all possible statuses
1287
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1288
-        //let's add a "don't change" option.
1289
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1290
-        $status_array                                        = array_merge($status_array, $statuses);
1291
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1292
-            'txn_reg_status_change[reg_status]',
1293
-            $status_array,
1294
-            'NAN',
1295
-            'id="txn-admin-payment-reg-status-inp"',
1296
-            'txn-reg-status-change-reg-status'
1297
-        );
1298
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1299
-            'delete_txn_reg_status_change[reg_status]',
1300
-            $status_array,
1301
-            'NAN',
1302
-            'delete-txn-admin-payment-reg-status-inp',
1303
-            'delete-txn-reg-status-change-reg-status'
1304
-        );
1305
-    }
1306
-
1307
-
1308
-    /**
1309
-     *    _get_payment_methods
1310
-     * Gets all the payment methods available generally, or the ones that are already
1311
-     * selected on these payments (in case their payment methods are no longer active).
1312
-     * Has the side-effect of updating the template args' payment_methods item
1313
-     *
1314
-     * @access private
1315
-     * @param EE_Payment[] to show on this page
1316
-     * @return void
1317
-     * @throws EE_Error
1318
-     * @throws InvalidArgumentException
1319
-     * @throws InvalidDataTypeException
1320
-     * @throws InvalidInterfaceException
1321
-     * @throws ReflectionException
1322
-     */
1323
-    private function _get_payment_methods($payments = array())
1324
-    {
1325
-        $payment_methods_of_payments = array();
1326
-        foreach ($payments as $payment) {
1327
-            if ($payment instanceof EE_Payment) {
1328
-                $payment_methods_of_payments[] = $payment->get('PMD_ID');
1329
-            }
1330
-        }
1331
-        if ($payment_methods_of_payments) {
1332
-            $query_args = array(
1333
-                array(
1334
-                    'OR*payment_method_for_payment' => array(
1335
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1336
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1337
-                    ),
1338
-                ),
1339
-            );
1340
-        } else {
1341
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1342
-        }
1343
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1344
-    }
1345
-
1346
-
1347
-    /**
1348
-     * txn_attendees_meta_box
1349
-     *    generates HTML for the Attendees Transaction main meta box
1350
-     *
1351
-     * @access public
1352
-     * @param WP_Post $post
1353
-     * @param array   $metabox
1354
-     * @return void
1355
-     * @throws DomainException
1356
-     * @throws EE_Error
1357
-     */
1358
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1359
-    {
1360
-
1361
-        /** @noinspection NonSecureExtractUsageInspection */
1362
-        extract($metabox['args']);
1363
-        $this->_template_args['post']            = $post;
1364
-        $this->_template_args['event_attendees'] = array();
1365
-        // process items in cart
1366
-        $line_items = $this->_transaction->get_many_related(
1367
-            'Line_Item',
1368
-            array(array('LIN_type' => 'line-item'))
1369
-        );
1370
-        if (! empty($line_items)) {
1371
-            foreach ($line_items as $item) {
1372
-                if ($item instanceof EE_Line_Item) {
1373
-                    switch ($item->OBJ_type()) {
1374
-                        case 'Event':
1375
-                            break;
1376
-                        case 'Ticket':
1377
-                            $ticket = $item->ticket();
1378
-                            //right now we're only handling tickets here.
1379
-                            //Cause its expected that only tickets will have attendees right?
1380
-                            if (! $ticket instanceof EE_Ticket) {
1381
-                                continue;
1382
-                            }
1383
-                            try {
1384
-                                $event_name = $ticket->get_event_name();
1385
-                            } catch (Exception $e) {
1386
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1387
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1388
-                            }
1389
-                            $event_name   .= ' - ' . $item->get('LIN_name');
1390
-                            $ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1391
-                            // now get all of the registrations for this transaction that use this ticket
1392
-                            $registrations = $ticket->get_many_related(
1393
-                                'Registration',
1394
-                                array(array('TXN_ID' => $this->_transaction->ID()))
1395
-                            );
1396
-                            foreach ($registrations as $registration) {
1397
-                                if (! $registration instanceof EE_Registration) {
1398
-                                    continue;
1399
-                                }
1400
-                                $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
1401
-                                    = $registration->status_ID();
1402
-                                $this->_template_args['event_attendees'][$registration->ID()]['att_num']
1403
-                                    = $registration->count();
1404
-                                $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name']
1405
-                                    = $event_name;
1406
-                                $this->_template_args['event_attendees'][$registration->ID()]['ticket_price']
1407
-                                    = $ticket_price;
1408
-                                // attendee info
1409
-                                $attendee = $registration->get_first_related('Attendee');
1410
-                                if ($attendee instanceof EE_Attendee) {
1411
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']
1412
-                                        = $attendee->ID();
1413
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee']
1414
-                                        = $attendee->full_name();
1415
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']
1416
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1417
-                                          . esc_html__(
1418
-                                              ' Event',
1419
-                                              'event_espresso'
1420
-                                          )
1421
-                                          . '">' . $attendee->email() . '</a>';
1422
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']
1423
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1424
-                                } else {
1425
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1426
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1427
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1428
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1429
-                                }
1430
-                            }
1431
-                            break;
1432
-
1433
-                    }
1434
-                }
1435
-            }
1436
-
1437
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1438
-                array(
1439
-                    'action'  => 'edit_transaction',
1440
-                    'process' => 'attendees',
1441
-                ),
1442
-                TXN_ADMIN_URL
1443
-            );
1444
-            echo EEH_Template::display_template(
1445
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1446
-                $this->_template_args,
1447
-                true
1448
-            );
1449
-
1450
-        } else {
1451
-            echo sprintf(
1452
-                esc_html__(
1453
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1454
-                    'event_espresso'
1455
-                ),
1456
-                '<p class="important-notice">',
1457
-                '</p>'
1458
-            );
1459
-        }
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * txn_registrant_side_meta_box
1465
-     * generates HTML for the Edit Transaction side meta box
1466
-     *
1467
-     * @access public
1468
-     * @return void
1469
-     * @throws DomainException
1470
-     * @throws EE_Error
1471
-     * @throws InvalidArgumentException
1472
-     * @throws InvalidDataTypeException
1473
-     * @throws InvalidInterfaceException
1474
-     * @throws ReflectionException
1475
-     */
1476
-    public function txn_registrant_side_meta_box()
1477
-    {
1478
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1479
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1480
-            : null;
1481
-        if (! $primary_att instanceof EE_Attendee) {
1482
-            $this->_template_args['no_attendee_message'] = esc_html__(
1483
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1484
-                'event_espresso'
1485
-            );
1486
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1487
-        }
1488
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1489
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1490
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1491
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1492
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1493
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1494
-            'action' => 'edit_attendee',
1495
-            'post'   => $primary_att->ID(),
1496
-        ), REG_ADMIN_URL);
1497
-        // get formatted address for registrant
1498
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1499
-        echo EEH_Template::display_template(
1500
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1501
-            $this->_template_args,
1502
-            true
1503
-        );
1504
-    }
1505
-
1506
-
1507
-    /**
1508
-     * txn_billing_info_side_meta_box
1509
-     *    generates HTML for the Edit Transaction side meta box
1510
-     *
1511
-     * @access public
1512
-     * @return void
1513
-     * @throws DomainException
1514
-     * @throws EE_Error
1515
-     */
1516
-    public function txn_billing_info_side_meta_box()
1517
-    {
1518
-
1519
-        $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1520
-        $this->_template_args['billing_form_url'] = add_query_arg(
1521
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1522
-            TXN_ADMIN_URL
1523
-        );
1524
-
1525
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1526
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1527
-    }
1528
-
1529
-
1530
-    /**
1531
-     * apply_payments_or_refunds
1532
-     *    registers a payment or refund made towards a transaction
1533
-     *
1534
-     * @access public
1535
-     * @return void
1536
-     * @throws EE_Error
1537
-     * @throws InvalidArgumentException
1538
-     * @throws ReflectionException
1539
-     * @throws RuntimeException
1540
-     * @throws InvalidDataTypeException
1541
-     * @throws InvalidInterfaceException
1542
-     */
1543
-    public function apply_payments_or_refunds()
1544
-    {
1545
-        $json_response_data = array('return_data' => false);
1546
-        $valid_data         = $this->_validate_payment_request_data();
1547
-        $has_access = EE_Registry::instance()->CAP->current_user_can(
1548
-            'ee_edit_payments',
1549
-            'apply_payment_or_refund_from_registration_details'
1550
-        );
1551
-        if (! empty($valid_data) && $has_access) {
1552
-            $PAY_ID = $valid_data['PAY_ID'];
1553
-            //save  the new payment
1554
-            $payment = $this->_create_payment_from_request_data($valid_data);
1555
-            // get the TXN for this payment
1556
-            $transaction = $payment->transaction();
1557
-            // verify transaction
1558
-            if ($transaction instanceof EE_Transaction) {
1559
-                // calculate_total_payments_and_update_status
1560
-                $this->_process_transaction_payments($transaction);
1561
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1562
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1563
-                // apply payment to registrations (if applicable)
1564
-                if (! empty($REG_IDs)) {
1565
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1566
-                    $this->_maybe_send_notifications();
1567
-                    // now process status changes for the same registrations
1568
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1569
-                }
1570
-                $this->_maybe_send_notifications($payment);
1571
-                //prepare to render page
1572
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1573
-                do_action(
1574
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1575
-                    $transaction,
1576
-                    $payment
1577
-                );
1578
-            } else {
1579
-                EE_Error::add_error(
1580
-                    esc_html__(
1581
-                        'A valid Transaction for this payment could not be retrieved.',
1582
-                        'event_espresso'
1583
-                    ),
1584
-                    __FILE__,
1585
-                    __FUNCTION__,
1586
-                    __LINE__
1587
-                );
1588
-            }
1589
-        } else {
1590
-            if ($has_access) {
1591
-                EE_Error::add_error(
1592
-                    esc_html__(
1593
-                        'The payment form data could not be processed. Please try again.',
1594
-                        'event_espresso'
1595
-                    ),
1596
-                    __FILE__,
1597
-                    __FUNCTION__,
1598
-                    __LINE__
1599
-                );
1600
-            } else {
1601
-                EE_Error::add_error(
1602
-                    esc_html__(
1603
-                        'You do not have access to apply payments or refunds to a registration.',
1604
-                        'event_espresso'
1605
-                    ),
1606
-                    __FILE__,
1607
-                    __FUNCTION__,
1608
-                    __LINE__
1609
-                );
1610
-            }
1611
-        }
1612
-        $notices              = EE_Error::get_notices(
1613
-            false,
1614
-            false,
1615
-            false
1616
-        );
1617
-        $this->_template_args = array(
1618
-            'data'    => $json_response_data,
1619
-            'error'   => $notices['errors'],
1620
-            'success' => $notices['success'],
1621
-        );
1622
-        $this->_return_json();
1623
-    }
1624
-
1625
-
1626
-    /**
1627
-     * _validate_payment_request_data
1628
-     *
1629
-     * @return array
1630
-     * @throws EE_Error
1631
-     */
1632
-    protected function _validate_payment_request_data()
1633
-    {
1634
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1635
-            return false;
1636
-        }
1637
-        $payment_form = $this->_generate_payment_form_section();
1638
-        try {
1639
-            if ($payment_form->was_submitted()) {
1640
-                $payment_form->receive_form_submission();
1641
-                if (! $payment_form->is_valid()) {
1642
-                    $submission_error_messages = array();
1643
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1644
-                        if ($validation_error instanceof EE_Validation_Error) {
1645
-                            $submission_error_messages[] = sprintf(
1646
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1647
-                                $validation_error->get_form_section()->html_label_text(),
1648
-                                $validation_error->getMessage()
1649
-                            );
1650
-                        }
1651
-                    }
1652
-                    EE_Error::add_error(
1653
-                        implode('<br />', $submission_error_messages),
1654
-                        __FILE__,
1655
-                        __FUNCTION__,
1656
-                        __LINE__
1657
-                    );
1658
-
1659
-                    return array();
1660
-                }
1661
-            }
1662
-        } catch (EE_Error $e) {
1663
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1664
-
1665
-            return array();
1666
-        }
1667
-
1668
-        return $payment_form->valid_data();
1669
-    }
1670
-
1671
-
1672
-    /**
1673
-     * _generate_payment_form_section
1674
-     *
1675
-     * @return EE_Form_Section_Proper
1676
-     * @throws EE_Error
1677
-     */
1678
-    protected function _generate_payment_form_section()
1679
-    {
1680
-        return new EE_Form_Section_Proper(
1681
-            array(
1682
-                'name'        => 'txn_admin_payment',
1683
-                'subsections' => array(
1684
-                    'PAY_ID'          => new EE_Text_Input(
1685
-                        array(
1686
-                            'default'               => 0,
1687
-                            'required'              => false,
1688
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1689
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1690
-                        )
1691
-                    ),
1692
-                    'TXN_ID'          => new EE_Text_Input(
1693
-                        array(
1694
-                            'default'               => 0,
1695
-                            'required'              => true,
1696
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1697
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1698
-                        )
1699
-                    ),
1700
-                    'type'            => new EE_Text_Input(
1701
-                        array(
1702
-                            'default'               => 1,
1703
-                            'required'              => true,
1704
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1705
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1706
-                        )
1707
-                    ),
1708
-                    'amount'          => new EE_Text_Input(
1709
-                        array(
1710
-                            'default'               => 0,
1711
-                            'required'              => true,
1712
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1713
-                            'validation_strategies' => array(new EE_Float_Normalization()),
1714
-                        )
1715
-                    ),
1716
-                    'status'          => new EE_Text_Input(
1717
-                        array(
1718
-                            'default'         => EEM_Payment::status_id_approved,
1719
-                            'required'        => true,
1720
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1721
-                        )
1722
-                    ),
1723
-                    'PMD_ID'          => new EE_Text_Input(
1724
-                        array(
1725
-                            'default'               => 2,
1726
-                            'required'              => true,
1727
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1728
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1729
-                        )
1730
-                    ),
1731
-                    'date'            => new EE_Text_Input(
1732
-                        array(
1733
-                            'default'         => time(),
1734
-                            'required'        => true,
1735
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1736
-                        )
1737
-                    ),
1738
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1739
-                        array(
1740
-                            'default'               => '',
1741
-                            'required'              => false,
1742
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1743
-                            'validation_strategies' => array(
1744
-                                new EE_Max_Length_Validation_Strategy(
1745
-                                    esc_html__('Input too long', 'event_espresso'),
1746
-                                    100
1747
-                                ),
1748
-                            ),
1749
-                        )
1750
-                    ),
1751
-                    'po_number'       => new EE_Text_Input(
1752
-                        array(
1753
-                            'default'               => '',
1754
-                            'required'              => false,
1755
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1756
-                            'validation_strategies' => array(
1757
-                                new EE_Max_Length_Validation_Strategy(
1758
-                                    esc_html__('Input too long', 'event_espresso'),
1759
-                                    100
1760
-                                ),
1761
-                            ),
1762
-                        )
1763
-                    ),
1764
-                    'accounting'      => new EE_Text_Input(
1765
-                        array(
1766
-                            'default'               => '',
1767
-                            'required'              => false,
1768
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1769
-                            'validation_strategies' => array(
1770
-                                new EE_Max_Length_Validation_Strategy(
1771
-                                    esc_html__('Input too long', 'event_espresso'),
1772
-                                    100
1773
-                                ),
1774
-                            ),
1775
-                        )
1776
-                    ),
1777
-                ),
1778
-            )
1779
-        );
1780
-    }
1781
-
1782
-
1783
-    /**
1784
-     * _create_payment_from_request_data
1785
-     *
1786
-     * @param array $valid_data
1787
-     * @return EE_Payment
1788
-     * @throws EE_Error
1789
-     */
1790
-    protected function _create_payment_from_request_data($valid_data)
1791
-    {
1792
-        $PAY_ID = $valid_data['PAY_ID'];
1793
-        // get payment amount
1794
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1795
-        // payments have a type value of 1 and refunds have a type value of -1
1796
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1797
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1798
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1799
-        $date    = $valid_data['date']
1800
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1801
-            : date('Y-m-d g:i a', current_time('timestamp'));
1802
-        $payment = EE_Payment::new_instance(
1803
-            array(
1804
-                'TXN_ID'              => $valid_data['TXN_ID'],
1805
-                'STS_ID'              => $valid_data['status'],
1806
-                'PAY_timestamp'       => $date,
1807
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1808
-                'PMD_ID'              => $valid_data['PMD_ID'],
1809
-                'PAY_amount'          => $amount,
1810
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1811
-                'PAY_po_number'       => $valid_data['po_number'],
1812
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1813
-                'PAY_details'         => $valid_data,
1814
-                'PAY_ID'              => $PAY_ID,
1815
-            ),
1816
-            '',
1817
-            array('Y-m-d', 'g:i a')
1818
-        );
1819
-
1820
-        if (! $payment->save()) {
1821
-            EE_Error::add_error(
1822
-                sprintf(
1823
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1824
-                    $payment->ID()
1825
-                ),
1826
-                __FILE__, __FUNCTION__, __LINE__
1827
-            );
1828
-        }
1829
-
1830
-        return $payment;
1831
-    }
1832
-
1833
-
1834
-    /**
1835
-     * _process_transaction_payments
1836
-     *
1837
-     * @param \EE_Transaction $transaction
1838
-     * @return void
1839
-     * @throws EE_Error
1840
-     * @throws InvalidArgumentException
1841
-     * @throws ReflectionException
1842
-     * @throws InvalidDataTypeException
1843
-     * @throws InvalidInterfaceException
1844
-     */
1845
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1846
-    {
1847
-        /** @type EE_Transaction_Payments $transaction_payments */
1848
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1849
-        //update the transaction with this payment
1850
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1851
-            EE_Error::add_success(esc_html__(
1852
-                'The payment has been processed successfully.', 'event_espresso'),
1853
-                __FILE__,
1854
-                __FUNCTION__,
1855
-                __LINE__
1856
-            );
1857
-        } else {
1858
-            EE_Error::add_error(
1859
-                esc_html__(
1860
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1861
-                    'event_espresso'
1862
-                )
1863
-                ,
1864
-                __FILE__,
1865
-                __FUNCTION__,
1866
-                __LINE__
1867
-            );
1868
-        }
1869
-    }
1870
-
1871
-
1872
-    /**
1873
-     * _get_REG_IDs_to_apply_payment_to
1874
-     * returns a list of registration IDs that the payment will apply to
1875
-     *
1876
-     * @param \EE_Payment $payment
1877
-     * @return array
1878
-     * @throws EE_Error
1879
-     */
1880
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1881
-    {
1882
-        $REG_IDs = array();
1883
-        // grab array of IDs for specific registrations to apply changes to
1884
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1885
-            $REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1886
-        }
1887
-        //nothing specified ? then get all reg IDs
1888
-        if (empty($REG_IDs)) {
1889
-            $registrations = $payment->transaction()->registrations();
1890
-            $REG_IDs       = ! empty($registrations)
1891
-                ? array_keys($registrations)
1892
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1893
-        }
1894
-
1895
-        // ensure that REG_IDs are integers and NOT strings
1896
-        return array_map('intval', $REG_IDs);
1897
-    }
1898
-
1899
-
1900
-    /**
1901
-     * @return array
1902
-     */
1903
-    public function existing_reg_payment_REG_IDs()
1904
-    {
1905
-        return $this->_existing_reg_payment_REG_IDs;
1906
-    }
1907
-
1908
-
1909
-    /**
1910
-     * @param array $existing_reg_payment_REG_IDs
1911
-     */
1912
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1913
-    {
1914
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1915
-    }
1916
-
1917
-
1918
-    /**
1919
-     * _get_existing_reg_payment_REG_IDs
1920
-     * returns a list of registration IDs that the payment is currently related to
1921
-     * as recorded in the database
1922
-     *
1923
-     * @param \EE_Payment $payment
1924
-     * @return array
1925
-     * @throws EE_Error
1926
-     */
1927
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1928
-    {
1929
-        if ($this->existing_reg_payment_REG_IDs() === null) {
1930
-            // let's get any existing reg payment records for this payment
1931
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1932
-            // but we only want the REG IDs, so grab the array keys
1933
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
1934
-                ? array_keys($existing_reg_payment_REG_IDs)
1935
-                : array();
1936
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1937
-        }
1938
-
1939
-        return $this->existing_reg_payment_REG_IDs();
1940
-    }
1941
-
1942
-
1943
-    /**
1944
-     * _remove_existing_registration_payments
1945
-     * this calculates the difference between existing relations
1946
-     * to the supplied payment and the new list registration IDs,
1947
-     * removes any related registrations that no longer apply,
1948
-     * and then updates the registration paid fields
1949
-     *
1950
-     * @param \EE_Payment $payment
1951
-     * @param int         $PAY_ID
1952
-     * @return bool;
1953
-     * @throws EE_Error
1954
-     * @throws InvalidArgumentException
1955
-     * @throws ReflectionException
1956
-     * @throws InvalidDataTypeException
1957
-     * @throws InvalidInterfaceException
1958
-     */
1959
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1960
-    {
1961
-        // newly created payments will have nothing recorded for $PAY_ID
1962
-        if ($PAY_ID == 0) {
1963
-            return false;
1964
-        }
1965
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1966
-        if (empty($existing_reg_payment_REG_IDs)) {
1967
-            return false;
1968
-        }
1969
-        /** @type EE_Transaction_Payments $transaction_payments */
1970
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1971
-
1972
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
1973
-            $payment,
1974
-            array(
1975
-                array(
1976
-                    'PAY_ID' => $payment->ID(),
1977
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1978
-                ),
1979
-            )
1980
-        );
1981
-    }
1982
-
1983
-
1984
-    /**
1985
-     * _update_registration_payments
1986
-     * this applies the payments to the selected registrations
1987
-     * but only if they have not already been paid for
1988
-     *
1989
-     * @param  EE_Transaction $transaction
1990
-     * @param \EE_Payment     $payment
1991
-     * @param array           $REG_IDs
1992
-     * @return void
1993
-     * @throws EE_Error
1994
-     * @throws InvalidArgumentException
1995
-     * @throws ReflectionException
1996
-     * @throws RuntimeException
1997
-     * @throws InvalidDataTypeException
1998
-     * @throws InvalidInterfaceException
1999
-     */
2000
-    protected function _update_registration_payments(
2001
-        EE_Transaction $transaction,
2002
-        EE_Payment $payment,
2003
-        $REG_IDs = array()
2004
-    ) {
2005
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2006
-        // so let's do that using our set of REG_IDs from the form
2007
-        $registration_query_where_params = array(
2008
-            'REG_ID' => array('IN', $REG_IDs),
2009
-        );
2010
-        // but add in some conditions regarding payment,
2011
-        // so that we don't apply payments to registrations that are free or have already been paid for
2012
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2013
-        if (! $payment->is_a_refund()) {
2014
-            $registration_query_where_params['REG_final_price']  = array('!=', 0);
2015
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2016
-        }
2017
-        $registrations = $transaction->registrations(array($registration_query_where_params));
2018
-        if (! empty($registrations)) {
2019
-            /** @type EE_Payment_Processor $payment_processor */
2020
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2021
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2022
-        }
2023
-    }
2024
-
2025
-
2026
-    /**
2027
-     * _process_registration_status_change
2028
-     * This processes requested registration status changes for all the registrations
2029
-     * on a given transaction and (optionally) sends out notifications for the changes.
2030
-     *
2031
-     * @param  EE_Transaction $transaction
2032
-     * @param array           $REG_IDs
2033
-     * @return bool
2034
-     * @throws EE_Error
2035
-     * @throws InvalidArgumentException
2036
-     * @throws ReflectionException
2037
-     * @throws InvalidDataTypeException
2038
-     * @throws InvalidInterfaceException
2039
-     */
2040
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2041
-    {
2042
-        // first if there is no change in status then we get out.
2043
-        if (
2044
-            ! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2045
-            || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2046
-        ) {
2047
-            //no error message, no change requested, just nothing to do man.
2048
-            return false;
2049
-        }
2050
-        /** @type EE_Transaction_Processor $transaction_processor */
2051
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2052
-
2053
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2054
-        return $transaction_processor->manually_update_registration_statuses(
2055
-            $transaction,
2056
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2057
-            array(array('REG_ID' => array('IN', $REG_IDs)))
2058
-        );
2059
-    }
2060
-
2061
-
2062
-    /**
2063
-     * _build_payment_json_response
2064
-     *
2065
-     * @access public
2066
-     * @param \EE_Payment $payment
2067
-     * @param array       $REG_IDs
2068
-     * @param bool | null $delete_txn_reg_status_change
2069
-     * @return array
2070
-     * @throws EE_Error
2071
-     * @throws InvalidArgumentException
2072
-     * @throws InvalidDataTypeException
2073
-     * @throws InvalidInterfaceException
2074
-     * @throws ReflectionException
2075
-     */
2076
-    protected function _build_payment_json_response(
2077
-        EE_Payment $payment,
2078
-        $REG_IDs = array(),
2079
-        $delete_txn_reg_status_change = null
2080
-    ) {
2081
-        // was the payment deleted ?
2082
-        if (is_bool($delete_txn_reg_status_change)) {
2083
-            return array(
2084
-                'PAY_ID'                       => $payment->ID(),
2085
-                'amount'                       => $payment->amount(),
2086
-                'total_paid'                   => $payment->transaction()->paid(),
2087
-                'txn_status'                   => $payment->transaction()->status_ID(),
2088
-                'pay_status'                   => $payment->STS_ID(),
2089
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2090
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2091
-            );
2092
-        } else {
2093
-            $this->_get_payment_status_array();
2094
-
2095
-            return array(
2096
-                'amount'           => $payment->amount(),
2097
-                'total_paid'       => $payment->transaction()->paid(),
2098
-                'txn_status'       => $payment->transaction()->status_ID(),
2099
-                'pay_status'       => $payment->STS_ID(),
2100
-                'PAY_ID'           => $payment->ID(),
2101
-                'STS_ID'           => $payment->STS_ID(),
2102
-                'status'           => self::$_pay_status[$payment->STS_ID()],
2103
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2104
-                'method'           => strtoupper($payment->source()),
2105
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2106
-                'gateway'          => $payment->payment_method()
2107
-                    ? $payment->payment_method()->admin_name()
2108
-                    : esc_html__("Unknown", 'event_espresso'),
2109
-                'gateway_response' => $payment->gateway_response(),
2110
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2111
-                'po_number'        => $payment->po_number(),
2112
-                'extra_accntng'    => $payment->extra_accntng(),
2113
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2114
-            );
2115
-        }
2116
-    }
2117
-
2118
-
2119
-    /**
2120
-     * delete_payment
2121
-     *    delete a payment or refund made towards a transaction
2122
-     *
2123
-     * @access public
2124
-     * @return void
2125
-     * @throws EE_Error
2126
-     * @throws InvalidArgumentException
2127
-     * @throws ReflectionException
2128
-     * @throws InvalidDataTypeException
2129
-     * @throws InvalidInterfaceException
2130
-     */
2131
-    public function delete_payment()
2132
-    {
2133
-        $json_response_data = array('return_data' => false);
2134
-        $PAY_ID             = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2135
-            ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2136
-            : 0;
2137
-        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2138
-            'ee_delete_payments',
2139
-            'delete_payment_from_registration_details'
2140
-        );
2141
-        if ($PAY_ID && $can_delete) {
2142
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2143
-                ? $this->_req_data['delete_txn_reg_status_change']
2144
-                : false;
2145
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2146
-            if ($payment instanceof EE_Payment) {
2147
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2148
-                /** @type EE_Transaction_Payments $transaction_payments */
2149
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2150
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2151
-                    $json_response_data['return_data'] = $this->_build_payment_json_response(
2152
-                        $payment,
2153
-                        $REG_IDs,
2154
-                        $delete_txn_reg_status_change
2155
-                    );
2156
-                    if ($delete_txn_reg_status_change) {
2157
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2158
-                        //MAKE sure we also add the delete_txn_req_status_change to the
2159
-                        //$_REQUEST global because that's how messages will be looking for it.
2160
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2161
-                        $this->_maybe_send_notifications();
2162
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2163
-                    }
2164
-                }
2165
-            } else {
2166
-                EE_Error::add_error(
2167
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2168
-                    __FILE__, __FUNCTION__, __LINE__
2169
-                );
2170
-            }
2171
-        } else {
2172
-            if ($can_delete) {
2173
-                EE_Error::add_error(
2174
-                    esc_html__(
2175
-                        'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2176
-                        'event_espresso'
2177
-                    ),
2178
-                    __FILE__, __FUNCTION__, __LINE__
2179
-                );
2180
-            } else {
2181
-                EE_Error::add_error(
2182
-                    esc_html__(
2183
-                        'You do not have access to delete a payment.',
2184
-                        'event_espresso'
2185
-                    ),
2186
-                    __FILE__,
2187
-                    __FUNCTION__,
2188
-                    __LINE__
2189
-                );
2190
-            }
2191
-        }
2192
-        $notices              = EE_Error::get_notices(false, false, false);
2193
-        $this->_template_args = array(
2194
-            'data'      => $json_response_data,
2195
-            'success'   => $notices['success'],
2196
-            'error'     => $notices['errors'],
2197
-            'attention' => $notices['attention'],
2198
-        );
2199
-        $this->_return_json();
2200
-    }
2201
-
2202
-
2203
-    /**
2204
-     * _registration_payment_data_array
2205
-     * adds info for 'owing' and 'paid' for each registration to the json response
2206
-     *
2207
-     * @access protected
2208
-     * @param array $REG_IDs
2209
-     * @return array
2210
-     * @throws EE_Error
2211
-     * @throws InvalidArgumentException
2212
-     * @throws InvalidDataTypeException
2213
-     * @throws InvalidInterfaceException
2214
-     * @throws ReflectionException
2215
-     */
2216
-    protected function _registration_payment_data_array($REG_IDs)
2217
-    {
2218
-        $registration_payment_data = array();
2219
-        //if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2220
-        if (! empty($REG_IDs)) {
2221
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2222
-            foreach ($registrations as $registration) {
2223
-                if ($registration instanceof EE_Registration) {
2224
-                    $registration_payment_data[$registration->ID()] = array(
2225
-                        'paid'  => $registration->pretty_paid(),
2226
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2227
-                    );
2228
-                }
2229
-            }
2230
-        }
2231
-
2232
-        return $registration_payment_data;
2233
-    }
2234
-
2235
-
2236
-    /**
2237
-     * _maybe_send_notifications
2238
-     * determines whether or not the admin has indicated that notifications should be sent.
2239
-     * If so, will toggle a filter switch for delivering registration notices.
2240
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2241
-     *
2242
-     * @access protected
2243
-     * @param \EE_Payment | null $payment
2244
-     */
2245
-    protected function _maybe_send_notifications($payment = null)
2246
-    {
2247
-        switch ($payment instanceof EE_Payment) {
2248
-            // payment notifications
2249
-            case true :
2250
-                if (
2251
-                    isset(
2252
-                        $this->_req_data['txn_payments'],
2253
-                        $this->_req_data['txn_payments']['send_notifications']
2254
-                    ) &&
2255
-                    filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2256
-                ) {
2257
-                    $this->_process_payment_notification($payment);
2258
-                }
2259
-                break;
2260
-            // registration notifications
2261
-            case false :
2262
-                if (
2263
-                    isset(
2264
-                        $this->_req_data['txn_reg_status_change'],
2265
-                        $this->_req_data['txn_reg_status_change']['send_notifications']
2266
-                    ) &&
2267
-                    filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2268
-                ) {
2269
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2270
-                }
2271
-                break;
2272
-        }
2273
-    }
2274
-
2275
-
2276
-    /**
2277
-     * _send_payment_reminder
2278
-     *    generates HTML for the View Transaction Details Admin page
2279
-     *
2280
-     * @access protected
2281
-     * @return void
2282
-     * @throws EE_Error
2283
-     * @throws InvalidArgumentException
2284
-     * @throws InvalidDataTypeException
2285
-     * @throws InvalidInterfaceException
2286
-     */
2287
-    protected function _send_payment_reminder()
2288
-    {
2289
-        $TXN_ID      = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2290
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2291
-        $query_args  = isset($this->_req_data['redirect_to']) ? array(
2292
-            'action' => $this->_req_data['redirect_to'],
2293
-            'TXN_ID' => $this->_req_data['TXN_ID'],
2294
-        ) : array();
2295
-        do_action(
2296
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2297
-            $transaction
2298
-        );
2299
-        $this->_redirect_after_action(
2300
-            false,
2301
-            esc_html__('payment reminder', 'event_espresso'),
2302
-            esc_html__('sent', 'event_espresso'),
2303
-            $query_args,
2304
-            true
2305
-        );
2306
-    }
2307
-
2308
-
2309
-    /**
2310
-     *  get_transactions
2311
-     *    get transactions for given parameters (used by list table)
2312
-     *
2313
-     * @param  int     $perpage how many transactions displayed per page
2314
-     * @param  boolean $count   return the count or objects
2315
-     * @param string   $view
2316
-     * @return mixed int = count || array of transaction objects
2317
-     * @throws EE_Error
2318
-     * @throws InvalidArgumentException
2319
-     * @throws InvalidDataTypeException
2320
-     * @throws InvalidInterfaceException
2321
-     */
2322
-    public function get_transactions($perpage, $count = false, $view = '')
2323
-    {
2324
-
2325
-        $TXN = EEM_Transaction::instance();
2326
-
2327
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
2328
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2329
-            : date(
2330
-                'm/d/Y',
2331
-                strtotime('-10 year')
2332
-            );
2333
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
2334
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2335
-            : date('m/d/Y');
2336
-
2337
-        //make sure our timestamps start and end right at the boundaries for each day
2338
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2339
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2340
-
2341
-
2342
-        //convert to timestamps
2343
-        $start_date = strtotime($start_date);
2344
-        $end_date   = strtotime($end_date);
2345
-
2346
-        //makes sure start date is the lowest value and vice versa
2347
-        $start_date = min($start_date, $end_date);
2348
-        $end_date   = max($start_date, $end_date);
2349
-
2350
-        //convert to correct format for query
2351
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2352
-            'TXN_timestamp',
2353
-            date('Y-m-d H:i:s', $start_date),
2354
-            'Y-m-d H:i:s'
2355
-        );
2356
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2357
-            'TXN_timestamp',
2358
-            date('Y-m-d H:i:s', $end_date),
2359
-            'Y-m-d H:i:s'
2360
-        );
2361
-
2362
-
2363
-        //set orderby
2364
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2365
-
2366
-        switch ($this->_req_data['orderby']) {
2367
-            case 'TXN_ID':
2368
-                $orderby = 'TXN_ID';
2369
-                break;
2370
-            case 'ATT_fname':
2371
-                $orderby = 'Registration.Attendee.ATT_fname';
2372
-                break;
2373
-            case 'event_name':
2374
-                $orderby = 'Registration.Event.EVT_name';
2375
-                break;
2376
-            default: //'TXN_timestamp'
2377
-                $orderby = 'TXN_timestamp';
2378
-        }
2379
-
2380
-        $sort         = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2381
-        $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2382
-        $per_page     = ! empty($perpage) ? $perpage : 10;
2383
-        $per_page     = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2384
-
2385
-        $offset = ($current_page - 1) * $per_page;
2386
-        $limit  = array($offset, $per_page);
2387
-
2388
-        $_where = array(
2389
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2390
-            'Registration.REG_count' => 1,
2391
-        );
2392
-
2393
-        if (isset($this->_req_data['EVT_ID'])) {
2394
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2395
-        }
2396
-
2397
-        if (isset($this->_req_data['s'])) {
2398
-            $search_string = '%' . $this->_req_data['s'] . '%';
2399
-            $_where['OR']  = array(
2400
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2401
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2402
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2403
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2404
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2405
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2406
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2407
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2408
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2409
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2410
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2411
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
2412
-                'Registration.REG_code'               => array('LIKE', $search_string),
2413
-                'Registration.REG_count'              => array('LIKE', $search_string),
2414
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
2415
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2416
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2417
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
2418
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2419
-                'TXN_session_data'                    => array('LIKE', $search_string),
2420
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2421
-            );
2422
-        }
2423
-
2424
-        //failed transactions
2425
-        $failed    = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2426
-                     || ($count && $view === 'failed');
2427
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2428
-                     || ($count && $view === 'abandoned');
2429
-
2430
-        if ($failed) {
2431
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2432
-        } else if ($abandoned) {
2433
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2434
-        } else {
2435
-            $_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
2436
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2437
-        }
2438
-
2439
-        $query_params = array(
2440
-            $_where,
2441
-            'order_by'                 => array($orderby => $sort),
2442
-            'limit'                    => $limit,
2443
-            'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2444
-        );
2445
-
2446
-        $transactions = $count
2447
-            ? $TXN->count(array($_where), 'TXN_ID', true)
2448
-            : $TXN->get_all($query_params);
2449
-
2450
-        return $transactions;
2451
-    }
19
+	/**
20
+	 * @var EE_Transaction
21
+	 */
22
+	private $_transaction;
23
+
24
+	/**
25
+	 * @var EE_Session
26
+	 */
27
+	private $_session;
28
+
29
+	/**
30
+	 * @var array $_txn_status
31
+	 */
32
+	private static $_txn_status;
33
+
34
+	/**
35
+	 * @var array $_pay_status
36
+	 */
37
+	private static $_pay_status;
38
+
39
+	/**
40
+	 * @var array $_existing_reg_payment_REG_IDs
41
+	 */
42
+	protected $_existing_reg_payment_REG_IDs = null;
43
+
44
+
45
+	/**
46
+	 * @Constructor
47
+	 * @access public
48
+	 * @param bool $routing
49
+	 * @throws EE_Error
50
+	 * @throws InvalidArgumentException
51
+	 * @throws ReflectionException
52
+	 * @throws InvalidDataTypeException
53
+	 * @throws InvalidInterfaceException
54
+	 */
55
+	public function __construct($routing = true)
56
+	{
57
+		parent::__construct($routing);
58
+	}
59
+
60
+
61
+	/**
62
+	 *    _init_page_props
63
+	 *
64
+	 * @return void
65
+	 */
66
+	protected function _init_page_props()
67
+	{
68
+		$this->page_slug        = TXN_PG_SLUG;
69
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
70
+		$this->_admin_base_url  = TXN_ADMIN_URL;
71
+		$this->_admin_base_path = TXN_ADMIN;
72
+	}
73
+
74
+
75
+	/**
76
+	 *    _ajax_hooks
77
+	 *
78
+	 * @return void
79
+	 */
80
+	protected function _ajax_hooks()
81
+	{
82
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
83
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
84
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
85
+	}
86
+
87
+
88
+	/**
89
+	 *    _define_page_props
90
+	 *
91
+	 * @return void
92
+	 */
93
+	protected function _define_page_props()
94
+	{
95
+		$this->_admin_page_title = $this->page_label;
96
+		$this->_labels           = array(
97
+			'buttons' => array(
98
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
99
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
100
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
101
+			),
102
+		);
103
+	}
104
+
105
+
106
+	/**
107
+	 *        grab url requests and route them
108
+	 *
109
+	 * @access private
110
+	 * @return void
111
+	 * @throws EE_Error
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 */
116
+	public function _set_page_routes()
117
+	{
118
+
119
+		$this->_set_transaction_status_array();
120
+
121
+		$txn_id = ! empty($this->_req_data['TXN_ID'])
122
+				  && ! is_array($this->_req_data['TXN_ID'])
123
+			? $this->_req_data['TXN_ID']
124
+			: 0;
125
+
126
+		$this->_page_routes = array(
127
+
128
+			'default' => array(
129
+				'func'       => '_transactions_overview_list_table',
130
+				'capability' => 'ee_read_transactions',
131
+			),
132
+
133
+			'view_transaction' => array(
134
+				'func'       => '_transaction_details',
135
+				'capability' => 'ee_read_transaction',
136
+				'obj_id'     => $txn_id,
137
+			),
138
+
139
+			'send_payment_reminder' => array(
140
+				'func'       => '_send_payment_reminder',
141
+				'noheader'   => true,
142
+				'capability' => 'ee_send_message',
143
+			),
144
+
145
+			'espresso_apply_payment' => array(
146
+				'func'       => 'apply_payments_or_refunds',
147
+				'noheader'   => true,
148
+				'capability' => 'ee_edit_payments',
149
+			),
150
+
151
+			'espresso_apply_refund' => array(
152
+				'func'       => 'apply_payments_or_refunds',
153
+				'noheader'   => true,
154
+				'capability' => 'ee_edit_payments',
155
+			),
156
+
157
+			'espresso_delete_payment' => array(
158
+				'func'       => 'delete_payment',
159
+				'noheader'   => true,
160
+				'capability' => 'ee_delete_payments',
161
+			),
162
+
163
+		);
164
+	}
165
+
166
+
167
+	protected function _set_page_config()
168
+	{
169
+		$this->_page_config = array(
170
+			'default'          => array(
171
+				'nav'           => array(
172
+					'label' => esc_html__('Overview', 'event_espresso'),
173
+					'order' => 10,
174
+				),
175
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
176
+				'help_tabs'     => array(
177
+					'transactions_overview_help_tab'                       => array(
178
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
179
+						'filename' => 'transactions_overview',
180
+					),
181
+					'transactions_overview_table_column_headings_help_tab' => array(
182
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
183
+						'filename' => 'transactions_overview_table_column_headings',
184
+					),
185
+					'transactions_overview_views_filters_help_tab'         => array(
186
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
187
+						'filename' => 'transactions_overview_views_filters_search',
188
+					),
189
+				),
190
+				'help_tour'     => array('Transactions_Overview_Help_Tour'),
191
+				/**
192
+				 * commented out because currently we are not displaying tips for transaction list table status but this
193
+				 * may change in a later iteration so want to keep the code for then.
194
+				 */
195
+				//'qtips' => array( 'Transactions_List_Table_Tips' ),
196
+				'require_nonce' => false,
197
+			),
198
+			'view_transaction' => array(
199
+				'nav'       => array(
200
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
201
+					'order'      => 5,
202
+					'url'        => isset($this->_req_data['TXN_ID'])
203
+						? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
204
+						: $this->_admin_base_url,
205
+					'persistent' => false,
206
+				),
207
+				'help_tabs' => array(
208
+					'transactions_view_transaction_help_tab'                                              => array(
209
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
210
+						'filename' => 'transactions_view_transaction',
211
+					),
212
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
213
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
214
+						'filename' => 'transactions_view_transaction_transaction_details_table',
215
+					),
216
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
217
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
218
+						'filename' => 'transactions_view_transaction_attendees_registered',
219
+					),
220
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
221
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
222
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
223
+					),
224
+				),
225
+				'qtips'     => array('Transaction_Details_Tips'),
226
+				'help_tour' => array('Transaction_Details_Help_Tour'),
227
+				'metaboxes' => array('_transaction_details_metaboxes'),
228
+
229
+				'require_nonce' => false,
230
+			),
231
+		);
232
+	}
233
+
234
+
235
+	/**
236
+	 * The below methods aren't used by this class currently
237
+	 */
238
+	protected function _add_screen_options()
239
+	{
240
+		//noop
241
+	}
242
+
243
+	protected function _add_feature_pointers()
244
+	{
245
+		//noop
246
+	}
247
+
248
+	public function admin_init()
249
+	{
250
+		// IF a registration was JUST added via the admin...
251
+		if (isset(
252
+			$this->_req_data['redirect_from'],
253
+			$this->_req_data['EVT_ID'],
254
+			$this->_req_data['event_name']
255
+		)) {
256
+			// then set a cookie so that we can block any attempts to use
257
+			// the back button as a way to enter another registration.
258
+			setcookie(
259
+				'ee_registration_added',
260
+				$this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/'
261
+			);
262
+			// and update the global
263
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
264
+		}
265
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
266
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
267
+			'event_espresso'
268
+		);
269
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
270
+			'An error occurred! Please refresh the page and try again.',
271
+			'event_espresso'
272
+		);
273
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
274
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
275
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
276
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
277
+			'This transaction has been overpaid ! Payments Total',
278
+			'event_espresso'
279
+		);
280
+	}
281
+
282
+	public function admin_notices()
283
+	{
284
+		//noop
285
+	}
286
+
287
+	public function admin_footer_scripts()
288
+	{
289
+		//noop
290
+	}
291
+
292
+
293
+	/**
294
+	 * _set_transaction_status_array
295
+	 * sets list of transaction statuses
296
+	 *
297
+	 * @access private
298
+	 * @return void
299
+	 * @throws EE_Error
300
+	 * @throws InvalidArgumentException
301
+	 * @throws InvalidDataTypeException
302
+	 * @throws InvalidInterfaceException
303
+	 */
304
+	private function _set_transaction_status_array()
305
+	{
306
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
307
+	}
308
+
309
+
310
+	/**
311
+	 * get_transaction_status_array
312
+	 * return the transaction status array for wp_list_table
313
+	 *
314
+	 * @access public
315
+	 * @return array
316
+	 */
317
+	public function get_transaction_status_array()
318
+	{
319
+		return self::$_txn_status;
320
+	}
321
+
322
+
323
+	/**
324
+	 *    get list of payment statuses
325
+	 *
326
+	 * @access private
327
+	 * @return void
328
+	 * @throws EE_Error
329
+	 * @throws InvalidArgumentException
330
+	 * @throws InvalidDataTypeException
331
+	 * @throws InvalidInterfaceException
332
+	 */
333
+	private function _get_payment_status_array()
334
+	{
335
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
336
+		$this->_template_args['payment_status'] = self::$_pay_status;
337
+
338
+	}
339
+
340
+
341
+	/**
342
+	 *    _add_screen_options_default
343
+	 *
344
+	 * @access protected
345
+	 * @return void
346
+	 * @throws InvalidArgumentException
347
+	 * @throws InvalidDataTypeException
348
+	 * @throws InvalidInterfaceException
349
+	 */
350
+	protected function _add_screen_options_default()
351
+	{
352
+		$this->_per_page_screen_option();
353
+	}
354
+
355
+
356
+	/**
357
+	 * load_scripts_styles
358
+	 *
359
+	 * @access public
360
+	 * @return void
361
+	 */
362
+	public function load_scripts_styles()
363
+	{
364
+		//enqueue style
365
+		wp_register_style(
366
+			'espresso_txn',
367
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
368
+			array(),
369
+			EVENT_ESPRESSO_VERSION
370
+		);
371
+		wp_enqueue_style('espresso_txn');
372
+		//scripts
373
+		wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
374
+			'ee_admin_js',
375
+			'ee-datepicker',
376
+			'jquery-ui-datepicker',
377
+			'jquery-ui-draggable',
378
+			'ee-dialog',
379
+			'ee-accounting',
380
+			'ee-serialize-full-array',
381
+		), EVENT_ESPRESSO_VERSION, true);
382
+		wp_enqueue_script('espresso_txn');
383
+	}
384
+
385
+
386
+	/**
387
+	 *    load_scripts_styles_view_transaction
388
+	 *
389
+	 * @access public
390
+	 * @return void
391
+	 */
392
+	public function load_scripts_styles_view_transaction()
393
+	{
394
+		//styles
395
+		wp_enqueue_style('espresso-ui-theme');
396
+	}
397
+
398
+
399
+	/**
400
+	 *    load_scripts_styles_default
401
+	 *
402
+	 * @access public
403
+	 * @return void
404
+	 */
405
+	public function load_scripts_styles_default()
406
+	{
407
+		//styles
408
+		wp_enqueue_style('espresso-ui-theme');
409
+	}
410
+
411
+
412
+	/**
413
+	 *    _set_list_table_views_default
414
+	 *
415
+	 * @access protected
416
+	 * @return void
417
+	 */
418
+	protected function _set_list_table_views_default()
419
+	{
420
+		$this->_views = array(
421
+			'all'       => array(
422
+				'slug'  => 'all',
423
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
424
+				'count' => 0,
425
+			),
426
+			'abandoned' => array(
427
+				'slug'  => 'abandoned',
428
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
+				'count' => 0,
430
+			),
431
+			'failed'    => array(
432
+				'slug'  => 'failed',
433
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
434
+				'count' => 0,
435
+			),
436
+		);
437
+	}
438
+
439
+
440
+	/**
441
+	 * _set_transaction_object
442
+	 * This sets the _transaction property for the transaction details screen
443
+	 *
444
+	 * @access private
445
+	 * @return void
446
+	 * @throws EE_Error
447
+	 * @throws InvalidArgumentException
448
+	 * @throws RuntimeException
449
+	 * @throws InvalidDataTypeException
450
+	 * @throws InvalidInterfaceException
451
+	 * @throws ReflectionException
452
+	 */
453
+	private function _set_transaction_object()
454
+	{
455
+		if ($this->_transaction instanceof EE_Transaction) {
456
+			return;
457
+		} //get out we've already set the object
458
+
459
+		$TXN_ID = ! empty($this->_req_data['TXN_ID'])
460
+			? absint($this->_req_data['TXN_ID'])
461
+			: false;
462
+
463
+		//get transaction object
464
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
465
+		$this->_session     = $this->_transaction instanceof EE_Transaction
466
+			? $this->_transaction->get('TXN_session_data')
467
+			: null;
468
+		$this->_transaction->verify_abandoned_transaction_status();
469
+
470
+		if (! $this->_transaction instanceof EE_Transaction) {
471
+			$error_msg = sprintf(
472
+				esc_html__(
473
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
474
+					'event_espresso'
475
+				),
476
+				$TXN_ID
477
+			);
478
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
479
+		}
480
+	}
481
+
482
+
483
+	/**
484
+	 *    _transaction_legend_items
485
+	 *
486
+	 * @access protected
487
+	 * @return array
488
+	 * @throws EE_Error
489
+	 * @throws InvalidArgumentException
490
+	 * @throws ReflectionException
491
+	 * @throws InvalidDataTypeException
492
+	 * @throws InvalidInterfaceException
493
+	 */
494
+	protected function _transaction_legend_items()
495
+	{
496
+		EE_Registry::instance()->load_helper('MSG_Template');
497
+		$items = array();
498
+
499
+		if (EE_Registry::instance()->CAP->current_user_can(
500
+			'ee_read_global_messages',
501
+			'view_filtered_messages'
502
+		)) {
503
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
504
+			if (is_array($related_for_icon)
505
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
506
+			) {
507
+				$items['view_related_messages'] = array(
508
+					'class' => $related_for_icon['css_class'],
509
+					'desc'  => $related_for_icon['label'],
510
+				);
511
+			}
512
+		}
513
+
514
+		$items = apply_filters(
515
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
516
+			array_merge(
517
+				$items,
518
+				array(
519
+					'view_details'          => array(
520
+						'class' => 'dashicons dashicons-cart',
521
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
522
+					),
523
+					'view_invoice'          => array(
524
+						'class' => 'dashicons dashicons-media-spreadsheet',
525
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
526
+					),
527
+					'view_receipt'          => array(
528
+						'class' => 'dashicons dashicons-media-default',
529
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
530
+					),
531
+					'view_registration'     => array(
532
+						'class' => 'dashicons dashicons-clipboard',
533
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
534
+					),
535
+					'payment_overview_link' => array(
536
+						'class' => 'dashicons dashicons-money',
537
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
538
+					),
539
+				)
540
+			)
541
+		);
542
+
543
+		if (EE_Registry::instance()->CAP->current_user_can(
544
+			'ee_send_message',
545
+			'espresso_transactions_send_payment_reminder'
546
+		)) {
547
+			if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
548
+				$items['send_payment_reminder'] = array(
549
+					'class' => 'dashicons dashicons-email-alt',
550
+					'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
551
+				);
552
+			} else {
553
+				$items['blank*'] = array(
554
+					'class' => '',
555
+					'desc'  => '',
556
+				);
557
+			}
558
+		} else {
559
+			$items['blank*'] = array(
560
+				'class' => '',
561
+				'desc'  => '',
562
+			);
563
+		}
564
+		$more_items = apply_filters(
565
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
566
+			array(
567
+				'overpaid'   => array(
568
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
569
+					'desc'  => EEH_Template::pretty_status(
570
+						EEM_Transaction::overpaid_status_code,
571
+						false,
572
+						'sentence'
573
+					),
574
+				),
575
+				'complete'   => array(
576
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
577
+					'desc'  => EEH_Template::pretty_status(
578
+						EEM_Transaction::complete_status_code,
579
+						false,
580
+						'sentence'
581
+					),
582
+				),
583
+				'incomplete' => array(
584
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
585
+					'desc'  => EEH_Template::pretty_status(
586
+						EEM_Transaction::incomplete_status_code,
587
+						false,
588
+						'sentence'
589
+					),
590
+				),
591
+				'abandoned'  => array(
592
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
593
+					'desc'  => EEH_Template::pretty_status(
594
+						EEM_Transaction::abandoned_status_code,
595
+						false,
596
+						'sentence'
597
+					),
598
+				),
599
+				'failed'     => array(
600
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
601
+					'desc'  => EEH_Template::pretty_status(
602
+						EEM_Transaction::failed_status_code,
603
+						false,
604
+						'sentence'
605
+					),
606
+				),
607
+			)
608
+		);
609
+
610
+		return array_merge($items, $more_items);
611
+	}
612
+
613
+
614
+	/**
615
+	 *    _transactions_overview_list_table
616
+	 *
617
+	 * @access protected
618
+	 * @return void
619
+	 * @throws DomainException
620
+	 * @throws EE_Error
621
+	 * @throws InvalidArgumentException
622
+	 * @throws InvalidDataTypeException
623
+	 * @throws InvalidInterfaceException
624
+	 * @throws ReflectionException
625
+	 */
626
+	protected function _transactions_overview_list_table()
627
+	{
628
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
629
+		$event = isset($this->_req_data['EVT_ID'])
630
+			? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
631
+			: null;
632
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
633
+			? sprintf(
634
+				esc_html__(
635
+					'%sViewing Transactions for the Event: %s%s',
636
+					'event_espresso'
637
+				),
638
+				'<h3>',
639
+				'<a href="'
640
+				. EE_Admin_Page::add_query_args_and_nonce(
641
+					array('action' => 'edit', 'post' => $event->ID()),
642
+					EVENTS_ADMIN_URL
643
+				)
644
+				. '" title="'
645
+				. esc_attr__(
646
+					'Click to Edit event',
647
+					'event_espresso'
648
+				)
649
+				. '">' . $event->get('EVT_name') . '</a>',
650
+				'</h3>'
651
+			)
652
+			: '';
653
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
654
+		$this->display_admin_list_table_page_with_no_sidebar();
655
+	}
656
+
657
+
658
+	/**
659
+	 *    _transaction_details
660
+	 * generates HTML for the View Transaction Details Admin page
661
+	 *
662
+	 * @access protected
663
+	 * @return void
664
+	 * @throws DomainException
665
+	 * @throws EE_Error
666
+	 * @throws InvalidArgumentException
667
+	 * @throws InvalidDataTypeException
668
+	 * @throws InvalidInterfaceException
669
+	 * @throws RuntimeException
670
+	 * @throws ReflectionException
671
+	 */
672
+	protected function _transaction_details()
673
+	{
674
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
675
+
676
+		$this->_set_transaction_status_array();
677
+
678
+		$this->_template_args                      = array();
679
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
680
+
681
+		$this->_set_transaction_object();
682
+
683
+		$primary_registration = $this->_transaction->primary_registration();
684
+		$attendee = $primary_registration instanceof EE_Registration
685
+			? $primary_registration->attendee()
686
+			: null;
687
+
688
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
689
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
690
+
691
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
692
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
693
+
694
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
695
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
696
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
697
+
698
+		$this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
699
+		$this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
700
+
701
+		$amount_due = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
702
+		$this->_template_args['amount_due'] = EEH_Template::format_currency(
703
+			$amount_due,
704
+			true
705
+		);
706
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
707
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
708
+												  . $this->_template_args['amount_due'];
709
+		} else {
710
+			$this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
711
+		}
712
+		$this->_template_args['amount_due_class'] = '';
713
+
714
+		if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
715
+			// paid in full
716
+			$this->_template_args['amount_due'] = false;
717
+		} elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
718
+			// overpaid
719
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
720
+		} elseif ($this->_transaction->get('TXN_total') > 0
721
+				  && $this->_transaction->get('TXN_paid') > 0
722
+		) {
723
+			// monies owing
724
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
725
+		} elseif ($this->_transaction->get('TXN_total') > 0
726
+				  && $this->_transaction->get('TXN_paid') == 0
727
+		) {
728
+			// no payments made yet
729
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
730
+		} elseif ($this->_transaction->get('TXN_total') == 0) {
731
+			// free event
732
+			$this->_template_args['amount_due'] = false;
733
+		}
734
+
735
+		$payment_method = $this->_transaction->payment_method();
736
+
737
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
738
+			? $payment_method->admin_name()
739
+			: esc_html__('Unknown', 'event_espresso');
740
+
741
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
742
+		// link back to overview
743
+		$this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
744
+			? $_SERVER['HTTP_REFERER']
745
+			: TXN_ADMIN_URL;
746
+
747
+
748
+		// next link
749
+		$next_txn                                 = $this->_transaction->next(
750
+			null,
751
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
752
+			'TXN_ID'
753
+		);
754
+		$this->_template_args['next_transaction'] = $next_txn
755
+			? $this->_next_link(
756
+				EE_Admin_Page::add_query_args_and_nonce(
757
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
758
+					TXN_ADMIN_URL
759
+				),
760
+				'dashicons dashicons-arrow-right ee-icon-size-22'
761
+			)
762
+			: '';
763
+		// previous link
764
+		$previous_txn                                 = $this->_transaction->previous(
765
+			null,
766
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
767
+			'TXN_ID'
768
+		);
769
+		$this->_template_args['previous_transaction'] = $previous_txn
770
+			? $this->_previous_link(
771
+				EE_Admin_Page::add_query_args_and_nonce(
772
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
773
+					TXN_ADMIN_URL
774
+				),
775
+				'dashicons dashicons-arrow-left ee-icon-size-22'
776
+			)
777
+			: '';
778
+
779
+		// were we just redirected here after adding a new registration ???
780
+		if (isset(
781
+			$this->_req_data['redirect_from'],
782
+			$this->_req_data['EVT_ID'],
783
+			$this->_req_data['event_name']
784
+		)) {
785
+			if (EE_Registry::instance()->CAP->current_user_can(
786
+				'ee_edit_registrations',
787
+				'espresso_registrations_new_registration',
788
+				$this->_req_data['EVT_ID']
789
+			)) {
790
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
791
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
792
+					array(
793
+						'page'     => 'espresso_registrations',
794
+						'action'   => 'new_registration',
795
+						'return'   => 'default',
796
+						'TXN_ID'   => $this->_transaction->ID(),
797
+						'event_id' => $this->_req_data['EVT_ID'],
798
+					),
799
+					REG_ADMIN_URL
800
+				);
801
+				$this->_admin_page_title .= '">';
802
+
803
+				$this->_admin_page_title .= sprintf(
804
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
805
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
806
+				);
807
+				$this->_admin_page_title .= '</a>';
808
+			}
809
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
810
+		}
811
+		// grab messages at the last second
812
+		$this->_template_args['notices'] = EE_Error::get_notices();
813
+		// path to template
814
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
815
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
816
+			$template_path,
817
+			$this->_template_args,
818
+			true
819
+		);
820
+
821
+		// the details template wrapper
822
+		$this->display_admin_page_with_sidebar();
823
+
824
+	}
825
+
826
+
827
+	/**
828
+	 *        _transaction_details_metaboxes
829
+	 *
830
+	 * @access protected
831
+	 * @return void
832
+	 * @throws EE_Error
833
+	 * @throws InvalidArgumentException
834
+	 * @throws InvalidDataTypeException
835
+	 * @throws InvalidInterfaceException
836
+	 * @throws RuntimeException
837
+	 * @throws ReflectionException
838
+	 */
839
+	protected function _transaction_details_metaboxes()
840
+	{
841
+
842
+		$this->_set_transaction_object();
843
+
844
+		add_meta_box(
845
+			'edit-txn-details-mbox',
846
+			esc_html__('Transaction Details', 'event_espresso'),
847
+			array($this, 'txn_details_meta_box'),
848
+			$this->_wp_page_slug,
849
+			'normal',
850
+			'high'
851
+		);
852
+		add_meta_box(
853
+			'edit-txn-attendees-mbox',
854
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
855
+			array($this, 'txn_attendees_meta_box'),
856
+			$this->_wp_page_slug,
857
+			'normal',
858
+			'high',
859
+			array('TXN_ID' => $this->_transaction->ID())
860
+		);
861
+		add_meta_box(
862
+			'edit-txn-registrant-mbox',
863
+			esc_html__('Primary Contact', 'event_espresso'),
864
+			array($this, 'txn_registrant_side_meta_box'),
865
+			$this->_wp_page_slug,
866
+			'side',
867
+			'high'
868
+		);
869
+		add_meta_box(
870
+			'edit-txn-billing-info-mbox',
871
+			esc_html__('Billing Information', 'event_espresso'),
872
+			array($this, 'txn_billing_info_side_meta_box'),
873
+			$this->_wp_page_slug,
874
+			'side',
875
+			'high'
876
+		);
877
+	}
878
+
879
+
880
+	/**
881
+	 * Callback for transaction actions metabox.
882
+	 *
883
+	 * @param EE_Transaction|null $transaction
884
+	 * @throws DomainException
885
+	 * @throws EE_Error
886
+	 * @throws InvalidArgumentException
887
+	 * @throws InvalidDataTypeException
888
+	 * @throws InvalidInterfaceException
889
+	 * @throws ReflectionException
890
+	 * @throws RuntimeException
891
+	 */
892
+	public function getActionButtons(EE_Transaction $transaction = null)
893
+	{
894
+		$content = '';
895
+		$actions = array();
896
+		if (! $transaction instanceof EE_Transaction) {
897
+			return $content;
898
+		}
899
+		/** @var EE_Registration $primary_registration */
900
+		$primary_registration = $transaction->primary_registration();
901
+		$attendee = $primary_registration instanceof EE_Registration
902
+			? $primary_registration->attendee()
903
+			: null;
904
+
905
+		if ($attendee instanceof EE_Attendee
906
+			&& EE_Registry::instance()->CAP->current_user_can(
907
+				'ee_send_message',
908
+				'espresso_transactions_send_payment_reminder'
909
+			)
910
+		) {
911
+			$actions['payment_reminder'] =
912
+				EEH_MSG_Template::is_mt_active('payment_reminder')
913
+				&& $this->_transaction->get('STS_ID') !== EEM_Transaction::complete_status_code
914
+				&& $this->_transaction->get('STS_ID') !== EEM_Transaction::overpaid_status_code
915
+					? EEH_Template::get_button_or_link(
916
+						EE_Admin_Page::add_query_args_and_nonce(
917
+							array(
918
+								'action'      => 'send_payment_reminder',
919
+								'TXN_ID'      => $this->_transaction->ID(),
920
+								'redirect_to' => 'view_transaction',
921
+							),
922
+							TXN_ADMIN_URL
923
+						),
924
+						esc_html__(' Send Payment Reminder', 'event_espresso'),
925
+						'button secondary-button',
926
+						'dashicons dashicons-email-alt'
927
+					)
928
+					: '';
929
+		}
930
+
931
+		if ($primary_registration instanceof EE_Registration
932
+			&& EEH_MSG_Template::is_mt_active('receipt')
933
+		) {
934
+			$actions['receipt'] = EEH_Template::get_button_or_link(
935
+				$primary_registration->receipt_url(),
936
+				esc_html__('View Receipt', 'event_espresso'),
937
+				'button secondary-button',
938
+				'dashicons dashicons-media-default'
939
+			);
940
+		}
941
+
942
+		if ($primary_registration instanceof EE_Registration
943
+			&& EEH_MSG_Template::is_mt_active('invoice')
944
+		) {
945
+			$actions['invoice'] = EEH_Template::get_button_or_link(
946
+				$primary_registration->invoice_url(),
947
+				esc_html__('View Invoice', 'event_espresso'),
948
+				'button secondary-button',
949
+				'dashicons dashicons-media-spreadsheet'
950
+			);
951
+		}
952
+		$actions = array_filter(
953
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
954
+		);
955
+		if ($actions) {
956
+			$content = '<ul>';
957
+			$content .= '<li>' . implode('</li><li>', $actions) . '</li>';
958
+			$content .= '</uL>';
959
+		}
960
+		return $content;
961
+	}
962
+
963
+
964
+	/**
965
+	 * txn_details_meta_box
966
+	 * generates HTML for the Transaction main meta box
967
+	 *
968
+	 * @return void
969
+	 * @throws DomainException
970
+	 * @throws EE_Error
971
+	 * @throws InvalidArgumentException
972
+	 * @throws InvalidDataTypeException
973
+	 * @throws InvalidInterfaceException
974
+	 * @throws RuntimeException
975
+	 * @throws ReflectionException
976
+	 */
977
+	public function txn_details_meta_box()
978
+	{
979
+		$this->_set_transaction_object();
980
+		$this->_template_args['TXN_ID']   = $this->_transaction->ID();
981
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
982
+			? $this->_transaction->primary_registration()->attendee()
983
+			: null;
984
+		$this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
985
+			'ee_edit_payments',
986
+			'apply_payment_or_refund_from_registration_details'
987
+		);
988
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
989
+			'ee_delete_payments',
990
+			'delete_payment_from_registration_details'
991
+		);
992
+
993
+		//get line table
994
+		EEH_Autoloader::register_line_item_display_autoloaders();
995
+		$Line_Item_Display                       = new EE_Line_Item_Display(
996
+			'admin_table',
997
+			'EE_Admin_Table_Line_Item_Display_Strategy'
998
+		);
999
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1000
+			$this->_transaction->total_line_item()
1001
+		);
1002
+		$this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')
1003
+																	  ->get('REG_code');
1004
+
1005
+		// process taxes
1006
+		$taxes                         = $this->_transaction->get_many_related(
1007
+			'Line_Item',
1008
+			array(array('LIN_type' => EEM_Line_Item::type_tax))
1009
+		);
1010
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1011
+
1012
+		$this->_template_args['grand_total']     = EEH_Template::format_currency(
1013
+			$this->_transaction->get('TXN_total'),
1014
+			false,
1015
+			false
1016
+		);
1017
+		$this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
1018
+		$this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
1019
+
1020
+		// process payment details
1021
+		$payments = $this->_transaction->get_many_related('Payment');
1022
+		if (! empty($payments)) {
1023
+			$this->_template_args['payments']              = $payments;
1024
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1025
+		} else {
1026
+			$this->_template_args['payments']              = false;
1027
+			$this->_template_args['existing_reg_payments'] = array();
1028
+		}
1029
+
1030
+		$this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1031
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1032
+			array('action' => 'espresso_delete_payment'),
1033
+			TXN_ADMIN_URL
1034
+		);
1035
+
1036
+		if (isset($txn_details['invoice_number'])) {
1037
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1038
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1039
+				'Invoice Number',
1040
+				'event_espresso'
1041
+			);
1042
+		}
1043
+
1044
+		$this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
1045
+			->get_first_related('Registration')
1046
+			->get('REG_session');
1047
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1048
+			'Registration Session',
1049
+			'event_espresso'
1050
+		);
1051
+
1052
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1053
+			? $this->_session['ip_address']
1054
+			: '';
1055
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1056
+			'Transaction placed from IP',
1057
+			'event_espresso'
1058
+		);
1059
+
1060
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1061
+			? $this->_session['user_agent']
1062
+			: '';
1063
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1064
+			'Registrant User Agent',
1065
+			'event_espresso'
1066
+		);
1067
+
1068
+		$reg_steps = '<ul>';
1069
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1070
+			if ($reg_step_status === true) {
1071
+				$reg_steps .= '<li style="color:#70cc50">'
1072
+							  . sprintf(
1073
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1074
+								  ucwords(str_replace('_', ' ', $reg_step))
1075
+							  )
1076
+							  . '</li>';
1077
+			} elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1078
+				$reg_steps .= '<li style="color:#2EA2CC">'
1079
+							  . sprintf(
1080
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1081
+								  ucwords(str_replace('_', ' ', $reg_step)),
1082
+								  date(
1083
+									  get_option('date_format') . ' ' . get_option('time_format'),
1084
+									  ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1085
+								  )
1086
+							  )
1087
+							  . '</li>';
1088
+			} else {
1089
+				$reg_steps .= '<li style="color:#E76700">'
1090
+							  . sprintf(
1091
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1092
+								  ucwords(str_replace('_', ' ', $reg_step))
1093
+							  )
1094
+							  . '</li>';
1095
+			}
1096
+		}
1097
+		$reg_steps                                                 .= '</ul>';
1098
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1099
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1100
+			'Registration Step Progress',
1101
+			'event_espresso'
1102
+		);
1103
+
1104
+
1105
+		$this->_get_registrations_to_apply_payment_to();
1106
+		$this->_get_payment_methods($payments);
1107
+		$this->_get_payment_status_array();
1108
+		$this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
1109
+
1110
+		$this->_template_args['transaction_form_url']    = add_query_arg(array(
1111
+			'action'  => 'edit_transaction',
1112
+			'process' => 'transaction',
1113
+		), TXN_ADMIN_URL);
1114
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(array(
1115
+			'page'   => 'espresso_transactions',
1116
+			'action' => 'espresso_apply_payment',
1117
+		), WP_AJAX_URL);
1118
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(array(
1119
+			'page'   => 'espresso_transactions',
1120
+			'action' => 'espresso_delete_payment',
1121
+		), WP_AJAX_URL);
1122
+
1123
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1124
+
1125
+		// 'espresso_delete_payment_nonce'
1126
+
1127
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1128
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1129
+	}
1130
+
1131
+
1132
+	/**
1133
+	 * _get_registration_payment_IDs
1134
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1135
+	 *
1136
+	 * @access protected
1137
+	 * @param EE_Payment[] $payments
1138
+	 * @return array
1139
+	 * @throws EE_Error
1140
+	 * @throws InvalidArgumentException
1141
+	 * @throws InvalidDataTypeException
1142
+	 * @throws InvalidInterfaceException
1143
+	 * @throws ReflectionException
1144
+	 */
1145
+	protected function _get_registration_payment_IDs($payments = array())
1146
+	{
1147
+		$existing_reg_payments = array();
1148
+		// get all reg payments for these payments
1149
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(array(
1150
+			array(
1151
+				'PAY_ID' => array(
1152
+					'IN',
1153
+					array_keys($payments),
1154
+				),
1155
+			),
1156
+		));
1157
+		if (! empty($reg_payments)) {
1158
+			foreach ($payments as $payment) {
1159
+				if (! $payment instanceof EE_Payment) {
1160
+					continue;
1161
+				} elseif (! isset($existing_reg_payments[$payment->ID()])) {
1162
+					$existing_reg_payments[$payment->ID()] = array();
1163
+				}
1164
+				foreach ($reg_payments as $reg_payment) {
1165
+					if ($reg_payment instanceof EE_Registration_Payment
1166
+						&& $reg_payment->payment_ID() === $payment->ID()
1167
+					) {
1168
+						$existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
1169
+					}
1170
+				}
1171
+			}
1172
+		}
1173
+
1174
+		return $existing_reg_payments;
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * _get_registrations_to_apply_payment_to
1180
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1181
+	 * which allows the admin to only apply the payment to the specific registrations
1182
+	 *
1183
+	 * @access protected
1184
+	 * @return void
1185
+	 * @throws \EE_Error
1186
+	 */
1187
+	protected function _get_registrations_to_apply_payment_to()
1188
+	{
1189
+		// we want any registration with an active status (ie: not deleted or cancelled)
1190
+		$query_params                      = array(
1191
+			array(
1192
+				'STS_ID' => array(
1193
+					'IN',
1194
+					array(
1195
+						EEM_Registration::status_id_approved,
1196
+						EEM_Registration::status_id_pending_payment,
1197
+						EEM_Registration::status_id_not_approved,
1198
+					),
1199
+				),
1200
+			),
1201
+		);
1202
+		$registrations_to_apply_payment_to = EEH_HTML::br()
1203
+											 . EEH_HTML::div(
1204
+												 '',
1205
+												 'txn-admin-apply-payment-to-registrations-dv',
1206
+												 '',
1207
+												 'clear: both; margin: 1.5em 0 0; display: none;'
1208
+											 );
1209
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1210
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1211
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1212
+			EEH_HTML::tr(
1213
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1214
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1215
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1216
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1217
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1218
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1219
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1220
+			)
1221
+		);
1222
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1223
+		// get registrations for TXN
1224
+		$registrations = $this->_transaction->registrations($query_params);
1225
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1226
+		foreach ($registrations as $registration) {
1227
+			if ($registration instanceof EE_Registration) {
1228
+				$attendee_name                     = $registration->attendee() instanceof EE_Attendee
1229
+					? $registration->attendee()->full_name()
1230
+					: esc_html__('Unknown Attendee', 'event_espresso');
1231
+				$owing                             = $registration->final_price() - $registration->paid();
1232
+				$taxable                           = $registration->ticket()->taxable()
1233
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1234
+					: '';
1235
+				$checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1236
+					? ' checked="checked"'
1237
+					: '';
1238
+				$disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1239
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1240
+					EEH_HTML::td($registration->ID()) .
1241
+					EEH_HTML::td($attendee_name) .
1242
+					EEH_HTML::td(
1243
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1244
+					) .
1245
+					EEH_HTML::td($registration->event_name()) .
1246
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1247
+					EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1248
+					EEH_HTML::td(
1249
+						'<input type="checkbox" value="' . $registration->ID()
1250
+						. '" name="txn_admin_payment[registrations]"'
1251
+						. $checked . $disabled . '>',
1252
+						'',
1253
+						'jst-cntr'
1254
+					),
1255
+					'apply-payment-registration-row-' . $registration->ID()
1256
+				);
1257
+			}
1258
+		}
1259
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1260
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1261
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1262
+		$registrations_to_apply_payment_to                         .= EEH_HTML::p(
1263
+			esc_html__(
1264
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1265
+				'event_espresso'
1266
+			),
1267
+			'',
1268
+			'clear description'
1269
+		);
1270
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1271
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1272
+	}
1273
+
1274
+
1275
+	/**
1276
+	 * _get_reg_status_selection
1277
+	 *
1278
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1279
+	 *         instead of events.
1280
+	 * @access protected
1281
+	 * @return void
1282
+	 * @throws EE_Error
1283
+	 */
1284
+	protected function _get_reg_status_selection()
1285
+	{
1286
+		//first get all possible statuses
1287
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1288
+		//let's add a "don't change" option.
1289
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1290
+		$status_array                                        = array_merge($status_array, $statuses);
1291
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1292
+			'txn_reg_status_change[reg_status]',
1293
+			$status_array,
1294
+			'NAN',
1295
+			'id="txn-admin-payment-reg-status-inp"',
1296
+			'txn-reg-status-change-reg-status'
1297
+		);
1298
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1299
+			'delete_txn_reg_status_change[reg_status]',
1300
+			$status_array,
1301
+			'NAN',
1302
+			'delete-txn-admin-payment-reg-status-inp',
1303
+			'delete-txn-reg-status-change-reg-status'
1304
+		);
1305
+	}
1306
+
1307
+
1308
+	/**
1309
+	 *    _get_payment_methods
1310
+	 * Gets all the payment methods available generally, or the ones that are already
1311
+	 * selected on these payments (in case their payment methods are no longer active).
1312
+	 * Has the side-effect of updating the template args' payment_methods item
1313
+	 *
1314
+	 * @access private
1315
+	 * @param EE_Payment[] to show on this page
1316
+	 * @return void
1317
+	 * @throws EE_Error
1318
+	 * @throws InvalidArgumentException
1319
+	 * @throws InvalidDataTypeException
1320
+	 * @throws InvalidInterfaceException
1321
+	 * @throws ReflectionException
1322
+	 */
1323
+	private function _get_payment_methods($payments = array())
1324
+	{
1325
+		$payment_methods_of_payments = array();
1326
+		foreach ($payments as $payment) {
1327
+			if ($payment instanceof EE_Payment) {
1328
+				$payment_methods_of_payments[] = $payment->get('PMD_ID');
1329
+			}
1330
+		}
1331
+		if ($payment_methods_of_payments) {
1332
+			$query_args = array(
1333
+				array(
1334
+					'OR*payment_method_for_payment' => array(
1335
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1336
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1337
+					),
1338
+				),
1339
+			);
1340
+		} else {
1341
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1342
+		}
1343
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1344
+	}
1345
+
1346
+
1347
+	/**
1348
+	 * txn_attendees_meta_box
1349
+	 *    generates HTML for the Attendees Transaction main meta box
1350
+	 *
1351
+	 * @access public
1352
+	 * @param WP_Post $post
1353
+	 * @param array   $metabox
1354
+	 * @return void
1355
+	 * @throws DomainException
1356
+	 * @throws EE_Error
1357
+	 */
1358
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1359
+	{
1360
+
1361
+		/** @noinspection NonSecureExtractUsageInspection */
1362
+		extract($metabox['args']);
1363
+		$this->_template_args['post']            = $post;
1364
+		$this->_template_args['event_attendees'] = array();
1365
+		// process items in cart
1366
+		$line_items = $this->_transaction->get_many_related(
1367
+			'Line_Item',
1368
+			array(array('LIN_type' => 'line-item'))
1369
+		);
1370
+		if (! empty($line_items)) {
1371
+			foreach ($line_items as $item) {
1372
+				if ($item instanceof EE_Line_Item) {
1373
+					switch ($item->OBJ_type()) {
1374
+						case 'Event':
1375
+							break;
1376
+						case 'Ticket':
1377
+							$ticket = $item->ticket();
1378
+							//right now we're only handling tickets here.
1379
+							//Cause its expected that only tickets will have attendees right?
1380
+							if (! $ticket instanceof EE_Ticket) {
1381
+								continue;
1382
+							}
1383
+							try {
1384
+								$event_name = $ticket->get_event_name();
1385
+							} catch (Exception $e) {
1386
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1387
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1388
+							}
1389
+							$event_name   .= ' - ' . $item->get('LIN_name');
1390
+							$ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1391
+							// now get all of the registrations for this transaction that use this ticket
1392
+							$registrations = $ticket->get_many_related(
1393
+								'Registration',
1394
+								array(array('TXN_ID' => $this->_transaction->ID()))
1395
+							);
1396
+							foreach ($registrations as $registration) {
1397
+								if (! $registration instanceof EE_Registration) {
1398
+									continue;
1399
+								}
1400
+								$this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
1401
+									= $registration->status_ID();
1402
+								$this->_template_args['event_attendees'][$registration->ID()]['att_num']
1403
+									= $registration->count();
1404
+								$this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name']
1405
+									= $event_name;
1406
+								$this->_template_args['event_attendees'][$registration->ID()]['ticket_price']
1407
+									= $ticket_price;
1408
+								// attendee info
1409
+								$attendee = $registration->get_first_related('Attendee');
1410
+								if ($attendee instanceof EE_Attendee) {
1411
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']
1412
+										= $attendee->ID();
1413
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee']
1414
+										= $attendee->full_name();
1415
+									$this->_template_args['event_attendees'][$registration->ID()]['email']
1416
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1417
+										  . esc_html__(
1418
+											  ' Event',
1419
+											  'event_espresso'
1420
+										  )
1421
+										  . '">' . $attendee->email() . '</a>';
1422
+									$this->_template_args['event_attendees'][$registration->ID()]['address']
1423
+										= EEH_Address::format($attendee, 'inline', false, false);
1424
+								} else {
1425
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1426
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1427
+									$this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1428
+									$this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1429
+								}
1430
+							}
1431
+							break;
1432
+
1433
+					}
1434
+				}
1435
+			}
1436
+
1437
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1438
+				array(
1439
+					'action'  => 'edit_transaction',
1440
+					'process' => 'attendees',
1441
+				),
1442
+				TXN_ADMIN_URL
1443
+			);
1444
+			echo EEH_Template::display_template(
1445
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1446
+				$this->_template_args,
1447
+				true
1448
+			);
1449
+
1450
+		} else {
1451
+			echo sprintf(
1452
+				esc_html__(
1453
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1454
+					'event_espresso'
1455
+				),
1456
+				'<p class="important-notice">',
1457
+				'</p>'
1458
+			);
1459
+		}
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * txn_registrant_side_meta_box
1465
+	 * generates HTML for the Edit Transaction side meta box
1466
+	 *
1467
+	 * @access public
1468
+	 * @return void
1469
+	 * @throws DomainException
1470
+	 * @throws EE_Error
1471
+	 * @throws InvalidArgumentException
1472
+	 * @throws InvalidDataTypeException
1473
+	 * @throws InvalidInterfaceException
1474
+	 * @throws ReflectionException
1475
+	 */
1476
+	public function txn_registrant_side_meta_box()
1477
+	{
1478
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1479
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1480
+			: null;
1481
+		if (! $primary_att instanceof EE_Attendee) {
1482
+			$this->_template_args['no_attendee_message'] = esc_html__(
1483
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1484
+				'event_espresso'
1485
+			);
1486
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1487
+		}
1488
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1489
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1490
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1491
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1492
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1493
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1494
+			'action' => 'edit_attendee',
1495
+			'post'   => $primary_att->ID(),
1496
+		), REG_ADMIN_URL);
1497
+		// get formatted address for registrant
1498
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1499
+		echo EEH_Template::display_template(
1500
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1501
+			$this->_template_args,
1502
+			true
1503
+		);
1504
+	}
1505
+
1506
+
1507
+	/**
1508
+	 * txn_billing_info_side_meta_box
1509
+	 *    generates HTML for the Edit Transaction side meta box
1510
+	 *
1511
+	 * @access public
1512
+	 * @return void
1513
+	 * @throws DomainException
1514
+	 * @throws EE_Error
1515
+	 */
1516
+	public function txn_billing_info_side_meta_box()
1517
+	{
1518
+
1519
+		$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1520
+		$this->_template_args['billing_form_url'] = add_query_arg(
1521
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1522
+			TXN_ADMIN_URL
1523
+		);
1524
+
1525
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1526
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1527
+	}
1528
+
1529
+
1530
+	/**
1531
+	 * apply_payments_or_refunds
1532
+	 *    registers a payment or refund made towards a transaction
1533
+	 *
1534
+	 * @access public
1535
+	 * @return void
1536
+	 * @throws EE_Error
1537
+	 * @throws InvalidArgumentException
1538
+	 * @throws ReflectionException
1539
+	 * @throws RuntimeException
1540
+	 * @throws InvalidDataTypeException
1541
+	 * @throws InvalidInterfaceException
1542
+	 */
1543
+	public function apply_payments_or_refunds()
1544
+	{
1545
+		$json_response_data = array('return_data' => false);
1546
+		$valid_data         = $this->_validate_payment_request_data();
1547
+		$has_access = EE_Registry::instance()->CAP->current_user_can(
1548
+			'ee_edit_payments',
1549
+			'apply_payment_or_refund_from_registration_details'
1550
+		);
1551
+		if (! empty($valid_data) && $has_access) {
1552
+			$PAY_ID = $valid_data['PAY_ID'];
1553
+			//save  the new payment
1554
+			$payment = $this->_create_payment_from_request_data($valid_data);
1555
+			// get the TXN for this payment
1556
+			$transaction = $payment->transaction();
1557
+			// verify transaction
1558
+			if ($transaction instanceof EE_Transaction) {
1559
+				// calculate_total_payments_and_update_status
1560
+				$this->_process_transaction_payments($transaction);
1561
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1562
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1563
+				// apply payment to registrations (if applicable)
1564
+				if (! empty($REG_IDs)) {
1565
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1566
+					$this->_maybe_send_notifications();
1567
+					// now process status changes for the same registrations
1568
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1569
+				}
1570
+				$this->_maybe_send_notifications($payment);
1571
+				//prepare to render page
1572
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1573
+				do_action(
1574
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1575
+					$transaction,
1576
+					$payment
1577
+				);
1578
+			} else {
1579
+				EE_Error::add_error(
1580
+					esc_html__(
1581
+						'A valid Transaction for this payment could not be retrieved.',
1582
+						'event_espresso'
1583
+					),
1584
+					__FILE__,
1585
+					__FUNCTION__,
1586
+					__LINE__
1587
+				);
1588
+			}
1589
+		} else {
1590
+			if ($has_access) {
1591
+				EE_Error::add_error(
1592
+					esc_html__(
1593
+						'The payment form data could not be processed. Please try again.',
1594
+						'event_espresso'
1595
+					),
1596
+					__FILE__,
1597
+					__FUNCTION__,
1598
+					__LINE__
1599
+				);
1600
+			} else {
1601
+				EE_Error::add_error(
1602
+					esc_html__(
1603
+						'You do not have access to apply payments or refunds to a registration.',
1604
+						'event_espresso'
1605
+					),
1606
+					__FILE__,
1607
+					__FUNCTION__,
1608
+					__LINE__
1609
+				);
1610
+			}
1611
+		}
1612
+		$notices              = EE_Error::get_notices(
1613
+			false,
1614
+			false,
1615
+			false
1616
+		);
1617
+		$this->_template_args = array(
1618
+			'data'    => $json_response_data,
1619
+			'error'   => $notices['errors'],
1620
+			'success' => $notices['success'],
1621
+		);
1622
+		$this->_return_json();
1623
+	}
1624
+
1625
+
1626
+	/**
1627
+	 * _validate_payment_request_data
1628
+	 *
1629
+	 * @return array
1630
+	 * @throws EE_Error
1631
+	 */
1632
+	protected function _validate_payment_request_data()
1633
+	{
1634
+		if (! isset($this->_req_data['txn_admin_payment'])) {
1635
+			return false;
1636
+		}
1637
+		$payment_form = $this->_generate_payment_form_section();
1638
+		try {
1639
+			if ($payment_form->was_submitted()) {
1640
+				$payment_form->receive_form_submission();
1641
+				if (! $payment_form->is_valid()) {
1642
+					$submission_error_messages = array();
1643
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1644
+						if ($validation_error instanceof EE_Validation_Error) {
1645
+							$submission_error_messages[] = sprintf(
1646
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1647
+								$validation_error->get_form_section()->html_label_text(),
1648
+								$validation_error->getMessage()
1649
+							);
1650
+						}
1651
+					}
1652
+					EE_Error::add_error(
1653
+						implode('<br />', $submission_error_messages),
1654
+						__FILE__,
1655
+						__FUNCTION__,
1656
+						__LINE__
1657
+					);
1658
+
1659
+					return array();
1660
+				}
1661
+			}
1662
+		} catch (EE_Error $e) {
1663
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1664
+
1665
+			return array();
1666
+		}
1667
+
1668
+		return $payment_form->valid_data();
1669
+	}
1670
+
1671
+
1672
+	/**
1673
+	 * _generate_payment_form_section
1674
+	 *
1675
+	 * @return EE_Form_Section_Proper
1676
+	 * @throws EE_Error
1677
+	 */
1678
+	protected function _generate_payment_form_section()
1679
+	{
1680
+		return new EE_Form_Section_Proper(
1681
+			array(
1682
+				'name'        => 'txn_admin_payment',
1683
+				'subsections' => array(
1684
+					'PAY_ID'          => new EE_Text_Input(
1685
+						array(
1686
+							'default'               => 0,
1687
+							'required'              => false,
1688
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1689
+							'validation_strategies' => array(new EE_Int_Normalization()),
1690
+						)
1691
+					),
1692
+					'TXN_ID'          => new EE_Text_Input(
1693
+						array(
1694
+							'default'               => 0,
1695
+							'required'              => true,
1696
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1697
+							'validation_strategies' => array(new EE_Int_Normalization()),
1698
+						)
1699
+					),
1700
+					'type'            => new EE_Text_Input(
1701
+						array(
1702
+							'default'               => 1,
1703
+							'required'              => true,
1704
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1705
+							'validation_strategies' => array(new EE_Int_Normalization()),
1706
+						)
1707
+					),
1708
+					'amount'          => new EE_Text_Input(
1709
+						array(
1710
+							'default'               => 0,
1711
+							'required'              => true,
1712
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1713
+							'validation_strategies' => array(new EE_Float_Normalization()),
1714
+						)
1715
+					),
1716
+					'status'          => new EE_Text_Input(
1717
+						array(
1718
+							'default'         => EEM_Payment::status_id_approved,
1719
+							'required'        => true,
1720
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1721
+						)
1722
+					),
1723
+					'PMD_ID'          => new EE_Text_Input(
1724
+						array(
1725
+							'default'               => 2,
1726
+							'required'              => true,
1727
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1728
+							'validation_strategies' => array(new EE_Int_Normalization()),
1729
+						)
1730
+					),
1731
+					'date'            => new EE_Text_Input(
1732
+						array(
1733
+							'default'         => time(),
1734
+							'required'        => true,
1735
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1736
+						)
1737
+					),
1738
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1739
+						array(
1740
+							'default'               => '',
1741
+							'required'              => false,
1742
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1743
+							'validation_strategies' => array(
1744
+								new EE_Max_Length_Validation_Strategy(
1745
+									esc_html__('Input too long', 'event_espresso'),
1746
+									100
1747
+								),
1748
+							),
1749
+						)
1750
+					),
1751
+					'po_number'       => new EE_Text_Input(
1752
+						array(
1753
+							'default'               => '',
1754
+							'required'              => false,
1755
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1756
+							'validation_strategies' => array(
1757
+								new EE_Max_Length_Validation_Strategy(
1758
+									esc_html__('Input too long', 'event_espresso'),
1759
+									100
1760
+								),
1761
+							),
1762
+						)
1763
+					),
1764
+					'accounting'      => new EE_Text_Input(
1765
+						array(
1766
+							'default'               => '',
1767
+							'required'              => false,
1768
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1769
+							'validation_strategies' => array(
1770
+								new EE_Max_Length_Validation_Strategy(
1771
+									esc_html__('Input too long', 'event_espresso'),
1772
+									100
1773
+								),
1774
+							),
1775
+						)
1776
+					),
1777
+				),
1778
+			)
1779
+		);
1780
+	}
1781
+
1782
+
1783
+	/**
1784
+	 * _create_payment_from_request_data
1785
+	 *
1786
+	 * @param array $valid_data
1787
+	 * @return EE_Payment
1788
+	 * @throws EE_Error
1789
+	 */
1790
+	protected function _create_payment_from_request_data($valid_data)
1791
+	{
1792
+		$PAY_ID = $valid_data['PAY_ID'];
1793
+		// get payment amount
1794
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1795
+		// payments have a type value of 1 and refunds have a type value of -1
1796
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1797
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1798
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1799
+		$date    = $valid_data['date']
1800
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1801
+			: date('Y-m-d g:i a', current_time('timestamp'));
1802
+		$payment = EE_Payment::new_instance(
1803
+			array(
1804
+				'TXN_ID'              => $valid_data['TXN_ID'],
1805
+				'STS_ID'              => $valid_data['status'],
1806
+				'PAY_timestamp'       => $date,
1807
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1808
+				'PMD_ID'              => $valid_data['PMD_ID'],
1809
+				'PAY_amount'          => $amount,
1810
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1811
+				'PAY_po_number'       => $valid_data['po_number'],
1812
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1813
+				'PAY_details'         => $valid_data,
1814
+				'PAY_ID'              => $PAY_ID,
1815
+			),
1816
+			'',
1817
+			array('Y-m-d', 'g:i a')
1818
+		);
1819
+
1820
+		if (! $payment->save()) {
1821
+			EE_Error::add_error(
1822
+				sprintf(
1823
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1824
+					$payment->ID()
1825
+				),
1826
+				__FILE__, __FUNCTION__, __LINE__
1827
+			);
1828
+		}
1829
+
1830
+		return $payment;
1831
+	}
1832
+
1833
+
1834
+	/**
1835
+	 * _process_transaction_payments
1836
+	 *
1837
+	 * @param \EE_Transaction $transaction
1838
+	 * @return void
1839
+	 * @throws EE_Error
1840
+	 * @throws InvalidArgumentException
1841
+	 * @throws ReflectionException
1842
+	 * @throws InvalidDataTypeException
1843
+	 * @throws InvalidInterfaceException
1844
+	 */
1845
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1846
+	{
1847
+		/** @type EE_Transaction_Payments $transaction_payments */
1848
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1849
+		//update the transaction with this payment
1850
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1851
+			EE_Error::add_success(esc_html__(
1852
+				'The payment has been processed successfully.', 'event_espresso'),
1853
+				__FILE__,
1854
+				__FUNCTION__,
1855
+				__LINE__
1856
+			);
1857
+		} else {
1858
+			EE_Error::add_error(
1859
+				esc_html__(
1860
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1861
+					'event_espresso'
1862
+				)
1863
+				,
1864
+				__FILE__,
1865
+				__FUNCTION__,
1866
+				__LINE__
1867
+			);
1868
+		}
1869
+	}
1870
+
1871
+
1872
+	/**
1873
+	 * _get_REG_IDs_to_apply_payment_to
1874
+	 * returns a list of registration IDs that the payment will apply to
1875
+	 *
1876
+	 * @param \EE_Payment $payment
1877
+	 * @return array
1878
+	 * @throws EE_Error
1879
+	 */
1880
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1881
+	{
1882
+		$REG_IDs = array();
1883
+		// grab array of IDs for specific registrations to apply changes to
1884
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1885
+			$REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1886
+		}
1887
+		//nothing specified ? then get all reg IDs
1888
+		if (empty($REG_IDs)) {
1889
+			$registrations = $payment->transaction()->registrations();
1890
+			$REG_IDs       = ! empty($registrations)
1891
+				? array_keys($registrations)
1892
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1893
+		}
1894
+
1895
+		// ensure that REG_IDs are integers and NOT strings
1896
+		return array_map('intval', $REG_IDs);
1897
+	}
1898
+
1899
+
1900
+	/**
1901
+	 * @return array
1902
+	 */
1903
+	public function existing_reg_payment_REG_IDs()
1904
+	{
1905
+		return $this->_existing_reg_payment_REG_IDs;
1906
+	}
1907
+
1908
+
1909
+	/**
1910
+	 * @param array $existing_reg_payment_REG_IDs
1911
+	 */
1912
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1913
+	{
1914
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1915
+	}
1916
+
1917
+
1918
+	/**
1919
+	 * _get_existing_reg_payment_REG_IDs
1920
+	 * returns a list of registration IDs that the payment is currently related to
1921
+	 * as recorded in the database
1922
+	 *
1923
+	 * @param \EE_Payment $payment
1924
+	 * @return array
1925
+	 * @throws EE_Error
1926
+	 */
1927
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1928
+	{
1929
+		if ($this->existing_reg_payment_REG_IDs() === null) {
1930
+			// let's get any existing reg payment records for this payment
1931
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1932
+			// but we only want the REG IDs, so grab the array keys
1933
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
1934
+				? array_keys($existing_reg_payment_REG_IDs)
1935
+				: array();
1936
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1937
+		}
1938
+
1939
+		return $this->existing_reg_payment_REG_IDs();
1940
+	}
1941
+
1942
+
1943
+	/**
1944
+	 * _remove_existing_registration_payments
1945
+	 * this calculates the difference between existing relations
1946
+	 * to the supplied payment and the new list registration IDs,
1947
+	 * removes any related registrations that no longer apply,
1948
+	 * and then updates the registration paid fields
1949
+	 *
1950
+	 * @param \EE_Payment $payment
1951
+	 * @param int         $PAY_ID
1952
+	 * @return bool;
1953
+	 * @throws EE_Error
1954
+	 * @throws InvalidArgumentException
1955
+	 * @throws ReflectionException
1956
+	 * @throws InvalidDataTypeException
1957
+	 * @throws InvalidInterfaceException
1958
+	 */
1959
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1960
+	{
1961
+		// newly created payments will have nothing recorded for $PAY_ID
1962
+		if ($PAY_ID == 0) {
1963
+			return false;
1964
+		}
1965
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1966
+		if (empty($existing_reg_payment_REG_IDs)) {
1967
+			return false;
1968
+		}
1969
+		/** @type EE_Transaction_Payments $transaction_payments */
1970
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1971
+
1972
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
1973
+			$payment,
1974
+			array(
1975
+				array(
1976
+					'PAY_ID' => $payment->ID(),
1977
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1978
+				),
1979
+			)
1980
+		);
1981
+	}
1982
+
1983
+
1984
+	/**
1985
+	 * _update_registration_payments
1986
+	 * this applies the payments to the selected registrations
1987
+	 * but only if they have not already been paid for
1988
+	 *
1989
+	 * @param  EE_Transaction $transaction
1990
+	 * @param \EE_Payment     $payment
1991
+	 * @param array           $REG_IDs
1992
+	 * @return void
1993
+	 * @throws EE_Error
1994
+	 * @throws InvalidArgumentException
1995
+	 * @throws ReflectionException
1996
+	 * @throws RuntimeException
1997
+	 * @throws InvalidDataTypeException
1998
+	 * @throws InvalidInterfaceException
1999
+	 */
2000
+	protected function _update_registration_payments(
2001
+		EE_Transaction $transaction,
2002
+		EE_Payment $payment,
2003
+		$REG_IDs = array()
2004
+	) {
2005
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2006
+		// so let's do that using our set of REG_IDs from the form
2007
+		$registration_query_where_params = array(
2008
+			'REG_ID' => array('IN', $REG_IDs),
2009
+		);
2010
+		// but add in some conditions regarding payment,
2011
+		// so that we don't apply payments to registrations that are free or have already been paid for
2012
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2013
+		if (! $payment->is_a_refund()) {
2014
+			$registration_query_where_params['REG_final_price']  = array('!=', 0);
2015
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2016
+		}
2017
+		$registrations = $transaction->registrations(array($registration_query_where_params));
2018
+		if (! empty($registrations)) {
2019
+			/** @type EE_Payment_Processor $payment_processor */
2020
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2021
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2022
+		}
2023
+	}
2024
+
2025
+
2026
+	/**
2027
+	 * _process_registration_status_change
2028
+	 * This processes requested registration status changes for all the registrations
2029
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2030
+	 *
2031
+	 * @param  EE_Transaction $transaction
2032
+	 * @param array           $REG_IDs
2033
+	 * @return bool
2034
+	 * @throws EE_Error
2035
+	 * @throws InvalidArgumentException
2036
+	 * @throws ReflectionException
2037
+	 * @throws InvalidDataTypeException
2038
+	 * @throws InvalidInterfaceException
2039
+	 */
2040
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2041
+	{
2042
+		// first if there is no change in status then we get out.
2043
+		if (
2044
+			! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2045
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2046
+		) {
2047
+			//no error message, no change requested, just nothing to do man.
2048
+			return false;
2049
+		}
2050
+		/** @type EE_Transaction_Processor $transaction_processor */
2051
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2052
+
2053
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2054
+		return $transaction_processor->manually_update_registration_statuses(
2055
+			$transaction,
2056
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2057
+			array(array('REG_ID' => array('IN', $REG_IDs)))
2058
+		);
2059
+	}
2060
+
2061
+
2062
+	/**
2063
+	 * _build_payment_json_response
2064
+	 *
2065
+	 * @access public
2066
+	 * @param \EE_Payment $payment
2067
+	 * @param array       $REG_IDs
2068
+	 * @param bool | null $delete_txn_reg_status_change
2069
+	 * @return array
2070
+	 * @throws EE_Error
2071
+	 * @throws InvalidArgumentException
2072
+	 * @throws InvalidDataTypeException
2073
+	 * @throws InvalidInterfaceException
2074
+	 * @throws ReflectionException
2075
+	 */
2076
+	protected function _build_payment_json_response(
2077
+		EE_Payment $payment,
2078
+		$REG_IDs = array(),
2079
+		$delete_txn_reg_status_change = null
2080
+	) {
2081
+		// was the payment deleted ?
2082
+		if (is_bool($delete_txn_reg_status_change)) {
2083
+			return array(
2084
+				'PAY_ID'                       => $payment->ID(),
2085
+				'amount'                       => $payment->amount(),
2086
+				'total_paid'                   => $payment->transaction()->paid(),
2087
+				'txn_status'                   => $payment->transaction()->status_ID(),
2088
+				'pay_status'                   => $payment->STS_ID(),
2089
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2090
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2091
+			);
2092
+		} else {
2093
+			$this->_get_payment_status_array();
2094
+
2095
+			return array(
2096
+				'amount'           => $payment->amount(),
2097
+				'total_paid'       => $payment->transaction()->paid(),
2098
+				'txn_status'       => $payment->transaction()->status_ID(),
2099
+				'pay_status'       => $payment->STS_ID(),
2100
+				'PAY_ID'           => $payment->ID(),
2101
+				'STS_ID'           => $payment->STS_ID(),
2102
+				'status'           => self::$_pay_status[$payment->STS_ID()],
2103
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2104
+				'method'           => strtoupper($payment->source()),
2105
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2106
+				'gateway'          => $payment->payment_method()
2107
+					? $payment->payment_method()->admin_name()
2108
+					: esc_html__("Unknown", 'event_espresso'),
2109
+				'gateway_response' => $payment->gateway_response(),
2110
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2111
+				'po_number'        => $payment->po_number(),
2112
+				'extra_accntng'    => $payment->extra_accntng(),
2113
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2114
+			);
2115
+		}
2116
+	}
2117
+
2118
+
2119
+	/**
2120
+	 * delete_payment
2121
+	 *    delete a payment or refund made towards a transaction
2122
+	 *
2123
+	 * @access public
2124
+	 * @return void
2125
+	 * @throws EE_Error
2126
+	 * @throws InvalidArgumentException
2127
+	 * @throws ReflectionException
2128
+	 * @throws InvalidDataTypeException
2129
+	 * @throws InvalidInterfaceException
2130
+	 */
2131
+	public function delete_payment()
2132
+	{
2133
+		$json_response_data = array('return_data' => false);
2134
+		$PAY_ID             = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2135
+			? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2136
+			: 0;
2137
+		$can_delete = EE_Registry::instance()->CAP->current_user_can(
2138
+			'ee_delete_payments',
2139
+			'delete_payment_from_registration_details'
2140
+		);
2141
+		if ($PAY_ID && $can_delete) {
2142
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2143
+				? $this->_req_data['delete_txn_reg_status_change']
2144
+				: false;
2145
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2146
+			if ($payment instanceof EE_Payment) {
2147
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2148
+				/** @type EE_Transaction_Payments $transaction_payments */
2149
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2150
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2151
+					$json_response_data['return_data'] = $this->_build_payment_json_response(
2152
+						$payment,
2153
+						$REG_IDs,
2154
+						$delete_txn_reg_status_change
2155
+					);
2156
+					if ($delete_txn_reg_status_change) {
2157
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2158
+						//MAKE sure we also add the delete_txn_req_status_change to the
2159
+						//$_REQUEST global because that's how messages will be looking for it.
2160
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2161
+						$this->_maybe_send_notifications();
2162
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2163
+					}
2164
+				}
2165
+			} else {
2166
+				EE_Error::add_error(
2167
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2168
+					__FILE__, __FUNCTION__, __LINE__
2169
+				);
2170
+			}
2171
+		} else {
2172
+			if ($can_delete) {
2173
+				EE_Error::add_error(
2174
+					esc_html__(
2175
+						'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2176
+						'event_espresso'
2177
+					),
2178
+					__FILE__, __FUNCTION__, __LINE__
2179
+				);
2180
+			} else {
2181
+				EE_Error::add_error(
2182
+					esc_html__(
2183
+						'You do not have access to delete a payment.',
2184
+						'event_espresso'
2185
+					),
2186
+					__FILE__,
2187
+					__FUNCTION__,
2188
+					__LINE__
2189
+				);
2190
+			}
2191
+		}
2192
+		$notices              = EE_Error::get_notices(false, false, false);
2193
+		$this->_template_args = array(
2194
+			'data'      => $json_response_data,
2195
+			'success'   => $notices['success'],
2196
+			'error'     => $notices['errors'],
2197
+			'attention' => $notices['attention'],
2198
+		);
2199
+		$this->_return_json();
2200
+	}
2201
+
2202
+
2203
+	/**
2204
+	 * _registration_payment_data_array
2205
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2206
+	 *
2207
+	 * @access protected
2208
+	 * @param array $REG_IDs
2209
+	 * @return array
2210
+	 * @throws EE_Error
2211
+	 * @throws InvalidArgumentException
2212
+	 * @throws InvalidDataTypeException
2213
+	 * @throws InvalidInterfaceException
2214
+	 * @throws ReflectionException
2215
+	 */
2216
+	protected function _registration_payment_data_array($REG_IDs)
2217
+	{
2218
+		$registration_payment_data = array();
2219
+		//if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2220
+		if (! empty($REG_IDs)) {
2221
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2222
+			foreach ($registrations as $registration) {
2223
+				if ($registration instanceof EE_Registration) {
2224
+					$registration_payment_data[$registration->ID()] = array(
2225
+						'paid'  => $registration->pretty_paid(),
2226
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2227
+					);
2228
+				}
2229
+			}
2230
+		}
2231
+
2232
+		return $registration_payment_data;
2233
+	}
2234
+
2235
+
2236
+	/**
2237
+	 * _maybe_send_notifications
2238
+	 * determines whether or not the admin has indicated that notifications should be sent.
2239
+	 * If so, will toggle a filter switch for delivering registration notices.
2240
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2241
+	 *
2242
+	 * @access protected
2243
+	 * @param \EE_Payment | null $payment
2244
+	 */
2245
+	protected function _maybe_send_notifications($payment = null)
2246
+	{
2247
+		switch ($payment instanceof EE_Payment) {
2248
+			// payment notifications
2249
+			case true :
2250
+				if (
2251
+					isset(
2252
+						$this->_req_data['txn_payments'],
2253
+						$this->_req_data['txn_payments']['send_notifications']
2254
+					) &&
2255
+					filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2256
+				) {
2257
+					$this->_process_payment_notification($payment);
2258
+				}
2259
+				break;
2260
+			// registration notifications
2261
+			case false :
2262
+				if (
2263
+					isset(
2264
+						$this->_req_data['txn_reg_status_change'],
2265
+						$this->_req_data['txn_reg_status_change']['send_notifications']
2266
+					) &&
2267
+					filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2268
+				) {
2269
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2270
+				}
2271
+				break;
2272
+		}
2273
+	}
2274
+
2275
+
2276
+	/**
2277
+	 * _send_payment_reminder
2278
+	 *    generates HTML for the View Transaction Details Admin page
2279
+	 *
2280
+	 * @access protected
2281
+	 * @return void
2282
+	 * @throws EE_Error
2283
+	 * @throws InvalidArgumentException
2284
+	 * @throws InvalidDataTypeException
2285
+	 * @throws InvalidInterfaceException
2286
+	 */
2287
+	protected function _send_payment_reminder()
2288
+	{
2289
+		$TXN_ID      = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2290
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2291
+		$query_args  = isset($this->_req_data['redirect_to']) ? array(
2292
+			'action' => $this->_req_data['redirect_to'],
2293
+			'TXN_ID' => $this->_req_data['TXN_ID'],
2294
+		) : array();
2295
+		do_action(
2296
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2297
+			$transaction
2298
+		);
2299
+		$this->_redirect_after_action(
2300
+			false,
2301
+			esc_html__('payment reminder', 'event_espresso'),
2302
+			esc_html__('sent', 'event_espresso'),
2303
+			$query_args,
2304
+			true
2305
+		);
2306
+	}
2307
+
2308
+
2309
+	/**
2310
+	 *  get_transactions
2311
+	 *    get transactions for given parameters (used by list table)
2312
+	 *
2313
+	 * @param  int     $perpage how many transactions displayed per page
2314
+	 * @param  boolean $count   return the count or objects
2315
+	 * @param string   $view
2316
+	 * @return mixed int = count || array of transaction objects
2317
+	 * @throws EE_Error
2318
+	 * @throws InvalidArgumentException
2319
+	 * @throws InvalidDataTypeException
2320
+	 * @throws InvalidInterfaceException
2321
+	 */
2322
+	public function get_transactions($perpage, $count = false, $view = '')
2323
+	{
2324
+
2325
+		$TXN = EEM_Transaction::instance();
2326
+
2327
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
2328
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2329
+			: date(
2330
+				'm/d/Y',
2331
+				strtotime('-10 year')
2332
+			);
2333
+		$end_date   = isset($this->_req_data['txn-filter-end-date'])
2334
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2335
+			: date('m/d/Y');
2336
+
2337
+		//make sure our timestamps start and end right at the boundaries for each day
2338
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2339
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2340
+
2341
+
2342
+		//convert to timestamps
2343
+		$start_date = strtotime($start_date);
2344
+		$end_date   = strtotime($end_date);
2345
+
2346
+		//makes sure start date is the lowest value and vice versa
2347
+		$start_date = min($start_date, $end_date);
2348
+		$end_date   = max($start_date, $end_date);
2349
+
2350
+		//convert to correct format for query
2351
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2352
+			'TXN_timestamp',
2353
+			date('Y-m-d H:i:s', $start_date),
2354
+			'Y-m-d H:i:s'
2355
+		);
2356
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2357
+			'TXN_timestamp',
2358
+			date('Y-m-d H:i:s', $end_date),
2359
+			'Y-m-d H:i:s'
2360
+		);
2361
+
2362
+
2363
+		//set orderby
2364
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2365
+
2366
+		switch ($this->_req_data['orderby']) {
2367
+			case 'TXN_ID':
2368
+				$orderby = 'TXN_ID';
2369
+				break;
2370
+			case 'ATT_fname':
2371
+				$orderby = 'Registration.Attendee.ATT_fname';
2372
+				break;
2373
+			case 'event_name':
2374
+				$orderby = 'Registration.Event.EVT_name';
2375
+				break;
2376
+			default: //'TXN_timestamp'
2377
+				$orderby = 'TXN_timestamp';
2378
+		}
2379
+
2380
+		$sort         = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2381
+		$current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2382
+		$per_page     = ! empty($perpage) ? $perpage : 10;
2383
+		$per_page     = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2384
+
2385
+		$offset = ($current_page - 1) * $per_page;
2386
+		$limit  = array($offset, $per_page);
2387
+
2388
+		$_where = array(
2389
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2390
+			'Registration.REG_count' => 1,
2391
+		);
2392
+
2393
+		if (isset($this->_req_data['EVT_ID'])) {
2394
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2395
+		}
2396
+
2397
+		if (isset($this->_req_data['s'])) {
2398
+			$search_string = '%' . $this->_req_data['s'] . '%';
2399
+			$_where['OR']  = array(
2400
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2401
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2402
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2403
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2404
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2405
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2406
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2407
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2408
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2409
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2410
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2411
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
2412
+				'Registration.REG_code'               => array('LIKE', $search_string),
2413
+				'Registration.REG_count'              => array('LIKE', $search_string),
2414
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
2415
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2416
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2417
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
2418
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2419
+				'TXN_session_data'                    => array('LIKE', $search_string),
2420
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2421
+			);
2422
+		}
2423
+
2424
+		//failed transactions
2425
+		$failed    = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2426
+					 || ($count && $view === 'failed');
2427
+		$abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2428
+					 || ($count && $view === 'abandoned');
2429
+
2430
+		if ($failed) {
2431
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2432
+		} else if ($abandoned) {
2433
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2434
+		} else {
2435
+			$_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
2436
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2437
+		}
2438
+
2439
+		$query_params = array(
2440
+			$_where,
2441
+			'order_by'                 => array($orderby => $sort),
2442
+			'limit'                    => $limit,
2443
+			'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2444
+		);
2445
+
2446
+		$transactions = $count
2447
+			? $TXN->count(array($_where), 'TXN_ID', true)
2448
+			: $TXN->get_all($query_params);
2449
+
2450
+		return $transactions;
2451
+	}
2452 2452
 }
Please login to merge, or discard this patch.
Spacing   +81 added lines, -81 removed lines patch added patch discarded remove patch
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
             'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
267 267
             'event_espresso'
268 268
         );
269
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
269
+        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
270 270
             'An error occurred! Please refresh the page and try again.',
271 271
             'event_espresso'
272 272
         );
@@ -364,13 +364,13 @@  discard block
 block discarded – undo
364 364
         //enqueue style
365 365
         wp_register_style(
366 366
             'espresso_txn',
367
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
367
+            TXN_ASSETS_URL.'espresso_transactions_admin.css',
368 368
             array(),
369 369
             EVENT_ESPRESSO_VERSION
370 370
         );
371 371
         wp_enqueue_style('espresso_txn');
372 372
         //scripts
373
-        wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
373
+        wp_register_script('espresso_txn', TXN_ASSETS_URL.'espresso_transactions_admin.js', array(
374 374
             'ee_admin_js',
375 375
             'ee-datepicker',
376 376
             'jquery-ui-datepicker',
@@ -467,7 +467,7 @@  discard block
 block discarded – undo
467 467
             : null;
468 468
         $this->_transaction->verify_abandoned_transaction_status();
469 469
 
470
-        if (! $this->_transaction instanceof EE_Transaction) {
470
+        if ( ! $this->_transaction instanceof EE_Transaction) {
471 471
             $error_msg = sprintf(
472 472
                 esc_html__(
473 473
                     'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
@@ -565,7 +565,7 @@  discard block
 block discarded – undo
565 565
             'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
566 566
             array(
567 567
                 'overpaid'   => array(
568
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
568
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::overpaid_status_code,
569 569
                     'desc'  => EEH_Template::pretty_status(
570 570
                         EEM_Transaction::overpaid_status_code,
571 571
                         false,
@@ -573,7 +573,7 @@  discard block
 block discarded – undo
573 573
                     ),
574 574
                 ),
575 575
                 'complete'   => array(
576
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
576
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::complete_status_code,
577 577
                     'desc'  => EEH_Template::pretty_status(
578 578
                         EEM_Transaction::complete_status_code,
579 579
                         false,
@@ -581,7 +581,7 @@  discard block
 block discarded – undo
581 581
                     ),
582 582
                 ),
583 583
                 'incomplete' => array(
584
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
584
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::incomplete_status_code,
585 585
                     'desc'  => EEH_Template::pretty_status(
586 586
                         EEM_Transaction::incomplete_status_code,
587 587
                         false,
@@ -589,7 +589,7 @@  discard block
 block discarded – undo
589 589
                     ),
590 590
                 ),
591 591
                 'abandoned'  => array(
592
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
592
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::abandoned_status_code,
593 593
                     'desc'  => EEH_Template::pretty_status(
594 594
                         EEM_Transaction::abandoned_status_code,
595 595
                         false,
@@ -597,7 +597,7 @@  discard block
 block discarded – undo
597 597
                     ),
598 598
                 ),
599 599
                 'failed'     => array(
600
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
600
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::failed_status_code,
601 601
                     'desc'  => EEH_Template::pretty_status(
602 602
                         EEM_Transaction::failed_status_code,
603 603
                         false,
@@ -646,11 +646,11 @@  discard block
 block discarded – undo
646 646
                     'Click to Edit event',
647 647
                     'event_espresso'
648 648
                 )
649
-                . '">' . $event->get('EVT_name') . '</a>',
649
+                . '">'.$event->get('EVT_name').'</a>',
650 650
                 '</h3>'
651 651
             )
652 652
             : '';
653
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
653
+        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
654 654
         $this->display_admin_list_table_page_with_no_sidebar();
655 655
     }
656 656
 
@@ -693,7 +693,7 @@  discard block
 block discarded – undo
693 693
 
694 694
         $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
695 695
         $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
696
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
696
+        $this->_template_args['txn_status']['class'] = 'status-'.$this->_transaction->get('STS_ID');
697 697
 
698 698
         $this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
699 699
         $this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
@@ -746,7 +746,7 @@  discard block
 block discarded – undo
746 746
 
747 747
 
748 748
         // next link
749
-        $next_txn                                 = $this->_transaction->next(
749
+        $next_txn = $this->_transaction->next(
750 750
             null,
751 751
             array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
752 752
             'TXN_ID'
@@ -761,7 +761,7 @@  discard block
 block discarded – undo
761 761
             )
762 762
             : '';
763 763
         // previous link
764
-        $previous_txn                                 = $this->_transaction->previous(
764
+        $previous_txn = $this->_transaction->previous(
765 765
             null,
766 766
             array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
767 767
             'TXN_ID'
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
         // grab messages at the last second
812 812
         $this->_template_args['notices'] = EE_Error::get_notices();
813 813
         // path to template
814
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
814
+        $template_path                             = TXN_TEMPLATE_PATH.'txn_admin_details_header.template.php';
815 815
         $this->_template_args['admin_page_header'] = EEH_Template::display_template(
816 816
             $template_path,
817 817
             $this->_template_args,
@@ -893,7 +893,7 @@  discard block
 block discarded – undo
893 893
     {
894 894
         $content = '';
895 895
         $actions = array();
896
-        if (! $transaction instanceof EE_Transaction) {
896
+        if ( ! $transaction instanceof EE_Transaction) {
897 897
             return $content;
898 898
         }
899 899
         /** @var EE_Registration $primary_registration */
@@ -954,7 +954,7 @@  discard block
 block discarded – undo
954 954
         );
955 955
         if ($actions) {
956 956
             $content = '<ul>';
957
-            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
957
+            $content .= '<li>'.implode('</li><li>', $actions).'</li>';
958 958
             $content .= '</uL>';
959 959
         }
960 960
         return $content;
@@ -992,7 +992,7 @@  discard block
 block discarded – undo
992 992
 
993 993
         //get line table
994 994
         EEH_Autoloader::register_line_item_display_autoloaders();
995
-        $Line_Item_Display                       = new EE_Line_Item_Display(
995
+        $Line_Item_Display = new EE_Line_Item_Display(
996 996
             'admin_table',
997 997
             'EE_Admin_Table_Line_Item_Display_Strategy'
998 998
         );
@@ -1003,13 +1003,13 @@  discard block
 block discarded – undo
1003 1003
                                                                       ->get('REG_code');
1004 1004
 
1005 1005
         // process taxes
1006
-        $taxes                         = $this->_transaction->get_many_related(
1006
+        $taxes = $this->_transaction->get_many_related(
1007 1007
             'Line_Item',
1008 1008
             array(array('LIN_type' => EEM_Line_Item::type_tax))
1009 1009
         );
1010 1010
         $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1011 1011
 
1012
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1012
+        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1013 1013
             $this->_transaction->get('TXN_total'),
1014 1014
             false,
1015 1015
             false
@@ -1019,7 +1019,7 @@  discard block
 block discarded – undo
1019 1019
 
1020 1020
         // process payment details
1021 1021
         $payments = $this->_transaction->get_many_related('Payment');
1022
-        if (! empty($payments)) {
1022
+        if ( ! empty($payments)) {
1023 1023
             $this->_template_args['payments']              = $payments;
1024 1024
             $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1025 1025
         } else {
@@ -1080,7 +1080,7 @@  discard block
 block discarded – undo
1080 1080
                                   esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1081 1081
                                   ucwords(str_replace('_', ' ', $reg_step)),
1082 1082
                                   date(
1083
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1083
+                                      get_option('date_format').' '.get_option('time_format'),
1084 1084
                                       ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1085 1085
                                   )
1086 1086
                               )
@@ -1094,7 +1094,7 @@  discard block
 block discarded – undo
1094 1094
                               . '</li>';
1095 1095
             }
1096 1096
         }
1097
-        $reg_steps                                                 .= '</ul>';
1097
+        $reg_steps .= '</ul>';
1098 1098
         $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1099 1099
         $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1100 1100
             'Registration Step Progress',
@@ -1107,11 +1107,11 @@  discard block
 block discarded – undo
1107 1107
         $this->_get_payment_status_array();
1108 1108
         $this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
1109 1109
 
1110
-        $this->_template_args['transaction_form_url']    = add_query_arg(array(
1110
+        $this->_template_args['transaction_form_url'] = add_query_arg(array(
1111 1111
             'action'  => 'edit_transaction',
1112 1112
             'process' => 'transaction',
1113 1113
         ), TXN_ADMIN_URL);
1114
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(array(
1114
+        $this->_template_args['apply_payment_form_url'] = add_query_arg(array(
1115 1115
             'page'   => 'espresso_transactions',
1116 1116
             'action' => 'espresso_apply_payment',
1117 1117
         ), WP_AJAX_URL);
@@ -1124,7 +1124,7 @@  discard block
 block discarded – undo
1124 1124
 
1125 1125
         // 'espresso_delete_payment_nonce'
1126 1126
 
1127
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1127
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_txn_details.template.php';
1128 1128
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
1129 1129
     }
1130 1130
 
@@ -1154,11 +1154,11 @@  discard block
 block discarded – undo
1154 1154
                 ),
1155 1155
             ),
1156 1156
         ));
1157
-        if (! empty($reg_payments)) {
1157
+        if ( ! empty($reg_payments)) {
1158 1158
             foreach ($payments as $payment) {
1159
-                if (! $payment instanceof EE_Payment) {
1159
+                if ( ! $payment instanceof EE_Payment) {
1160 1160
                     continue;
1161
-                } elseif (! isset($existing_reg_payments[$payment->ID()])) {
1161
+                } elseif ( ! isset($existing_reg_payments[$payment->ID()])) {
1162 1162
                     $existing_reg_payments[$payment->ID()] = array();
1163 1163
                 }
1164 1164
                 foreach ($reg_payments as $reg_payment) {
@@ -1187,7 +1187,7 @@  discard block
 block discarded – undo
1187 1187
     protected function _get_registrations_to_apply_payment_to()
1188 1188
     {
1189 1189
         // we want any registration with an active status (ie: not deleted or cancelled)
1190
-        $query_params                      = array(
1190
+        $query_params = array(
1191 1191
             array(
1192 1192
                 'STS_ID' => array(
1193 1193
                     'IN',
@@ -1206,16 +1206,16 @@  discard block
 block discarded – undo
1206 1206
                                                  '',
1207 1207
                                                  'clear: both; margin: 1.5em 0 0; display: none;'
1208 1208
                                              );
1209
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1209
+        $registrations_to_apply_payment_to .= EEH_HTML::br().EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1210 1210
         $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1211 1211
         $registrations_to_apply_payment_to .= EEH_HTML::thead(
1212 1212
             EEH_HTML::tr(
1213
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1214
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1215
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1216
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1217
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1218
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1213
+                EEH_HTML::th(esc_html__('ID', 'event_espresso')).
1214
+                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')).
1215
+                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')).
1216
+                EEH_HTML::th(esc_html__('Event', 'event_espresso')).
1217
+                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr').
1218
+                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr').
1219 1219
                 EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1220 1220
             )
1221 1221
         );
@@ -1230,29 +1230,29 @@  discard block
 block discarded – undo
1230 1230
                     : esc_html__('Unknown Attendee', 'event_espresso');
1231 1231
                 $owing                             = $registration->final_price() - $registration->paid();
1232 1232
                 $taxable                           = $registration->ticket()->taxable()
1233
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1233
+                    ? ' <span class="smaller-text lt-grey-text"> '.esc_html__('+ tax', 'event_espresso').'</span>'
1234 1234
                     : '';
1235 1235
                 $checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1236 1236
                     ? ' checked="checked"'
1237 1237
                     : '';
1238
-                $disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1238
+                $disabled = $registration->final_price() > 0 ? '' : ' disabled';
1239 1239
                 $registrations_to_apply_payment_to .= EEH_HTML::tr(
1240
-                    EEH_HTML::td($registration->ID()) .
1241
-                    EEH_HTML::td($attendee_name) .
1240
+                    EEH_HTML::td($registration->ID()).
1241
+                    EEH_HTML::td($attendee_name).
1242 1242
                     EEH_HTML::td(
1243
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1244
-                    ) .
1245
-                    EEH_HTML::td($registration->event_name()) .
1246
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1247
-                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1243
+                        $registration->ticket()->name().' : '.$registration->ticket()->pretty_price().$taxable
1244
+                    ).
1245
+                    EEH_HTML::td($registration->event_name()).
1246
+                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr').
1247
+                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr').
1248 1248
                     EEH_HTML::td(
1249
-                        '<input type="checkbox" value="' . $registration->ID()
1249
+                        '<input type="checkbox" value="'.$registration->ID()
1250 1250
                         . '" name="txn_admin_payment[registrations]"'
1251
-                        . $checked . $disabled . '>',
1251
+                        . $checked.$disabled.'>',
1252 1252
                         '',
1253 1253
                         'jst-cntr'
1254 1254
                     ),
1255
-                    'apply-payment-registration-row-' . $registration->ID()
1255
+                    'apply-payment-registration-row-'.$registration->ID()
1256 1256
                 );
1257 1257
             }
1258 1258
         }
@@ -1267,7 +1267,7 @@  discard block
 block discarded – undo
1267 1267
             '',
1268 1268
             'clear description'
1269 1269
         );
1270
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1270
+        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1271 1271
         $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1272 1272
     }
1273 1273
 
@@ -1333,12 +1333,12 @@  discard block
 block discarded – undo
1333 1333
                 array(
1334 1334
                     'OR*payment_method_for_payment' => array(
1335 1335
                         'PMD_ID'    => array('IN', $payment_methods_of_payments),
1336
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1336
+                        'PMD_scope' => array('LIKE', '%'.EEM_Payment_Method::scope_admin.'%'),
1337 1337
                     ),
1338 1338
                 ),
1339 1339
             );
1340 1340
         } else {
1341
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1341
+            $query_args = array(array('PMD_scope' => array('LIKE', '%'.EEM_Payment_Method::scope_admin.'%')));
1342 1342
         }
1343 1343
         $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1344 1344
     }
@@ -1367,7 +1367,7 @@  discard block
 block discarded – undo
1367 1367
             'Line_Item',
1368 1368
             array(array('LIN_type' => 'line-item'))
1369 1369
         );
1370
-        if (! empty($line_items)) {
1370
+        if ( ! empty($line_items)) {
1371 1371
             foreach ($line_items as $item) {
1372 1372
                 if ($item instanceof EE_Line_Item) {
1373 1373
                     switch ($item->OBJ_type()) {
@@ -1377,7 +1377,7 @@  discard block
 block discarded – undo
1377 1377
                             $ticket = $item->ticket();
1378 1378
                             //right now we're only handling tickets here.
1379 1379
                             //Cause its expected that only tickets will have attendees right?
1380
-                            if (! $ticket instanceof EE_Ticket) {
1380
+                            if ( ! $ticket instanceof EE_Ticket) {
1381 1381
                                 continue;
1382 1382
                             }
1383 1383
                             try {
@@ -1386,7 +1386,7 @@  discard block
 block discarded – undo
1386 1386
                                 EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1387 1387
                                 $event_name = esc_html__('Unknown Event', 'event_espresso');
1388 1388
                             }
1389
-                            $event_name   .= ' - ' . $item->get('LIN_name');
1389
+                            $event_name   .= ' - '.$item->get('LIN_name');
1390 1390
                             $ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1391 1391
                             // now get all of the registrations for this transaction that use this ticket
1392 1392
                             $registrations = $ticket->get_many_related(
@@ -1394,7 +1394,7 @@  discard block
 block discarded – undo
1394 1394
                                 array(array('TXN_ID' => $this->_transaction->ID()))
1395 1395
                             );
1396 1396
                             foreach ($registrations as $registration) {
1397
-                                if (! $registration instanceof EE_Registration) {
1397
+                                if ( ! $registration instanceof EE_Registration) {
1398 1398
                                     continue;
1399 1399
                                 }
1400 1400
                                 $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
@@ -1413,12 +1413,12 @@  discard block
 block discarded – undo
1413 1413
                                     $this->_template_args['event_attendees'][$registration->ID()]['attendee']
1414 1414
                                         = $attendee->full_name();
1415 1415
                                     $this->_template_args['event_attendees'][$registration->ID()]['email']
1416
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1416
+                                        = '<a href="mailto:'.$attendee->email().'?subject='.$event_name
1417 1417
                                           . esc_html__(
1418 1418
                                               ' Event',
1419 1419
                                               'event_espresso'
1420 1420
                                           )
1421
-                                          . '">' . $attendee->email() . '</a>';
1421
+                                          . '">'.$attendee->email().'</a>';
1422 1422
                                     $this->_template_args['event_attendees'][$registration->ID()]['address']
1423 1423
                                         = EEH_Address::format($attendee, 'inline', false, false);
1424 1424
                                 } else {
@@ -1442,7 +1442,7 @@  discard block
 block discarded – undo
1442 1442
                 TXN_ADMIN_URL
1443 1443
             );
1444 1444
             echo EEH_Template::display_template(
1445
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1445
+                TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_attendees.template.php',
1446 1446
                 $this->_template_args,
1447 1447
                 true
1448 1448
             );
@@ -1478,12 +1478,12 @@  discard block
 block discarded – undo
1478 1478
         $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1479 1479
             ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1480 1480
             : null;
1481
-        if (! $primary_att instanceof EE_Attendee) {
1481
+        if ( ! $primary_att instanceof EE_Attendee) {
1482 1482
             $this->_template_args['no_attendee_message'] = esc_html__(
1483 1483
                 'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1484 1484
                 'event_espresso'
1485 1485
             );
1486
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1486
+            $primary_att = EEM_Attendee::instance()->create_default_object();
1487 1487
         }
1488 1488
         $this->_template_args['ATT_ID']            = $primary_att->ID();
1489 1489
         $this->_template_args['prime_reg_fname']   = $primary_att->fname();
@@ -1497,7 +1497,7 @@  discard block
 block discarded – undo
1497 1497
         // get formatted address for registrant
1498 1498
         $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1499 1499
         echo EEH_Template::display_template(
1500
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1500
+            TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_registrant.template.php',
1501 1501
             $this->_template_args,
1502 1502
             true
1503 1503
         );
@@ -1522,8 +1522,8 @@  discard block
 block discarded – undo
1522 1522
             TXN_ADMIN_URL
1523 1523
         );
1524 1524
 
1525
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1526
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1525
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_billing_info.template.php';
1526
+        echo EEH_Template::display_template($template_path, $this->_template_args, true); /**/
1527 1527
     }
1528 1528
 
1529 1529
 
@@ -1548,7 +1548,7 @@  discard block
 block discarded – undo
1548 1548
             'ee_edit_payments',
1549 1549
             'apply_payment_or_refund_from_registration_details'
1550 1550
         );
1551
-        if (! empty($valid_data) && $has_access) {
1551
+        if ( ! empty($valid_data) && $has_access) {
1552 1552
             $PAY_ID = $valid_data['PAY_ID'];
1553 1553
             //save  the new payment
1554 1554
             $payment = $this->_create_payment_from_request_data($valid_data);
@@ -1561,7 +1561,7 @@  discard block
 block discarded – undo
1561 1561
                 $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1562 1562
                 $this->_remove_existing_registration_payments($payment, $PAY_ID);
1563 1563
                 // apply payment to registrations (if applicable)
1564
-                if (! empty($REG_IDs)) {
1564
+                if ( ! empty($REG_IDs)) {
1565 1565
                     $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1566 1566
                     $this->_maybe_send_notifications();
1567 1567
                     // now process status changes for the same registrations
@@ -1609,7 +1609,7 @@  discard block
 block discarded – undo
1609 1609
                 );
1610 1610
             }
1611 1611
         }
1612
-        $notices              = EE_Error::get_notices(
1612
+        $notices = EE_Error::get_notices(
1613 1613
             false,
1614 1614
             false,
1615 1615
             false
@@ -1631,14 +1631,14 @@  discard block
 block discarded – undo
1631 1631
      */
1632 1632
     protected function _validate_payment_request_data()
1633 1633
     {
1634
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1634
+        if ( ! isset($this->_req_data['txn_admin_payment'])) {
1635 1635
             return false;
1636 1636
         }
1637 1637
         $payment_form = $this->_generate_payment_form_section();
1638 1638
         try {
1639 1639
             if ($payment_form->was_submitted()) {
1640 1640
                 $payment_form->receive_form_submission();
1641
-                if (! $payment_form->is_valid()) {
1641
+                if ( ! $payment_form->is_valid()) {
1642 1642
                     $submission_error_messages = array();
1643 1643
                     foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1644 1644
                         if ($validation_error instanceof EE_Validation_Error) {
@@ -1817,7 +1817,7 @@  discard block
 block discarded – undo
1817 1817
             array('Y-m-d', 'g:i a')
1818 1818
         );
1819 1819
 
1820
-        if (! $payment->save()) {
1820
+        if ( ! $payment->save()) {
1821 1821
             EE_Error::add_error(
1822 1822
                 sprintf(
1823 1823
                     esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
@@ -1882,7 +1882,7 @@  discard block
 block discarded – undo
1882 1882
         $REG_IDs = array();
1883 1883
         // grab array of IDs for specific registrations to apply changes to
1884 1884
         if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1885
-            $REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1885
+            $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1886 1886
         }
1887 1887
         //nothing specified ? then get all reg IDs
1888 1888
         if (empty($REG_IDs)) {
@@ -2010,12 +2010,12 @@  discard block
 block discarded – undo
2010 2010
         // but add in some conditions regarding payment,
2011 2011
         // so that we don't apply payments to registrations that are free or have already been paid for
2012 2012
         // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2013
-        if (! $payment->is_a_refund()) {
2013
+        if ( ! $payment->is_a_refund()) {
2014 2014
             $registration_query_where_params['REG_final_price']  = array('!=', 0);
2015 2015
             $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2016 2016
         }
2017 2017
         $registrations = $transaction->registrations(array($registration_query_where_params));
2018
-        if (! empty($registrations)) {
2018
+        if ( ! empty($registrations)) {
2019 2019
             /** @type EE_Payment_Processor $payment_processor */
2020 2020
             $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2021 2021
             $payment_processor->process_registration_payments($transaction, $payment, $registrations);
@@ -2217,7 +2217,7 @@  discard block
 block discarded – undo
2217 2217
     {
2218 2218
         $registration_payment_data = array();
2219 2219
         //if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2220
-        if (! empty($REG_IDs)) {
2220
+        if ( ! empty($REG_IDs)) {
2221 2221
             $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2222 2222
             foreach ($registrations as $registration) {
2223 2223
                 if ($registration instanceof EE_Registration) {
@@ -2330,13 +2330,13 @@  discard block
 block discarded – undo
2330 2330
                 'm/d/Y',
2331 2331
                 strtotime('-10 year')
2332 2332
             );
2333
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
2333
+        $end_date = isset($this->_req_data['txn-filter-end-date'])
2334 2334
             ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2335 2335
             : date('m/d/Y');
2336 2336
 
2337 2337
         //make sure our timestamps start and end right at the boundaries for each day
2338
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2339
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2338
+        $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00';
2339
+        $end_date   = date('Y-m-d', strtotime($end_date)).' 23:59:59';
2340 2340
 
2341 2341
 
2342 2342
         //convert to timestamps
@@ -2353,7 +2353,7 @@  discard block
 block discarded – undo
2353 2353
             date('Y-m-d H:i:s', $start_date),
2354 2354
             'Y-m-d H:i:s'
2355 2355
         );
2356
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2356
+        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2357 2357
             'TXN_timestamp',
2358 2358
             date('Y-m-d H:i:s', $end_date),
2359 2359
             'Y-m-d H:i:s'
@@ -2395,7 +2395,7 @@  discard block
 block discarded – undo
2395 2395
         }
2396 2396
 
2397 2397
         if (isset($this->_req_data['s'])) {
2398
-            $search_string = '%' . $this->_req_data['s'] . '%';
2398
+            $search_string = '%'.$this->_req_data['s'].'%';
2399 2399
             $_where['OR']  = array(
2400 2400
                 'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2401 2401
                 'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
@@ -2422,9 +2422,9 @@  discard block
 block discarded – undo
2422 2422
         }
2423 2423
 
2424 2424
         //failed transactions
2425
-        $failed    = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2425
+        $failed    = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2426 2426
                      || ($count && $view === 'failed');
2427
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2427
+        $abandoned = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2428 2428
                      || ($count && $view === 'abandoned');
2429 2429
 
2430 2430
         if ($failed) {
Please login to merge, or discard this patch.
core/request_stack/EE_Request.core.php 1 patch
Indentation   +363 added lines, -363 removed lines patch added patch discarded remove patch
@@ -22,369 +22,369 @@
 block discarded – undo
22 22
 class EE_Request implements LegacyRequestInterface, InterminableInterface
23 23
 {
24 24
 
25
-    /**
26
-     * @var RequestInterface $request
27
-     */
28
-    private $request;
29
-
30
-    /**
31
-     * whether current request is for the admin but NOT via AJAX
32
-     *
33
-     * @var boolean $admin
34
-     */
35
-    public $admin = false;
36
-
37
-    /**
38
-     * whether current request is via AJAX
39
-     *
40
-     * @var boolean $ajax
41
-     */
42
-    public $ajax = false;
43
-
44
-    /**
45
-     * whether current request is via AJAX from the frontend of the site
46
-     *
47
-     * @var boolean $front_ajax
48
-     */
49
-    public $front_ajax = false;
50
-
51
-
52
-    /**
53
-     * @deprecated 4.9.53
54
-     * @param array $get
55
-     * @param array $post
56
-     * @param array $cookie
57
-     * @param array $server
58
-     */
59
-    public function __construct(
60
-        array $get = array(),
61
-        array $post = array(),
62
-        array $cookie = array(),
63
-        array $server = array()
64
-    ) {
65
-    }
66
-
67
-
68
-    /**
69
-     * @return RequestInterface
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidInterfaceException
72
-     * @throws InvalidDataTypeException
73
-     */
74
-    private function request()
75
-    {
76
-        if($this->request instanceof RequestInterface){
77
-            return $this->request;
78
-        }
79
-        $loader = LoaderFactory::getLoader();
80
-        $this->request = $loader->getShared('EventEspresso\core\services\request\RequestInterface');
81
-        return $this->request;
82
-    }
83
-
84
-
85
-    /**
86
-     * @param RequestInterface $request
87
-     */
88
-    public function setRequest(RequestInterface $request)
89
-    {
90
-        $this->request = $request;
91
-    }
92
-
93
-
94
-
95
-    /**
96
-     * @deprecated 4.9.53
97
-     * @return array
98
-     * @throws InvalidArgumentException
99
-     * @throws InvalidDataTypeException
100
-     * @throws InvalidInterfaceException
101
-     */
102
-    public function get_params()
103
-    {
104
-        return $this->request()->getParams();
105
-    }
106
-
107
-
108
-
109
-    /**
110
-     * @deprecated 4.9.53
111
-     * @return array
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     */
116
-    public function post_params()
117
-    {
118
-        return $this->request()->postParams();
119
-    }
120
-
121
-
122
-
123
-    /**
124
-     * @deprecated 4.9.53
125
-     * @return array
126
-     * @throws InvalidArgumentException
127
-     * @throws InvalidDataTypeException
128
-     * @throws InvalidInterfaceException
129
-     */
130
-    public function cookie_params()
131
-    {
132
-        return $this->request()->cookieParams();
133
-    }
134
-
135
-
136
-    /**
137
-     * @deprecated 4.9.53
138
-     * @return array
139
-     * @throws InvalidArgumentException
140
-     * @throws InvalidDataTypeException
141
-     * @throws InvalidInterfaceException
142
-     */
143
-    public function server_params()
144
-    {
145
-        return $this->request()->serverParams();
146
-    }
147
-
148
-
149
-
150
-    /**
151
-     * returns contents of $_REQUEST
152
-     *
153
-     * @deprecated 4.9.53
154
-     * @return array
155
-     * @throws InvalidArgumentException
156
-     * @throws InvalidDataTypeException
157
-     * @throws InvalidInterfaceException
158
-     */
159
-    public function params()
160
-    {
161
-        return $this->request()->requestParams();
162
-    }
163
-
164
-
165
-
166
-    /**
167
-     * @deprecated 4.9.53
168
-     * @param      $key
169
-     * @param      $value
170
-     * @param bool $override_ee
171
-     * @return void
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     */
176
-    public function set($key, $value, $override_ee = false)
177
-    {
178
-        $this->request()->setRequestParam($key, $value, $override_ee);
179
-    }
180
-
181
-
182
-
183
-    /**
184
-     * returns   the value for a request param if the given key exists
185
-     *
186
-     * @deprecated 4.9.53
187
-     * @param      $key
188
-     * @param null $default
189
-     * @return mixed
190
-     * @throws InvalidArgumentException
191
-     * @throws InvalidDataTypeException
192
-     * @throws InvalidInterfaceException
193
-     */
194
-    public function get($key, $default = null)
195
-    {
196
-        return $this->request()->getRequestParam($key, $default);
197
-    }
198
-
199
-
200
-
201
-    /**
202
-     * check if param exists
203
-     *
204
-     * @deprecated 4.9.53
205
-     * @param $key
206
-     * @return bool
207
-     * @throws InvalidArgumentException
208
-     * @throws InvalidDataTypeException
209
-     * @throws InvalidInterfaceException
210
-     */
211
-    public function is_set($key)
212
-    {
213
-        return $this->request()->requestParamIsSet($key);
214
-    }
215
-
216
-
217
-    /**
218
-     * remove param
219
-     *
220
-     * @deprecated 4.9.53
221
-     * @param      $key
222
-     * @param bool $unset_from_global_too
223
-     * @throws InvalidArgumentException
224
-     * @throws InvalidDataTypeException
225
-     * @throws InvalidInterfaceException
226
-     */
227
-    public function un_set($key, $unset_from_global_too = false)
228
-    {
229
-        $this->request()->unSetRequestParam($key, $unset_from_global_too);
230
-    }
231
-
232
-
233
-
234
-    /**
235
-     * @deprecated 4.9.53
236
-     * @return string
237
-     * @throws InvalidArgumentException
238
-     * @throws InvalidDataTypeException
239
-     * @throws InvalidInterfaceException
240
-     */
241
-    public function ip_address()
242
-    {
243
-        return $this->request()->ipAddress();
244
-    }
245
-
246
-
247
-    /**
248
-     * @deprecated 4.9.53
249
-     * @return bool
250
-     * @throws InvalidArgumentException
251
-     * @throws InvalidDataTypeException
252
-     * @throws InvalidInterfaceException
253
-     */
254
-    public function isAdmin()
255
-    {
256
-        return $this->request()->isAdmin();
257
-    }
258
-
259
-
260
-    /**
261
-     * @deprecated 4.9.53
262
-     * @return mixed
263
-     * @throws InvalidArgumentException
264
-     * @throws InvalidDataTypeException
265
-     * @throws InvalidInterfaceException
266
-     */
267
-    public function isAjax()
268
-    {
269
-        return $this->request()->isAjax();
270
-    }
271
-
272
-
273
-    /**
274
-     * @deprecated 4.9.53
275
-     * @return mixed
276
-     * @throws InvalidArgumentException
277
-     * @throws InvalidDataTypeException
278
-     * @throws InvalidInterfaceException
279
-     */
280
-    public function isFrontAjax()
281
-    {
282
-        return $this->request()->isFrontAjax();
283
-    }
284
-
285
-
286
-    /**
287
-     * @deprecated 4.9.53
288
-     * @return mixed|string
289
-     * @throws InvalidArgumentException
290
-     * @throws InvalidDataTypeException
291
-     * @throws InvalidInterfaceException
292
-     */
293
-    public function requestUri()
294
-    {
295
-        return $this->request()->requestUri();
296
-    }
297
-
298
-
299
-    /**
300
-     * @deprecated 4.9.53
301
-     * @return string
302
-     * @throws InvalidArgumentException
303
-     * @throws InvalidDataTypeException
304
-     * @throws InvalidInterfaceException
305
-     */
306
-    public function userAgent()
307
-    {
308
-        return $this->request()->userAgent();
309
-    }
310
-
311
-
312
-    /**
313
-     * @deprecated 4.9.53
314
-     * @param string $user_agent
315
-     * @throws InvalidArgumentException
316
-     * @throws InvalidDataTypeException
317
-     * @throws InvalidInterfaceException
318
-     */
319
-    public function setUserAgent($user_agent = '')
320
-    {
321
-        $this->request()->setUserAgent($user_agent);
322
-    }
323
-
324
-
325
-    /**
326
-     * @deprecated 4.9.53
327
-     * @return bool
328
-     * @throws InvalidArgumentException
329
-     * @throws InvalidDataTypeException
330
-     * @throws InvalidInterfaceException
331
-     */
332
-    public function isBot()
333
-    {
334
-        return $this->request()->isBot();
335
-    }
336
-
337
-
338
-    /**
339
-     * @deprecated 4.9.53
340
-     * @param bool $is_bot
341
-     * @throws InvalidArgumentException
342
-     * @throws InvalidDataTypeException
343
-     * @throws InvalidInterfaceException
344
-     */
345
-    public function setIsBot($is_bot)
346
-    {
347
-        $this->request()->setIsBot($is_bot);
348
-    }
349
-
350
-
351
-    /**
352
-     * check if a request parameter exists whose key that matches the supplied wildcard pattern
353
-     * and return the value for the first match found
354
-     * wildcards can be either of the following:
355
-     *      ? to represent a single character of any type
356
-     *      * to represent one or more characters of any type
357
-     *
358
-     * @param string     $pattern
359
-     * @param null|mixed $default
360
-     * @return false|int
361
-     * @throws InvalidArgumentException
362
-     * @throws InvalidInterfaceException
363
-     * @throws InvalidDataTypeException
364
-     */
365
-    public function getMatch($pattern, $default = null)
366
-    {
367
-        return $this->request()->getMatch($pattern, $default);
368
-    }
369
-
370
-
371
-    /**
372
-     * check if a request parameter exists whose key matches the supplied wildcard pattern
373
-     * wildcards can be either of the following:
374
-     *      ? to represent a single character of any type
375
-     *      * to represent one or more characters of any type
376
-     * returns true if a match is found or false if not
377
-     *
378
-     * @param string $pattern
379
-     * @return false|int
380
-     * @throws InvalidArgumentException
381
-     * @throws InvalidInterfaceException
382
-     * @throws InvalidDataTypeException
383
-     */
384
-    public function matches($pattern)
385
-    {
386
-        return $this->request()->matches($pattern);
387
-    }
25
+	/**
26
+	 * @var RequestInterface $request
27
+	 */
28
+	private $request;
29
+
30
+	/**
31
+	 * whether current request is for the admin but NOT via AJAX
32
+	 *
33
+	 * @var boolean $admin
34
+	 */
35
+	public $admin = false;
36
+
37
+	/**
38
+	 * whether current request is via AJAX
39
+	 *
40
+	 * @var boolean $ajax
41
+	 */
42
+	public $ajax = false;
43
+
44
+	/**
45
+	 * whether current request is via AJAX from the frontend of the site
46
+	 *
47
+	 * @var boolean $front_ajax
48
+	 */
49
+	public $front_ajax = false;
50
+
51
+
52
+	/**
53
+	 * @deprecated 4.9.53
54
+	 * @param array $get
55
+	 * @param array $post
56
+	 * @param array $cookie
57
+	 * @param array $server
58
+	 */
59
+	public function __construct(
60
+		array $get = array(),
61
+		array $post = array(),
62
+		array $cookie = array(),
63
+		array $server = array()
64
+	) {
65
+	}
66
+
67
+
68
+	/**
69
+	 * @return RequestInterface
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidInterfaceException
72
+	 * @throws InvalidDataTypeException
73
+	 */
74
+	private function request()
75
+	{
76
+		if($this->request instanceof RequestInterface){
77
+			return $this->request;
78
+		}
79
+		$loader = LoaderFactory::getLoader();
80
+		$this->request = $loader->getShared('EventEspresso\core\services\request\RequestInterface');
81
+		return $this->request;
82
+	}
83
+
84
+
85
+	/**
86
+	 * @param RequestInterface $request
87
+	 */
88
+	public function setRequest(RequestInterface $request)
89
+	{
90
+		$this->request = $request;
91
+	}
92
+
93
+
94
+
95
+	/**
96
+	 * @deprecated 4.9.53
97
+	 * @return array
98
+	 * @throws InvalidArgumentException
99
+	 * @throws InvalidDataTypeException
100
+	 * @throws InvalidInterfaceException
101
+	 */
102
+	public function get_params()
103
+	{
104
+		return $this->request()->getParams();
105
+	}
106
+
107
+
108
+
109
+	/**
110
+	 * @deprecated 4.9.53
111
+	 * @return array
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 */
116
+	public function post_params()
117
+	{
118
+		return $this->request()->postParams();
119
+	}
120
+
121
+
122
+
123
+	/**
124
+	 * @deprecated 4.9.53
125
+	 * @return array
126
+	 * @throws InvalidArgumentException
127
+	 * @throws InvalidDataTypeException
128
+	 * @throws InvalidInterfaceException
129
+	 */
130
+	public function cookie_params()
131
+	{
132
+		return $this->request()->cookieParams();
133
+	}
134
+
135
+
136
+	/**
137
+	 * @deprecated 4.9.53
138
+	 * @return array
139
+	 * @throws InvalidArgumentException
140
+	 * @throws InvalidDataTypeException
141
+	 * @throws InvalidInterfaceException
142
+	 */
143
+	public function server_params()
144
+	{
145
+		return $this->request()->serverParams();
146
+	}
147
+
148
+
149
+
150
+	/**
151
+	 * returns contents of $_REQUEST
152
+	 *
153
+	 * @deprecated 4.9.53
154
+	 * @return array
155
+	 * @throws InvalidArgumentException
156
+	 * @throws InvalidDataTypeException
157
+	 * @throws InvalidInterfaceException
158
+	 */
159
+	public function params()
160
+	{
161
+		return $this->request()->requestParams();
162
+	}
163
+
164
+
165
+
166
+	/**
167
+	 * @deprecated 4.9.53
168
+	 * @param      $key
169
+	 * @param      $value
170
+	 * @param bool $override_ee
171
+	 * @return void
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 */
176
+	public function set($key, $value, $override_ee = false)
177
+	{
178
+		$this->request()->setRequestParam($key, $value, $override_ee);
179
+	}
180
+
181
+
182
+
183
+	/**
184
+	 * returns   the value for a request param if the given key exists
185
+	 *
186
+	 * @deprecated 4.9.53
187
+	 * @param      $key
188
+	 * @param null $default
189
+	 * @return mixed
190
+	 * @throws InvalidArgumentException
191
+	 * @throws InvalidDataTypeException
192
+	 * @throws InvalidInterfaceException
193
+	 */
194
+	public function get($key, $default = null)
195
+	{
196
+		return $this->request()->getRequestParam($key, $default);
197
+	}
198
+
199
+
200
+
201
+	/**
202
+	 * check if param exists
203
+	 *
204
+	 * @deprecated 4.9.53
205
+	 * @param $key
206
+	 * @return bool
207
+	 * @throws InvalidArgumentException
208
+	 * @throws InvalidDataTypeException
209
+	 * @throws InvalidInterfaceException
210
+	 */
211
+	public function is_set($key)
212
+	{
213
+		return $this->request()->requestParamIsSet($key);
214
+	}
215
+
216
+
217
+	/**
218
+	 * remove param
219
+	 *
220
+	 * @deprecated 4.9.53
221
+	 * @param      $key
222
+	 * @param bool $unset_from_global_too
223
+	 * @throws InvalidArgumentException
224
+	 * @throws InvalidDataTypeException
225
+	 * @throws InvalidInterfaceException
226
+	 */
227
+	public function un_set($key, $unset_from_global_too = false)
228
+	{
229
+		$this->request()->unSetRequestParam($key, $unset_from_global_too);
230
+	}
231
+
232
+
233
+
234
+	/**
235
+	 * @deprecated 4.9.53
236
+	 * @return string
237
+	 * @throws InvalidArgumentException
238
+	 * @throws InvalidDataTypeException
239
+	 * @throws InvalidInterfaceException
240
+	 */
241
+	public function ip_address()
242
+	{
243
+		return $this->request()->ipAddress();
244
+	}
245
+
246
+
247
+	/**
248
+	 * @deprecated 4.9.53
249
+	 * @return bool
250
+	 * @throws InvalidArgumentException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws InvalidInterfaceException
253
+	 */
254
+	public function isAdmin()
255
+	{
256
+		return $this->request()->isAdmin();
257
+	}
258
+
259
+
260
+	/**
261
+	 * @deprecated 4.9.53
262
+	 * @return mixed
263
+	 * @throws InvalidArgumentException
264
+	 * @throws InvalidDataTypeException
265
+	 * @throws InvalidInterfaceException
266
+	 */
267
+	public function isAjax()
268
+	{
269
+		return $this->request()->isAjax();
270
+	}
271
+
272
+
273
+	/**
274
+	 * @deprecated 4.9.53
275
+	 * @return mixed
276
+	 * @throws InvalidArgumentException
277
+	 * @throws InvalidDataTypeException
278
+	 * @throws InvalidInterfaceException
279
+	 */
280
+	public function isFrontAjax()
281
+	{
282
+		return $this->request()->isFrontAjax();
283
+	}
284
+
285
+
286
+	/**
287
+	 * @deprecated 4.9.53
288
+	 * @return mixed|string
289
+	 * @throws InvalidArgumentException
290
+	 * @throws InvalidDataTypeException
291
+	 * @throws InvalidInterfaceException
292
+	 */
293
+	public function requestUri()
294
+	{
295
+		return $this->request()->requestUri();
296
+	}
297
+
298
+
299
+	/**
300
+	 * @deprecated 4.9.53
301
+	 * @return string
302
+	 * @throws InvalidArgumentException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws InvalidInterfaceException
305
+	 */
306
+	public function userAgent()
307
+	{
308
+		return $this->request()->userAgent();
309
+	}
310
+
311
+
312
+	/**
313
+	 * @deprecated 4.9.53
314
+	 * @param string $user_agent
315
+	 * @throws InvalidArgumentException
316
+	 * @throws InvalidDataTypeException
317
+	 * @throws InvalidInterfaceException
318
+	 */
319
+	public function setUserAgent($user_agent = '')
320
+	{
321
+		$this->request()->setUserAgent($user_agent);
322
+	}
323
+
324
+
325
+	/**
326
+	 * @deprecated 4.9.53
327
+	 * @return bool
328
+	 * @throws InvalidArgumentException
329
+	 * @throws InvalidDataTypeException
330
+	 * @throws InvalidInterfaceException
331
+	 */
332
+	public function isBot()
333
+	{
334
+		return $this->request()->isBot();
335
+	}
336
+
337
+
338
+	/**
339
+	 * @deprecated 4.9.53
340
+	 * @param bool $is_bot
341
+	 * @throws InvalidArgumentException
342
+	 * @throws InvalidDataTypeException
343
+	 * @throws InvalidInterfaceException
344
+	 */
345
+	public function setIsBot($is_bot)
346
+	{
347
+		$this->request()->setIsBot($is_bot);
348
+	}
349
+
350
+
351
+	/**
352
+	 * check if a request parameter exists whose key that matches the supplied wildcard pattern
353
+	 * and return the value for the first match found
354
+	 * wildcards can be either of the following:
355
+	 *      ? to represent a single character of any type
356
+	 *      * to represent one or more characters of any type
357
+	 *
358
+	 * @param string     $pattern
359
+	 * @param null|mixed $default
360
+	 * @return false|int
361
+	 * @throws InvalidArgumentException
362
+	 * @throws InvalidInterfaceException
363
+	 * @throws InvalidDataTypeException
364
+	 */
365
+	public function getMatch($pattern, $default = null)
366
+	{
367
+		return $this->request()->getMatch($pattern, $default);
368
+	}
369
+
370
+
371
+	/**
372
+	 * check if a request parameter exists whose key matches the supplied wildcard pattern
373
+	 * wildcards can be either of the following:
374
+	 *      ? to represent a single character of any type
375
+	 *      * to represent one or more characters of any type
376
+	 * returns true if a match is found or false if not
377
+	 *
378
+	 * @param string $pattern
379
+	 * @return false|int
380
+	 * @throws InvalidArgumentException
381
+	 * @throws InvalidInterfaceException
382
+	 * @throws InvalidDataTypeException
383
+	 */
384
+	public function matches($pattern)
385
+	{
386
+		return $this->request()->matches($pattern);
387
+	}
388 388
 
389 389
 
390 390
 }
Please login to merge, or discard this patch.