Completed
Branch BUG-10626-dst-unit-test (b2e779)
by
unknown
23:16 queued 12:00
created
core/helpers/EEH_Activation.helper.php 2 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
      *
614 614
      * @since  4.6.0
615 615
      * @global WPDB $wpdb
616
-     * @return mixed null|int WP_user ID or NULL
616
+     * @return integer|null null|int WP_user ID or NULL
617 617
      */
618 618
     public static function get_default_creator_id()
619 619
     {
@@ -774,7 +774,7 @@  discard block
 block discarded – undo
774 774
      * @static
775 775
      * @deprecated instead use TableManager::dropTable()
776 776
      * @param string $table_name
777
-     * @return bool | int
777
+     * @return integer | int
778 778
      */
779 779
     public static function delete_unused_db_table($table_name)
780 780
     {
@@ -791,7 +791,7 @@  discard block
 block discarded – undo
791 791
      * @deprecated instead use TableManager::dropIndex()
792 792
      * @param string $table_name
793 793
      * @param string $index_name
794
-     * @return bool | int
794
+     * @return integer | int
795 795
      */
796 796
     public static function drop_index($table_name, $index_name)
797 797
     {
Please login to merge, or discard this patch.
Indentation   +1652 added lines, -1652 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\interfaces\ResettableInterface;
3 3
 
4 4
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 
8 8
 
@@ -17,243 +17,243 @@  discard block
 block discarded – undo
17 17
 class EEH_Activation implements ResettableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * constant used to indicate a cron task is no longer in use
22
-     */
23
-    const cron_task_no_longer_in_use = 'no_longer_in_use';
24
-
25
-    /**
26
-     * option name that will indicate whether or not we still
27
-     * need to create EE's folders in the uploads directory
28
-     * (because if EE was installed without file system access,
29
-     * we need to request credentials before we can create them)
30
-     */
31
-    const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
32
-
33
-    /**
34
-     * WP_User->ID
35
-     *
36
-     * @var int
37
-     */
38
-    private static $_default_creator_id;
39
-
40
-    /**
41
-     * indicates whether or not we've already verified core's default data during this request,
42
-     * because after migrations are done, any addons activated while in maintenance mode
43
-     * will want to setup their own default data, and they might hook into core's default data
44
-     * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
45
-     * This prevents doing that for EVERY single addon.
46
-     *
47
-     * @var boolean
48
-     */
49
-    protected static $_initialized_db_content_already_in_this_request = false;
50
-
51
-    /**
52
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
53
-     */
54
-    private static $table_analysis;
55
-
56
-    /**
57
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
58
-     */
59
-    private static $table_manager;
60
-
61
-
62
-    /**
63
-     * @return \EventEspresso\core\services\database\TableAnalysis
64
-     */
65
-    public static function getTableAnalysis()
66
-    {
67
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
68
-            self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
69
-        }
70
-        return self::$table_analysis;
71
-    }
72
-
73
-
74
-    /**
75
-     * @return \EventEspresso\core\services\database\TableManager
76
-     */
77
-    public static function getTableManager()
78
-    {
79
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
80
-            self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
81
-        }
82
-        return self::$table_manager;
83
-    }
84
-
85
-
86
-    /**
87
-     *    _ensure_table_name_has_prefix
88
-     *
89
-     * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
90
-     * @access     public
91
-     * @static
92
-     * @param $table_name
93
-     * @return string
94
-     */
95
-    public static function ensure_table_name_has_prefix($table_name)
96
-    {
97
-        return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
98
-    }
99
-
100
-
101
-    /**
102
-     *    system_initialization
103
-     *    ensures the EE configuration settings are loaded with at least default options set
104
-     *    and that all critical EE pages have been generated with the appropriate shortcodes in place
105
-     *
106
-     * @access public
107
-     * @static
108
-     * @return void
109
-     */
110
-    public static function system_initialization()
111
-    {
112
-        EEH_Activation::reset_and_update_config();
113
-        //which is fired BEFORE activation of plugin anyways
114
-        EEH_Activation::verify_default_pages_exist();
115
-    }
116
-
117
-
118
-    /**
119
-     * Sets the database schema and creates folders. This should
120
-     * be called on plugin activation and reactivation
121
-     *
122
-     * @return boolean success, whether the database and folders are setup properly
123
-     * @throws \EE_Error
124
-     */
125
-    public static function initialize_db_and_folders()
126
-    {
127
-        $good_filesystem = EEH_Activation::create_upload_directories();
128
-        $good_db         = EEH_Activation::create_database_tables();
129
-        return $good_filesystem && $good_db;
130
-    }
131
-
132
-
133
-    /**
134
-     * assuming we have an up-to-date database schema, this will populate it
135
-     * with default and initial data. This should be called
136
-     * upon activation of a new plugin, reactivation, and at the end
137
-     * of running migration scripts
138
-     *
139
-     * @throws \EE_Error
140
-     */
141
-    public static function initialize_db_content()
142
-    {
143
-        //let's avoid doing all this logic repeatedly, especially when addons are requesting it
144
-        if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
145
-            return;
146
-        }
147
-        EEH_Activation::$_initialized_db_content_already_in_this_request = true;
148
-
149
-        EEH_Activation::initialize_system_questions();
150
-        EEH_Activation::insert_default_status_codes();
151
-        EEH_Activation::generate_default_message_templates();
152
-        EEH_Activation::create_no_ticket_prices_array();
153
-
154
-        EEH_Activation::validate_messages_system();
155
-        EEH_Activation::insert_default_payment_methods();
156
-        //in case we've
157
-        EEH_Activation::remove_cron_tasks();
158
-        EEH_Activation::create_cron_tasks();
159
-        // remove all TXN locks since that is being done via extra meta now
160
-        delete_option('ee_locked_transactions');
161
-        //also, check for CAF default db content
162
-        do_action('AHEE__EEH_Activation__initialize_db_content');
163
-        //also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
164
-        //which users really won't care about on initial activation
165
-        EE_Error::overwrite_success();
166
-    }
167
-
168
-
169
-    /**
170
-     * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
171
-     * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
172
-     * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
173
-     * (null)
174
-     *
175
-     * @param string $which_to_include can be 'current' (ones that are currently in use),
176
-     *                                 'old' (only returns ones that should no longer be used),or 'all',
177
-     * @return array
178
-     * @throws \EE_Error
179
-     */
180
-    public static function get_cron_tasks($which_to_include)
181
-    {
182
-        $cron_tasks = apply_filters(
183
-            'FHEE__EEH_Activation__get_cron_tasks',
184
-            array(
185
-                'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
20
+	/**
21
+	 * constant used to indicate a cron task is no longer in use
22
+	 */
23
+	const cron_task_no_longer_in_use = 'no_longer_in_use';
24
+
25
+	/**
26
+	 * option name that will indicate whether or not we still
27
+	 * need to create EE's folders in the uploads directory
28
+	 * (because if EE was installed without file system access,
29
+	 * we need to request credentials before we can create them)
30
+	 */
31
+	const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
32
+
33
+	/**
34
+	 * WP_User->ID
35
+	 *
36
+	 * @var int
37
+	 */
38
+	private static $_default_creator_id;
39
+
40
+	/**
41
+	 * indicates whether or not we've already verified core's default data during this request,
42
+	 * because after migrations are done, any addons activated while in maintenance mode
43
+	 * will want to setup their own default data, and they might hook into core's default data
44
+	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
45
+	 * This prevents doing that for EVERY single addon.
46
+	 *
47
+	 * @var boolean
48
+	 */
49
+	protected static $_initialized_db_content_already_in_this_request = false;
50
+
51
+	/**
52
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
53
+	 */
54
+	private static $table_analysis;
55
+
56
+	/**
57
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
58
+	 */
59
+	private static $table_manager;
60
+
61
+
62
+	/**
63
+	 * @return \EventEspresso\core\services\database\TableAnalysis
64
+	 */
65
+	public static function getTableAnalysis()
66
+	{
67
+		if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
68
+			self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
69
+		}
70
+		return self::$table_analysis;
71
+	}
72
+
73
+
74
+	/**
75
+	 * @return \EventEspresso\core\services\database\TableManager
76
+	 */
77
+	public static function getTableManager()
78
+	{
79
+		if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
80
+			self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
81
+		}
82
+		return self::$table_manager;
83
+	}
84
+
85
+
86
+	/**
87
+	 *    _ensure_table_name_has_prefix
88
+	 *
89
+	 * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
90
+	 * @access     public
91
+	 * @static
92
+	 * @param $table_name
93
+	 * @return string
94
+	 */
95
+	public static function ensure_table_name_has_prefix($table_name)
96
+	{
97
+		return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
98
+	}
99
+
100
+
101
+	/**
102
+	 *    system_initialization
103
+	 *    ensures the EE configuration settings are loaded with at least default options set
104
+	 *    and that all critical EE pages have been generated with the appropriate shortcodes in place
105
+	 *
106
+	 * @access public
107
+	 * @static
108
+	 * @return void
109
+	 */
110
+	public static function system_initialization()
111
+	{
112
+		EEH_Activation::reset_and_update_config();
113
+		//which is fired BEFORE activation of plugin anyways
114
+		EEH_Activation::verify_default_pages_exist();
115
+	}
116
+
117
+
118
+	/**
119
+	 * Sets the database schema and creates folders. This should
120
+	 * be called on plugin activation and reactivation
121
+	 *
122
+	 * @return boolean success, whether the database and folders are setup properly
123
+	 * @throws \EE_Error
124
+	 */
125
+	public static function initialize_db_and_folders()
126
+	{
127
+		$good_filesystem = EEH_Activation::create_upload_directories();
128
+		$good_db         = EEH_Activation::create_database_tables();
129
+		return $good_filesystem && $good_db;
130
+	}
131
+
132
+
133
+	/**
134
+	 * assuming we have an up-to-date database schema, this will populate it
135
+	 * with default and initial data. This should be called
136
+	 * upon activation of a new plugin, reactivation, and at the end
137
+	 * of running migration scripts
138
+	 *
139
+	 * @throws \EE_Error
140
+	 */
141
+	public static function initialize_db_content()
142
+	{
143
+		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
144
+		if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
145
+			return;
146
+		}
147
+		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
148
+
149
+		EEH_Activation::initialize_system_questions();
150
+		EEH_Activation::insert_default_status_codes();
151
+		EEH_Activation::generate_default_message_templates();
152
+		EEH_Activation::create_no_ticket_prices_array();
153
+
154
+		EEH_Activation::validate_messages_system();
155
+		EEH_Activation::insert_default_payment_methods();
156
+		//in case we've
157
+		EEH_Activation::remove_cron_tasks();
158
+		EEH_Activation::create_cron_tasks();
159
+		// remove all TXN locks since that is being done via extra meta now
160
+		delete_option('ee_locked_transactions');
161
+		//also, check for CAF default db content
162
+		do_action('AHEE__EEH_Activation__initialize_db_content');
163
+		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
164
+		//which users really won't care about on initial activation
165
+		EE_Error::overwrite_success();
166
+	}
167
+
168
+
169
+	/**
170
+	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
171
+	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
172
+	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
173
+	 * (null)
174
+	 *
175
+	 * @param string $which_to_include can be 'current' (ones that are currently in use),
176
+	 *                                 'old' (only returns ones that should no longer be used),or 'all',
177
+	 * @return array
178
+	 * @throws \EE_Error
179
+	 */
180
+	public static function get_cron_tasks($which_to_include)
181
+	{
182
+		$cron_tasks = apply_filters(
183
+			'FHEE__EEH_Activation__get_cron_tasks',
184
+			array(
185
+				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
186 186
 //				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
187
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
188
-                //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
189
-                'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
190
-            )
191
-        );
192
-        if ($which_to_include === 'old') {
193
-            $cron_tasks = array_filter(
194
-                $cron_tasks,
195
-                function ($value) {
196
-                    return $value === EEH_Activation::cron_task_no_longer_in_use;
197
-                }
198
-            );
199
-        } elseif ($which_to_include === 'current') {
200
-            $cron_tasks = array_filter($cron_tasks);
201
-        } elseif (WP_DEBUG && $which_to_include !== 'all') {
202
-            throw new EE_Error(
203
-                sprintf(
204
-                    __(
205
-                        'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
206
-                        'event_espresso'
207
-                    ),
208
-                    $which_to_include
209
-                )
210
-            );
211
-        }
212
-        return $cron_tasks;
213
-    }
214
-
215
-
216
-    /**
217
-     * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
218
-     *
219
-     * @throws \EE_Error
220
-     */
221
-    public static function create_cron_tasks()
222
-    {
223
-
224
-        foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
225
-            if (! wp_next_scheduled($hook_name)) {
226
-                /**
227
-                 * This allows client code to define the initial start timestamp for this schedule.
228
-                 */
229
-                if (is_array($frequency)
230
-                    && count($frequency) === 2
231
-                    && isset($frequency[0], $frequency[1])
232
-                ) {
233
-                    $start_timestamp = $frequency[0];
234
-                    $frequency = $frequency[1];
235
-                } else {
236
-                    $start_timestamp = time();
237
-                }
238
-                wp_schedule_event($start_timestamp, $frequency, $hook_name);
239
-            }
240
-        }
241
-
242
-    }
243
-
244
-
245
-    /**
246
-     * Remove the currently-existing and now-removed cron tasks.
247
-     *
248
-     * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
249
-     * @throws \EE_Error
250
-     */
251
-    public static function remove_cron_tasks($remove_all = true)
252
-    {
253
-        $cron_tasks_to_remove = $remove_all ? 'all' : 'old';
254
-        $crons                = _get_cron_array();
255
-        $crons                = is_array($crons) ? $crons : array();
256
-        /* reminder of what $crons look like:
187
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
188
+				//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
189
+				'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
190
+			)
191
+		);
192
+		if ($which_to_include === 'old') {
193
+			$cron_tasks = array_filter(
194
+				$cron_tasks,
195
+				function ($value) {
196
+					return $value === EEH_Activation::cron_task_no_longer_in_use;
197
+				}
198
+			);
199
+		} elseif ($which_to_include === 'current') {
200
+			$cron_tasks = array_filter($cron_tasks);
201
+		} elseif (WP_DEBUG && $which_to_include !== 'all') {
202
+			throw new EE_Error(
203
+				sprintf(
204
+					__(
205
+						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
206
+						'event_espresso'
207
+					),
208
+					$which_to_include
209
+				)
210
+			);
211
+		}
212
+		return $cron_tasks;
213
+	}
214
+
215
+
216
+	/**
217
+	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
218
+	 *
219
+	 * @throws \EE_Error
220
+	 */
221
+	public static function create_cron_tasks()
222
+	{
223
+
224
+		foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
225
+			if (! wp_next_scheduled($hook_name)) {
226
+				/**
227
+				 * This allows client code to define the initial start timestamp for this schedule.
228
+				 */
229
+				if (is_array($frequency)
230
+					&& count($frequency) === 2
231
+					&& isset($frequency[0], $frequency[1])
232
+				) {
233
+					$start_timestamp = $frequency[0];
234
+					$frequency = $frequency[1];
235
+				} else {
236
+					$start_timestamp = time();
237
+				}
238
+				wp_schedule_event($start_timestamp, $frequency, $hook_name);
239
+			}
240
+		}
241
+
242
+	}
243
+
244
+
245
+	/**
246
+	 * Remove the currently-existing and now-removed cron tasks.
247
+	 *
248
+	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
249
+	 * @throws \EE_Error
250
+	 */
251
+	public static function remove_cron_tasks($remove_all = true)
252
+	{
253
+		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
254
+		$crons                = _get_cron_array();
255
+		$crons                = is_array($crons) ? $crons : array();
256
+		/* reminder of what $crons look like:
257 257
          * Top-level keys are timestamps, and their values are arrays.
258 258
          * The 2nd level arrays have keys with each of the cron task hook names to run at that time
259 259
          * and their values are arrays.
@@ -270,912 +270,912 @@  discard block
 block discarded – undo
270 270
          *					...
271 271
          *      ...
272 272
          */
273
-        $ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
274
-        foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
275
-            if (is_array($hooks_to_fire_at_time)) {
276
-                foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
277
-                    if (isset($ee_cron_tasks_to_remove[$hook_name])
278
-                        && is_array($ee_cron_tasks_to_remove[$hook_name])
279
-                    ) {
280
-                        unset($crons[$timestamp][$hook_name]);
281
-                    }
282
-                }
283
-                //also take care of any empty cron timestamps.
284
-                if (empty($hooks_to_fire_at_time)) {
285
-                    unset($crons[$timestamp]);
286
-                }
287
-            }
288
-        }
289
-        _set_cron_array($crons);
290
-    }
291
-
292
-
293
-    /**
294
-     *    CPT_initialization
295
-     *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
296
-     *
297
-     * @access public
298
-     * @static
299
-     * @return void
300
-     */
301
-    public static function CPT_initialization()
302
-    {
303
-        // register Custom Post Types
304
-        EE_Registry::instance()->load_core('Register_CPTs');
305
-        flush_rewrite_rules();
306
-    }
307
-
308
-
309
-
310
-    /**
311
-     *    reset_and_update_config
312
-     * The following code was moved over from EE_Config so that it will no longer run on every request.
313
-     * If there is old calendar config data saved, then it will get converted on activation.
314
-     * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
315
-     *
316
-     * @access public
317
-     * @static
318
-     * @return void
319
-     */
320
-    public static function reset_and_update_config()
321
-    {
322
-        do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
323
-        add_filter(
324
-            'FHEE__EE_Config___load_core_config__config_settings',
325
-            array('EEH_Activation', 'migrate_old_config_data'),
326
-            10,
327
-            3
328
-        );
329
-        //EE_Config::reset();
330
-        if (! EE_Config::logging_enabled()) {
331
-            delete_option(EE_Config::LOG_NAME);
332
-        }
333
-    }
334
-
335
-
336
-    /**
337
-     *    load_calendar_config
338
-     *
339
-     * @access    public
340
-     * @return    void
341
-     */
342
-    public static function load_calendar_config()
343
-    {
344
-        // grab array of all plugin folders and loop thru it
345
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
346
-        if (empty($plugins)) {
347
-            return;
348
-        }
349
-        foreach ($plugins as $plugin_path) {
350
-            // grab plugin folder name from path
351
-            $plugin = basename($plugin_path);
352
-            // drill down to Espresso plugins
353
-            // then to calendar related plugins
354
-            if (
355
-                strpos($plugin, 'espresso') !== false
356
-                || strpos($plugin, 'Espresso') !== false
357
-                || strpos($plugin, 'ee4') !== false
358
-                || strpos($plugin, 'EE4') !== false
359
-                || strpos($plugin, 'calendar') !== false
360
-            ) {
361
-                // this is what we are looking for
362
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
363
-                // does it exist in this folder ?
364
-                if (is_readable($calendar_config)) {
365
-                    // YEAH! let's load it
366
-                    require_once($calendar_config);
367
-                }
368
-            }
369
-        }
370
-    }
371
-
372
-
373
-
374
-    /**
375
-     *    _migrate_old_config_data
376
-     *
377
-     * @access    public
378
-     * @param array|stdClass $settings
379
-     * @param string         $config
380
-     * @param \EE_Config     $EE_Config
381
-     * @return \stdClass
382
-     */
383
-    public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
384
-    {
385
-        $convert_from_array = array('addons');
386
-        // in case old settings were saved as an array
387
-        if (is_array($settings) && in_array($config, $convert_from_array)) {
388
-            // convert existing settings to an object
389
-            $config_array = $settings;
390
-            $settings = new stdClass();
391
-            foreach ($config_array as $key => $value) {
392
-                if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
393
-                    $EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
394
-                } else {
395
-                    $settings->{$key} = $value;
396
-                }
397
-            }
398
-            add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
399
-        }
400
-        return $settings;
401
-    }
402
-
403
-
404
-    /**
405
-     * deactivate_event_espresso
406
-     *
407
-     * @access public
408
-     * @static
409
-     * @return void
410
-     */
411
-    public static function deactivate_event_espresso()
412
-    {
413
-        // check permissions
414
-        if (current_user_can('activate_plugins')) {
415
-            deactivate_plugins(EE_PLUGIN_BASENAME, true);
416
-        }
417
-    }
418
-
419
-
420
-
421
-
422
-
423
-    /**
424
-     * verify_default_pages_exist
425
-     *
426
-     * @access public
427
-     * @static
428
-     * @return void
429
-     */
430
-    public static function verify_default_pages_exist()
431
-    {
432
-        $critical_page_problem = false;
433
-        $critical_pages = array(
434
-            array(
435
-                'id'   => 'reg_page_id',
436
-                'name' => __('Registration Checkout', 'event_espresso'),
437
-                'post' => null,
438
-                'code' => 'ESPRESSO_CHECKOUT',
439
-            ),
440
-            array(
441
-                'id'   => 'txn_page_id',
442
-                'name' => __('Transactions', 'event_espresso'),
443
-                'post' => null,
444
-                'code' => 'ESPRESSO_TXN_PAGE',
445
-            ),
446
-            array(
447
-                'id'   => 'thank_you_page_id',
448
-                'name' => __('Thank You', 'event_espresso'),
449
-                'post' => null,
450
-                'code' => 'ESPRESSO_THANK_YOU',
451
-            ),
452
-            array(
453
-                'id'   => 'cancel_page_id',
454
-                'name' => __('Registration Cancelled', 'event_espresso'),
455
-                'post' => null,
456
-                'code' => 'ESPRESSO_CANCELLED',
457
-            ),
458
-        );
459
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
460
-        foreach ($critical_pages as $critical_page) {
461
-            // is critical page ID set in config ?
462
-            if ($EE_Core_Config->{$critical_page['id']} !== false) {
463
-                // attempt to find post by ID
464
-                $critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
465
-            }
466
-            // no dice?
467
-            if ($critical_page['post'] === null) {
468
-                // attempt to find post by title
469
-                $critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
470
-                // still nothing?
471
-                if ($critical_page['post'] === null) {
472
-                    $critical_page = EEH_Activation::create_critical_page($critical_page);
473
-                    // REALLY? Still nothing ??!?!?
474
-                    if ($critical_page['post'] === null) {
475
-                        $msg = __(
476
-                            'The Event Espresso critical page configuration settings could not be updated.',
477
-                            'event_espresso'
478
-                        );
479
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
480
-                        break;
481
-                    }
482
-                }
483
-            }
484
-            // check that Post ID matches critical page ID in config
485
-            if (
486
-                isset($critical_page['post']->ID)
487
-                && $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
488
-            ) {
489
-                //update Config with post ID
490
-                $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
491
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
492
-                    $msg = __(
493
-                        'The Event Espresso critical page configuration settings could not be updated.',
494
-                        'event_espresso'
495
-                    );
496
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
497
-                }
498
-            }
499
-            $critical_page_problem =
500
-                ! isset($critical_page['post']->post_status)
501
-                || $critical_page['post']->post_status !== 'publish'
502
-                || strpos($critical_page['post']->post_content, $critical_page['code']) === false
503
-                    ? true
504
-                    : $critical_page_problem;
505
-        }
506
-        if ($critical_page_problem) {
507
-            $msg = sprintf(
508
-                __(
509
-                    'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
510
-                    'event_espresso'
511
-                ),
512
-                '<a href="'
513
-                . admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
514
-                . '">'
515
-                . __('Event Espresso Critical Pages Settings', 'event_espresso')
516
-                . '</a>'
517
-            );
518
-            EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
519
-        }
520
-        if (EE_Error::has_notices()) {
521
-            EE_Error::get_notices(false, true, true);
522
-        }
523
-    }
524
-
525
-
526
-
527
-    /**
528
-     * Returns the first post which uses the specified shortcode
529
-     *
530
-     * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
531
-     *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
532
-     *                             "[ESPRESSO_THANK_YOU"
533
-     *                             (we don't search for the closing shortcode bracket because they might have added
534
-     *                             parameter to the shortcode
535
-     * @return WP_Post or NULl
536
-     */
537
-    public static function get_page_by_ee_shortcode($ee_shortcode)
538
-    {
539
-        global $wpdb;
540
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
541
-        $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
542
-        if ($post_id) {
543
-            return get_post($post_id);
544
-        } else {
545
-            return null;
546
-        }
547
-    }
548
-
549
-
550
-    /**
551
-     *    This function generates a post for critical espresso pages
552
-     *
553
-     * @access public
554
-     * @static
555
-     * @param array $critical_page
556
-     * @return array
557
-     */
558
-    public static function create_critical_page($critical_page)
559
-    {
560
-
561
-        $post_args = array(
562
-            'post_title'     => $critical_page['name'],
563
-            'post_status'    => 'publish',
564
-            'post_type'      => 'page',
565
-            'comment_status' => 'closed',
566
-            'post_content'   => '[' . $critical_page['code'] . ']',
567
-        );
568
-
569
-        $post_id = wp_insert_post($post_args);
570
-        if (! $post_id) {
571
-            $msg = sprintf(
572
-                __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
573
-                $critical_page['name']
574
-            );
575
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
576
-            return $critical_page;
577
-        }
578
-        // get newly created post's details
579
-        if (! $critical_page['post'] = get_post($post_id)) {
580
-            $msg = sprintf(
581
-                __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
582
-                $critical_page['name']
583
-            );
584
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
585
-        }
586
-
587
-        return $critical_page;
588
-
589
-    }
590
-
591
-
592
-
593
-
594
-    /**
595
-     * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
596
-     * The role being used to check is filterable.
597
-     *
598
-     * @since  4.6.0
599
-     * @global WPDB $wpdb
600
-     * @return mixed null|int WP_user ID or NULL
601
-     */
602
-    public static function get_default_creator_id()
603
-    {
604
-        global $wpdb;
605
-        if ( ! empty(self::$_default_creator_id)) {
606
-            return self::$_default_creator_id;
607
-        }/**/
608
-        $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
609
-        //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.
610
-        $pre_filtered_id = apply_filters(
611
-            'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
612
-            false,
613
-            $role_to_check
614
-        );
615
-        if ($pre_filtered_id !== false) {
616
-            return (int)$pre_filtered_id;
617
-        }
618
-        $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
619
-        $query = $wpdb->prepare(
620
-            "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
621
-            '%' . $role_to_check . '%'
622
-        );
623
-        $user_id = $wpdb->get_var($query);
624
-        $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
625
-        if ($user_id && (int)$user_id) {
626
-            self::$_default_creator_id = (int)$user_id;
627
-            return self::$_default_creator_id;
628
-        } else {
629
-            return null;
630
-        }
631
-    }
632
-
633
-
634
-
635
-    /**
636
-     * used by EE and EE addons during plugin activation to create tables.
637
-     * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
638
-     * but includes extra logic regarding activations.
639
-     *
640
-     * @access public
641
-     * @static
642
-     * @param string  $table_name              without the $wpdb->prefix
643
-     * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
644
-     *                                         table query)
645
-     * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
646
-     * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
647
-     *                                         and new once this function is done (ie, you really do want to CREATE a
648
-     *                                         table, and expect it to be empty once you're done) leave as FALSE when
649
-     *                                         you just want to verify the table exists and matches this definition
650
-     *                                         (and if it HAS data in it you want to leave it be)
651
-     * @return void
652
-     * @throws EE_Error if there are database errors
653
-     */
654
-    public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
655
-    {
656
-        if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
657
-            return;
658
-        }
659
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
660
-        if ( ! function_exists('dbDelta')) {
661
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
662
-        }
663
-        $tableAnalysis = \EEH_Activation::getTableAnalysis();
664
-        $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
665
-        // do we need to first delete an existing version of this table ?
666
-        if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
667
-            // ok, delete the table... but ONLY if it's empty
668
-            $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
669
-            // table is NOT empty, are you SURE you want to delete this table ???
670
-            if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
671
-                \EEH_Activation::getTableManager()->dropTable($wp_table_name);
672
-            } else if ( ! $deleted_safely) {
673
-                // so we should be more cautious rather than just dropping tables so easily
674
-                error_log(
675
-                    sprintf(
676
-                        __(
677
-                            '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.',
678
-                            'event_espresso'
679
-                        ),
680
-                        $wp_table_name,
681
-                        '<br/>',
682
-                        'espresso_db_update'
683
-                    )
684
-                );
685
-            }
686
-        }
687
-        $engine = str_replace('ENGINE=', '', $engine);
688
-        \EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
689
-    }
690
-
691
-
692
-
693
-    /**
694
-     *    add_column_if_it_doesn't_exist
695
-     *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
696
-     *
697
-     * @access     public
698
-     * @static
699
-     * @deprecated instead use TableManager::addColumn()
700
-     * @param string $table_name  (without "wp_", eg "esp_attendee"
701
-     * @param string $column_name
702
-     * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
703
-     *                            'VARCHAR(10)'
704
-     * @return bool|int
705
-     */
706
-    public static function add_column_if_it_doesnt_exist(
707
-        $table_name,
708
-        $column_name,
709
-        $column_info = 'INT UNSIGNED NOT NULL'
710
-    ) {
711
-        return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
712
-    }
713
-
714
-
715
-    /**
716
-     * get_fields_on_table
717
-     * Gets all the fields on the database table.
718
-     *
719
-     * @access     public
720
-     * @deprecated instead use TableManager::getTableColumns()
721
-     * @static
722
-     * @param string $table_name , without prefixed $wpdb->prefix
723
-     * @return array of database column names
724
-     */
725
-    public static function get_fields_on_table($table_name = null)
726
-    {
727
-        return \EEH_Activation::getTableManager()->getTableColumns($table_name);
728
-    }
729
-
730
-
731
-    /**
732
-     * db_table_is_empty
733
-     *
734
-     * @access     public\
735
-     * @deprecated instead use TableAnalysis::tableIsEmpty()
736
-     * @static
737
-     * @param string $table_name
738
-     * @return bool
739
-     */
740
-    public static function db_table_is_empty($table_name)
741
-    {
742
-        return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
743
-    }
744
-
745
-
746
-    /**
747
-     * delete_db_table_if_empty
748
-     *
749
-     * @access public
750
-     * @static
751
-     * @param string $table_name
752
-     * @return bool | int
753
-     */
754
-    public static function delete_db_table_if_empty($table_name)
755
-    {
756
-        if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
757
-            return \EEH_Activation::getTableManager()->dropTable($table_name);
758
-        }
759
-        return false;
760
-    }
761
-
762
-
763
-    /**
764
-     * delete_unused_db_table
765
-     *
766
-     * @access     public
767
-     * @static
768
-     * @deprecated instead use TableManager::dropTable()
769
-     * @param string $table_name
770
-     * @return bool | int
771
-     */
772
-    public static function delete_unused_db_table($table_name)
773
-    {
774
-        return \EEH_Activation::getTableManager()->dropTable($table_name);
775
-    }
776
-
777
-
778
-    /**
779
-     * drop_index
780
-     *
781
-     * @access     public
782
-     * @static
783
-     * @deprecated instead use TableManager::dropIndex()
784
-     * @param string $table_name
785
-     * @param string $index_name
786
-     * @return bool | int
787
-     */
788
-    public static function drop_index($table_name, $index_name)
789
-    {
790
-        return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
791
-    }
792
-
793
-
794
-
795
-    /**
796
-     * create_database_tables
797
-     *
798
-     * @access public
799
-     * @static
800
-     * @throws EE_Error
801
-     * @return boolean success (whether database is setup properly or not)
802
-     */
803
-    public static function create_database_tables()
804
-    {
805
-        EE_Registry::instance()->load_core('Data_Migration_Manager');
806
-        //find the migration script that sets the database to be compatible with the code
807
-        $dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
808
-        if ($dms_name) {
809
-            $current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
810
-            $current_data_migration_script->set_migrating(false);
811
-            $current_data_migration_script->schema_changes_before_migration();
812
-            $current_data_migration_script->schema_changes_after_migration();
813
-            if ($current_data_migration_script->get_errors()) {
814
-                if (WP_DEBUG) {
815
-                    foreach ($current_data_migration_script->get_errors() as $error) {
816
-                        EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
817
-                    }
818
-                } else {
819
-                    EE_Error::add_error(
820
-                        __(
821
-                            'There were errors creating the Event Espresso database tables and Event Espresso has been 
273
+		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
274
+		foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
275
+			if (is_array($hooks_to_fire_at_time)) {
276
+				foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
277
+					if (isset($ee_cron_tasks_to_remove[$hook_name])
278
+						&& is_array($ee_cron_tasks_to_remove[$hook_name])
279
+					) {
280
+						unset($crons[$timestamp][$hook_name]);
281
+					}
282
+				}
283
+				//also take care of any empty cron timestamps.
284
+				if (empty($hooks_to_fire_at_time)) {
285
+					unset($crons[$timestamp]);
286
+				}
287
+			}
288
+		}
289
+		_set_cron_array($crons);
290
+	}
291
+
292
+
293
+	/**
294
+	 *    CPT_initialization
295
+	 *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
296
+	 *
297
+	 * @access public
298
+	 * @static
299
+	 * @return void
300
+	 */
301
+	public static function CPT_initialization()
302
+	{
303
+		// register Custom Post Types
304
+		EE_Registry::instance()->load_core('Register_CPTs');
305
+		flush_rewrite_rules();
306
+	}
307
+
308
+
309
+
310
+	/**
311
+	 *    reset_and_update_config
312
+	 * The following code was moved over from EE_Config so that it will no longer run on every request.
313
+	 * If there is old calendar config data saved, then it will get converted on activation.
314
+	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
315
+	 *
316
+	 * @access public
317
+	 * @static
318
+	 * @return void
319
+	 */
320
+	public static function reset_and_update_config()
321
+	{
322
+		do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
323
+		add_filter(
324
+			'FHEE__EE_Config___load_core_config__config_settings',
325
+			array('EEH_Activation', 'migrate_old_config_data'),
326
+			10,
327
+			3
328
+		);
329
+		//EE_Config::reset();
330
+		if (! EE_Config::logging_enabled()) {
331
+			delete_option(EE_Config::LOG_NAME);
332
+		}
333
+	}
334
+
335
+
336
+	/**
337
+	 *    load_calendar_config
338
+	 *
339
+	 * @access    public
340
+	 * @return    void
341
+	 */
342
+	public static function load_calendar_config()
343
+	{
344
+		// grab array of all plugin folders and loop thru it
345
+		$plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
346
+		if (empty($plugins)) {
347
+			return;
348
+		}
349
+		foreach ($plugins as $plugin_path) {
350
+			// grab plugin folder name from path
351
+			$plugin = basename($plugin_path);
352
+			// drill down to Espresso plugins
353
+			// then to calendar related plugins
354
+			if (
355
+				strpos($plugin, 'espresso') !== false
356
+				|| strpos($plugin, 'Espresso') !== false
357
+				|| strpos($plugin, 'ee4') !== false
358
+				|| strpos($plugin, 'EE4') !== false
359
+				|| strpos($plugin, 'calendar') !== false
360
+			) {
361
+				// this is what we are looking for
362
+				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
363
+				// does it exist in this folder ?
364
+				if (is_readable($calendar_config)) {
365
+					// YEAH! let's load it
366
+					require_once($calendar_config);
367
+				}
368
+			}
369
+		}
370
+	}
371
+
372
+
373
+
374
+	/**
375
+	 *    _migrate_old_config_data
376
+	 *
377
+	 * @access    public
378
+	 * @param array|stdClass $settings
379
+	 * @param string         $config
380
+	 * @param \EE_Config     $EE_Config
381
+	 * @return \stdClass
382
+	 */
383
+	public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
384
+	{
385
+		$convert_from_array = array('addons');
386
+		// in case old settings were saved as an array
387
+		if (is_array($settings) && in_array($config, $convert_from_array)) {
388
+			// convert existing settings to an object
389
+			$config_array = $settings;
390
+			$settings = new stdClass();
391
+			foreach ($config_array as $key => $value) {
392
+				if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
393
+					$EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
394
+				} else {
395
+					$settings->{$key} = $value;
396
+				}
397
+			}
398
+			add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
399
+		}
400
+		return $settings;
401
+	}
402
+
403
+
404
+	/**
405
+	 * deactivate_event_espresso
406
+	 *
407
+	 * @access public
408
+	 * @static
409
+	 * @return void
410
+	 */
411
+	public static function deactivate_event_espresso()
412
+	{
413
+		// check permissions
414
+		if (current_user_can('activate_plugins')) {
415
+			deactivate_plugins(EE_PLUGIN_BASENAME, true);
416
+		}
417
+	}
418
+
419
+
420
+
421
+
422
+
423
+	/**
424
+	 * verify_default_pages_exist
425
+	 *
426
+	 * @access public
427
+	 * @static
428
+	 * @return void
429
+	 */
430
+	public static function verify_default_pages_exist()
431
+	{
432
+		$critical_page_problem = false;
433
+		$critical_pages = array(
434
+			array(
435
+				'id'   => 'reg_page_id',
436
+				'name' => __('Registration Checkout', 'event_espresso'),
437
+				'post' => null,
438
+				'code' => 'ESPRESSO_CHECKOUT',
439
+			),
440
+			array(
441
+				'id'   => 'txn_page_id',
442
+				'name' => __('Transactions', 'event_espresso'),
443
+				'post' => null,
444
+				'code' => 'ESPRESSO_TXN_PAGE',
445
+			),
446
+			array(
447
+				'id'   => 'thank_you_page_id',
448
+				'name' => __('Thank You', 'event_espresso'),
449
+				'post' => null,
450
+				'code' => 'ESPRESSO_THANK_YOU',
451
+			),
452
+			array(
453
+				'id'   => 'cancel_page_id',
454
+				'name' => __('Registration Cancelled', 'event_espresso'),
455
+				'post' => null,
456
+				'code' => 'ESPRESSO_CANCELLED',
457
+			),
458
+		);
459
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
460
+		foreach ($critical_pages as $critical_page) {
461
+			// is critical page ID set in config ?
462
+			if ($EE_Core_Config->{$critical_page['id']} !== false) {
463
+				// attempt to find post by ID
464
+				$critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
465
+			}
466
+			// no dice?
467
+			if ($critical_page['post'] === null) {
468
+				// attempt to find post by title
469
+				$critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
470
+				// still nothing?
471
+				if ($critical_page['post'] === null) {
472
+					$critical_page = EEH_Activation::create_critical_page($critical_page);
473
+					// REALLY? Still nothing ??!?!?
474
+					if ($critical_page['post'] === null) {
475
+						$msg = __(
476
+							'The Event Espresso critical page configuration settings could not be updated.',
477
+							'event_espresso'
478
+						);
479
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
480
+						break;
481
+					}
482
+				}
483
+			}
484
+			// check that Post ID matches critical page ID in config
485
+			if (
486
+				isset($critical_page['post']->ID)
487
+				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
488
+			) {
489
+				//update Config with post ID
490
+				$EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
491
+				if (! EE_Config::instance()->update_espresso_config(false, false)) {
492
+					$msg = __(
493
+						'The Event Espresso critical page configuration settings could not be updated.',
494
+						'event_espresso'
495
+					);
496
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
497
+				}
498
+			}
499
+			$critical_page_problem =
500
+				! isset($critical_page['post']->post_status)
501
+				|| $critical_page['post']->post_status !== 'publish'
502
+				|| strpos($critical_page['post']->post_content, $critical_page['code']) === false
503
+					? true
504
+					: $critical_page_problem;
505
+		}
506
+		if ($critical_page_problem) {
507
+			$msg = sprintf(
508
+				__(
509
+					'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
510
+					'event_espresso'
511
+				),
512
+				'<a href="'
513
+				. admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
514
+				. '">'
515
+				. __('Event Espresso Critical Pages Settings', 'event_espresso')
516
+				. '</a>'
517
+			);
518
+			EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
519
+		}
520
+		if (EE_Error::has_notices()) {
521
+			EE_Error::get_notices(false, true, true);
522
+		}
523
+	}
524
+
525
+
526
+
527
+	/**
528
+	 * Returns the first post which uses the specified shortcode
529
+	 *
530
+	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
531
+	 *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
532
+	 *                             "[ESPRESSO_THANK_YOU"
533
+	 *                             (we don't search for the closing shortcode bracket because they might have added
534
+	 *                             parameter to the shortcode
535
+	 * @return WP_Post or NULl
536
+	 */
537
+	public static function get_page_by_ee_shortcode($ee_shortcode)
538
+	{
539
+		global $wpdb;
540
+		$shortcode_and_opening_bracket = '[' . $ee_shortcode;
541
+		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
542
+		if ($post_id) {
543
+			return get_post($post_id);
544
+		} else {
545
+			return null;
546
+		}
547
+	}
548
+
549
+
550
+	/**
551
+	 *    This function generates a post for critical espresso pages
552
+	 *
553
+	 * @access public
554
+	 * @static
555
+	 * @param array $critical_page
556
+	 * @return array
557
+	 */
558
+	public static function create_critical_page($critical_page)
559
+	{
560
+
561
+		$post_args = array(
562
+			'post_title'     => $critical_page['name'],
563
+			'post_status'    => 'publish',
564
+			'post_type'      => 'page',
565
+			'comment_status' => 'closed',
566
+			'post_content'   => '[' . $critical_page['code'] . ']',
567
+		);
568
+
569
+		$post_id = wp_insert_post($post_args);
570
+		if (! $post_id) {
571
+			$msg = sprintf(
572
+				__('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
573
+				$critical_page['name']
574
+			);
575
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
576
+			return $critical_page;
577
+		}
578
+		// get newly created post's details
579
+		if (! $critical_page['post'] = get_post($post_id)) {
580
+			$msg = sprintf(
581
+				__('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
582
+				$critical_page['name']
583
+			);
584
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
585
+		}
586
+
587
+		return $critical_page;
588
+
589
+	}
590
+
591
+
592
+
593
+
594
+	/**
595
+	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
596
+	 * The role being used to check is filterable.
597
+	 *
598
+	 * @since  4.6.0
599
+	 * @global WPDB $wpdb
600
+	 * @return mixed null|int WP_user ID or NULL
601
+	 */
602
+	public static function get_default_creator_id()
603
+	{
604
+		global $wpdb;
605
+		if ( ! empty(self::$_default_creator_id)) {
606
+			return self::$_default_creator_id;
607
+		}/**/
608
+		$role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
609
+		//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.
610
+		$pre_filtered_id = apply_filters(
611
+			'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
612
+			false,
613
+			$role_to_check
614
+		);
615
+		if ($pre_filtered_id !== false) {
616
+			return (int)$pre_filtered_id;
617
+		}
618
+		$capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
619
+		$query = $wpdb->prepare(
620
+			"SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
621
+			'%' . $role_to_check . '%'
622
+		);
623
+		$user_id = $wpdb->get_var($query);
624
+		$user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
625
+		if ($user_id && (int)$user_id) {
626
+			self::$_default_creator_id = (int)$user_id;
627
+			return self::$_default_creator_id;
628
+		} else {
629
+			return null;
630
+		}
631
+	}
632
+
633
+
634
+
635
+	/**
636
+	 * used by EE and EE addons during plugin activation to create tables.
637
+	 * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
638
+	 * but includes extra logic regarding activations.
639
+	 *
640
+	 * @access public
641
+	 * @static
642
+	 * @param string  $table_name              without the $wpdb->prefix
643
+	 * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
644
+	 *                                         table query)
645
+	 * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
646
+	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
647
+	 *                                         and new once this function is done (ie, you really do want to CREATE a
648
+	 *                                         table, and expect it to be empty once you're done) leave as FALSE when
649
+	 *                                         you just want to verify the table exists and matches this definition
650
+	 *                                         (and if it HAS data in it you want to leave it be)
651
+	 * @return void
652
+	 * @throws EE_Error if there are database errors
653
+	 */
654
+	public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
655
+	{
656
+		if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
657
+			return;
658
+		}
659
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
660
+		if ( ! function_exists('dbDelta')) {
661
+			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
662
+		}
663
+		$tableAnalysis = \EEH_Activation::getTableAnalysis();
664
+		$wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
665
+		// do we need to first delete an existing version of this table ?
666
+		if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
667
+			// ok, delete the table... but ONLY if it's empty
668
+			$deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
669
+			// table is NOT empty, are you SURE you want to delete this table ???
670
+			if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
671
+				\EEH_Activation::getTableManager()->dropTable($wp_table_name);
672
+			} else if ( ! $deleted_safely) {
673
+				// so we should be more cautious rather than just dropping tables so easily
674
+				error_log(
675
+					sprintf(
676
+						__(
677
+							'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.',
678
+							'event_espresso'
679
+						),
680
+						$wp_table_name,
681
+						'<br/>',
682
+						'espresso_db_update'
683
+					)
684
+				);
685
+			}
686
+		}
687
+		$engine = str_replace('ENGINE=', '', $engine);
688
+		\EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
689
+	}
690
+
691
+
692
+
693
+	/**
694
+	 *    add_column_if_it_doesn't_exist
695
+	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
696
+	 *
697
+	 * @access     public
698
+	 * @static
699
+	 * @deprecated instead use TableManager::addColumn()
700
+	 * @param string $table_name  (without "wp_", eg "esp_attendee"
701
+	 * @param string $column_name
702
+	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
703
+	 *                            'VARCHAR(10)'
704
+	 * @return bool|int
705
+	 */
706
+	public static function add_column_if_it_doesnt_exist(
707
+		$table_name,
708
+		$column_name,
709
+		$column_info = 'INT UNSIGNED NOT NULL'
710
+	) {
711
+		return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
712
+	}
713
+
714
+
715
+	/**
716
+	 * get_fields_on_table
717
+	 * Gets all the fields on the database table.
718
+	 *
719
+	 * @access     public
720
+	 * @deprecated instead use TableManager::getTableColumns()
721
+	 * @static
722
+	 * @param string $table_name , without prefixed $wpdb->prefix
723
+	 * @return array of database column names
724
+	 */
725
+	public static function get_fields_on_table($table_name = null)
726
+	{
727
+		return \EEH_Activation::getTableManager()->getTableColumns($table_name);
728
+	}
729
+
730
+
731
+	/**
732
+	 * db_table_is_empty
733
+	 *
734
+	 * @access     public\
735
+	 * @deprecated instead use TableAnalysis::tableIsEmpty()
736
+	 * @static
737
+	 * @param string $table_name
738
+	 * @return bool
739
+	 */
740
+	public static function db_table_is_empty($table_name)
741
+	{
742
+		return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
743
+	}
744
+
745
+
746
+	/**
747
+	 * delete_db_table_if_empty
748
+	 *
749
+	 * @access public
750
+	 * @static
751
+	 * @param string $table_name
752
+	 * @return bool | int
753
+	 */
754
+	public static function delete_db_table_if_empty($table_name)
755
+	{
756
+		if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
757
+			return \EEH_Activation::getTableManager()->dropTable($table_name);
758
+		}
759
+		return false;
760
+	}
761
+
762
+
763
+	/**
764
+	 * delete_unused_db_table
765
+	 *
766
+	 * @access     public
767
+	 * @static
768
+	 * @deprecated instead use TableManager::dropTable()
769
+	 * @param string $table_name
770
+	 * @return bool | int
771
+	 */
772
+	public static function delete_unused_db_table($table_name)
773
+	{
774
+		return \EEH_Activation::getTableManager()->dropTable($table_name);
775
+	}
776
+
777
+
778
+	/**
779
+	 * drop_index
780
+	 *
781
+	 * @access     public
782
+	 * @static
783
+	 * @deprecated instead use TableManager::dropIndex()
784
+	 * @param string $table_name
785
+	 * @param string $index_name
786
+	 * @return bool | int
787
+	 */
788
+	public static function drop_index($table_name, $index_name)
789
+	{
790
+		return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
791
+	}
792
+
793
+
794
+
795
+	/**
796
+	 * create_database_tables
797
+	 *
798
+	 * @access public
799
+	 * @static
800
+	 * @throws EE_Error
801
+	 * @return boolean success (whether database is setup properly or not)
802
+	 */
803
+	public static function create_database_tables()
804
+	{
805
+		EE_Registry::instance()->load_core('Data_Migration_Manager');
806
+		//find the migration script that sets the database to be compatible with the code
807
+		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
808
+		if ($dms_name) {
809
+			$current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
810
+			$current_data_migration_script->set_migrating(false);
811
+			$current_data_migration_script->schema_changes_before_migration();
812
+			$current_data_migration_script->schema_changes_after_migration();
813
+			if ($current_data_migration_script->get_errors()) {
814
+				if (WP_DEBUG) {
815
+					foreach ($current_data_migration_script->get_errors() as $error) {
816
+						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
817
+					}
818
+				} else {
819
+					EE_Error::add_error(
820
+						__(
821
+							'There were errors creating the Event Espresso database tables and Event Espresso has been 
822 822
                             deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.',
823
-                            'event_espresso'
824
-                        )
825
-                    );
826
-                }
827
-                return false;
828
-            }
829
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to();
830
-        } else {
831
-            EE_Error::add_error(
832
-                __(
833
-                    'Could not determine most up-to-date data migration script from which to pull database schema
823
+							'event_espresso'
824
+						)
825
+					);
826
+				}
827
+				return false;
828
+			}
829
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
830
+		} else {
831
+			EE_Error::add_error(
832
+				__(
833
+					'Could not determine most up-to-date data migration script from which to pull database schema
834 834
                      structure. So database is probably not setup properly',
835
-                    'event_espresso'
836
-                ),
837
-                __FILE__,
838
-                __FUNCTION__,
839
-                __LINE__
840
-            );
841
-            return false;
842
-        }
843
-        return true;
844
-    }
845
-
846
-
847
-
848
-    /**
849
-     * initialize_system_questions
850
-     *
851
-     * @access public
852
-     * @static
853
-     * @return void
854
-     */
855
-    public static function initialize_system_questions()
856
-    {
857
-        // QUESTION GROUPS
858
-        global $wpdb;
859
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
860
-        $SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
861
-        // what we have
862
-        $question_groups = $wpdb->get_col($SQL);
863
-        // check the response
864
-        $question_groups = is_array($question_groups) ? $question_groups : array();
865
-        // what we should have
866
-        $QSG_systems = array(1, 2);
867
-        // loop thru what we should have and compare to what we have
868
-        foreach ($QSG_systems as $QSG_system) {
869
-            // reset values array
870
-            $QSG_values = array();
871
-            // 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)
872
-            if (! in_array("$QSG_system", $question_groups)) {
873
-                // add it
874
-                switch ($QSG_system) {
875
-                    case 1:
876
-                        $QSG_values = array(
877
-                            'QSG_name'            => __('Personal Information', 'event_espresso'),
878
-                            'QSG_identifier'      => 'personal-information-' . time(),
879
-                            'QSG_desc'            => '',
880
-                            'QSG_order'           => 1,
881
-                            'QSG_show_group_name' => 1,
882
-                            'QSG_show_group_desc' => 1,
883
-                            'QSG_system'          => EEM_Question_Group::system_personal,
884
-                            'QSG_deleted'         => 0,
885
-                        );
886
-                        break;
887
-                    case 2:
888
-                        $QSG_values = array(
889
-                            'QSG_name'            => __('Address Information', 'event_espresso'),
890
-                            'QSG_identifier'      => 'address-information-' . time(),
891
-                            'QSG_desc'            => '',
892
-                            'QSG_order'           => 2,
893
-                            'QSG_show_group_name' => 1,
894
-                            'QSG_show_group_desc' => 1,
895
-                            'QSG_system'          => EEM_Question_Group::system_address,
896
-                            'QSG_deleted'         => 0,
897
-                        );
898
-                        break;
899
-                }
900
-                // make sure we have some values before inserting them
901
-                if (! empty($QSG_values)) {
902
-                    // insert system question
903
-                    $wpdb->insert(
904
-                        $table_name,
905
-                        $QSG_values,
906
-                        array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
907
-                    );
908
-                    $QSG_IDs[$QSG_system] = $wpdb->insert_id;
909
-                }
910
-            }
911
-        }
912
-        // QUESTIONS
913
-        global $wpdb;
914
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
915
-        $SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
916
-        // what we have
917
-        $questions = $wpdb->get_col($SQL);
918
-        // what we should have
919
-        $QST_systems = array(
920
-            'fname',
921
-            'lname',
922
-            'email',
923
-            'address',
924
-            'address2',
925
-            'city',
926
-            'country',
927
-            'state',
928
-            'zip',
929
-            'phone',
930
-        );
931
-        $order_for_group_1 = 1;
932
-        $order_for_group_2 = 1;
933
-        // loop thru what we should have and compare to what we have
934
-        foreach ($QST_systems as $QST_system) {
935
-            // reset values array
936
-            $QST_values = array();
937
-            // if we don't have what we should have
938
-            if (! in_array($QST_system, $questions)) {
939
-                // add it
940
-                switch ($QST_system) {
941
-                    case 'fname':
942
-                        $QST_values = array(
943
-                            'QST_display_text'  => __('First Name', 'event_espresso'),
944
-                            'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
945
-                            'QST_system'        => 'fname',
946
-                            'QST_type'          => 'TEXT',
947
-                            'QST_required'      => 1,
948
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
949
-                            'QST_order'         => 1,
950
-                            'QST_admin_only'    => 0,
951
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
952
-                            'QST_wp_user'       => self::get_default_creator_id(),
953
-                            'QST_deleted'       => 0,
954
-                        );
955
-                        break;
956
-                    case 'lname':
957
-                        $QST_values = array(
958
-                            'QST_display_text'  => __('Last Name', 'event_espresso'),
959
-                            'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
960
-                            'QST_system'        => 'lname',
961
-                            'QST_type'          => 'TEXT',
962
-                            'QST_required'      => 1,
963
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
964
-                            'QST_order'         => 2,
965
-                            'QST_admin_only'    => 0,
966
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
967
-                            'QST_wp_user'       => self::get_default_creator_id(),
968
-                            'QST_deleted'       => 0,
969
-                        );
970
-                        break;
971
-                    case 'email':
972
-                        $QST_values = array(
973
-                            'QST_display_text'  => __('Email Address', 'event_espresso'),
974
-                            'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
975
-                            'QST_system'        => 'email',
976
-                            'QST_type'          => 'EMAIL',
977
-                            'QST_required'      => 1,
978
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
979
-                            'QST_order'         => 3,
980
-                            'QST_admin_only'    => 0,
981
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
982
-                            'QST_wp_user'       => self::get_default_creator_id(),
983
-                            'QST_deleted'       => 0,
984
-                        );
985
-                        break;
986
-                    case 'address':
987
-                        $QST_values = array(
988
-                            'QST_display_text'  => __('Address', 'event_espresso'),
989
-                            'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
990
-                            'QST_system'        => 'address',
991
-                            'QST_type'          => 'TEXT',
992
-                            'QST_required'      => 0,
993
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
994
-                            'QST_order'         => 4,
995
-                            'QST_admin_only'    => 0,
996
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
997
-                            'QST_wp_user'       => self::get_default_creator_id(),
998
-                            'QST_deleted'       => 0,
999
-                        );
1000
-                        break;
1001
-                    case 'address2':
1002
-                        $QST_values = array(
1003
-                            'QST_display_text'  => __('Address2', 'event_espresso'),
1004
-                            'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1005
-                            'QST_system'        => 'address2',
1006
-                            'QST_type'          => 'TEXT',
1007
-                            'QST_required'      => 0,
1008
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1009
-                            'QST_order'         => 5,
1010
-                            'QST_admin_only'    => 0,
1011
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1012
-                            'QST_wp_user'       => self::get_default_creator_id(),
1013
-                            'QST_deleted'       => 0,
1014
-                        );
1015
-                        break;
1016
-                    case 'city':
1017
-                        $QST_values = array(
1018
-                            'QST_display_text'  => __('City', 'event_espresso'),
1019
-                            'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1020
-                            'QST_system'        => 'city',
1021
-                            'QST_type'          => 'TEXT',
1022
-                            'QST_required'      => 0,
1023
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1024
-                            'QST_order'         => 6,
1025
-                            'QST_admin_only'    => 0,
1026
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1027
-                            'QST_wp_user'       => self::get_default_creator_id(),
1028
-                            'QST_deleted'       => 0,
1029
-                        );
1030
-                        break;
1031
-                    case 'country':
1032
-                        $QST_values = array(
1033
-                            'QST_display_text'  => __('Country', 'event_espresso'),
1034
-                            'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1035
-                            'QST_system'        => 'country',
1036
-                            'QST_type'          => 'COUNTRY',
1037
-                            'QST_required'      => 0,
1038
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1039
-                            'QST_order'         => 7,
1040
-                            'QST_admin_only'    => 0,
1041
-                            'QST_wp_user'       => self::get_default_creator_id(),
1042
-                            'QST_deleted'       => 0,
1043
-                        );
1044
-                        break;
1045
-                    case 'state':
1046
-                        $QST_values = array(
1047
-                            'QST_display_text'  => __('State/Province', 'event_espresso'),
1048
-                            'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1049
-                            'QST_system'        => 'state',
1050
-                            'QST_type'          => 'STATE',
1051
-                            'QST_required'      => 0,
1052
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1053
-                            'QST_order'         => 8,
1054
-                            'QST_admin_only'    => 0,
1055
-                            'QST_wp_user'       => self::get_default_creator_id(),
1056
-                            'QST_deleted'       => 0,
1057
-                        );
1058
-                        break;
1059
-                    case 'zip':
1060
-                        $QST_values = array(
1061
-                            'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1062
-                            'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1063
-                            'QST_system'        => 'zip',
1064
-                            'QST_type'          => 'TEXT',
1065
-                            'QST_required'      => 0,
1066
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1067
-                            'QST_order'         => 9,
1068
-                            'QST_admin_only'    => 0,
1069
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1070
-                            'QST_wp_user'       => self::get_default_creator_id(),
1071
-                            'QST_deleted'       => 0,
1072
-                        );
1073
-                        break;
1074
-                    case 'phone':
1075
-                        $QST_values = array(
1076
-                            'QST_display_text'  => __('Phone Number', 'event_espresso'),
1077
-                            'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1078
-                            'QST_system'        => 'phone',
1079
-                            'QST_type'          => 'TEXT',
1080
-                            'QST_required'      => 0,
1081
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1082
-                            'QST_order'         => 10,
1083
-                            'QST_admin_only'    => 0,
1084
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1085
-                            'QST_wp_user'       => self::get_default_creator_id(),
1086
-                            'QST_deleted'       => 0,
1087
-                        );
1088
-                        break;
1089
-                }
1090
-                if (! empty($QST_values)) {
1091
-                    // insert system question
1092
-                    $wpdb->insert(
1093
-                        $table_name,
1094
-                        $QST_values,
1095
-                        array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1096
-                    );
1097
-                    $QST_ID = $wpdb->insert_id;
1098
-                    // QUESTION GROUP QUESTIONS
1099
-                    if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1100
-                        $system_question_we_want = EEM_Question_Group::system_personal;
1101
-                    } else {
1102
-                        $system_question_we_want = EEM_Question_Group::system_address;
1103
-                    }
1104
-                    if (isset($QSG_IDs[$system_question_we_want])) {
1105
-                        $QSG_ID = $QSG_IDs[$system_question_we_want];
1106
-                    } else {
1107
-                        $id_col = EEM_Question_Group::instance()
1108
-                                                    ->get_col(array(array('QSG_system' => $system_question_we_want)));
1109
-                        if (is_array($id_col)) {
1110
-                            $QSG_ID = reset($id_col);
1111
-                        } else {
1112
-                            //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
1113
-                            EE_Log::instance()->log(
1114
-                                __FILE__,
1115
-                                __FUNCTION__,
1116
-                                sprintf(
1117
-                                    __(
1118
-                                        'Could not associate question %1$s to a question group because no system question
835
+					'event_espresso'
836
+				),
837
+				__FILE__,
838
+				__FUNCTION__,
839
+				__LINE__
840
+			);
841
+			return false;
842
+		}
843
+		return true;
844
+	}
845
+
846
+
847
+
848
+	/**
849
+	 * initialize_system_questions
850
+	 *
851
+	 * @access public
852
+	 * @static
853
+	 * @return void
854
+	 */
855
+	public static function initialize_system_questions()
856
+	{
857
+		// QUESTION GROUPS
858
+		global $wpdb;
859
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
860
+		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
861
+		// what we have
862
+		$question_groups = $wpdb->get_col($SQL);
863
+		// check the response
864
+		$question_groups = is_array($question_groups) ? $question_groups : array();
865
+		// what we should have
866
+		$QSG_systems = array(1, 2);
867
+		// loop thru what we should have and compare to what we have
868
+		foreach ($QSG_systems as $QSG_system) {
869
+			// reset values array
870
+			$QSG_values = array();
871
+			// 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)
872
+			if (! in_array("$QSG_system", $question_groups)) {
873
+				// add it
874
+				switch ($QSG_system) {
875
+					case 1:
876
+						$QSG_values = array(
877
+							'QSG_name'            => __('Personal Information', 'event_espresso'),
878
+							'QSG_identifier'      => 'personal-information-' . time(),
879
+							'QSG_desc'            => '',
880
+							'QSG_order'           => 1,
881
+							'QSG_show_group_name' => 1,
882
+							'QSG_show_group_desc' => 1,
883
+							'QSG_system'          => EEM_Question_Group::system_personal,
884
+							'QSG_deleted'         => 0,
885
+						);
886
+						break;
887
+					case 2:
888
+						$QSG_values = array(
889
+							'QSG_name'            => __('Address Information', 'event_espresso'),
890
+							'QSG_identifier'      => 'address-information-' . time(),
891
+							'QSG_desc'            => '',
892
+							'QSG_order'           => 2,
893
+							'QSG_show_group_name' => 1,
894
+							'QSG_show_group_desc' => 1,
895
+							'QSG_system'          => EEM_Question_Group::system_address,
896
+							'QSG_deleted'         => 0,
897
+						);
898
+						break;
899
+				}
900
+				// make sure we have some values before inserting them
901
+				if (! empty($QSG_values)) {
902
+					// insert system question
903
+					$wpdb->insert(
904
+						$table_name,
905
+						$QSG_values,
906
+						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
907
+					);
908
+					$QSG_IDs[$QSG_system] = $wpdb->insert_id;
909
+				}
910
+			}
911
+		}
912
+		// QUESTIONS
913
+		global $wpdb;
914
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
915
+		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
916
+		// what we have
917
+		$questions = $wpdb->get_col($SQL);
918
+		// what we should have
919
+		$QST_systems = array(
920
+			'fname',
921
+			'lname',
922
+			'email',
923
+			'address',
924
+			'address2',
925
+			'city',
926
+			'country',
927
+			'state',
928
+			'zip',
929
+			'phone',
930
+		);
931
+		$order_for_group_1 = 1;
932
+		$order_for_group_2 = 1;
933
+		// loop thru what we should have and compare to what we have
934
+		foreach ($QST_systems as $QST_system) {
935
+			// reset values array
936
+			$QST_values = array();
937
+			// if we don't have what we should have
938
+			if (! in_array($QST_system, $questions)) {
939
+				// add it
940
+				switch ($QST_system) {
941
+					case 'fname':
942
+						$QST_values = array(
943
+							'QST_display_text'  => __('First Name', 'event_espresso'),
944
+							'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
945
+							'QST_system'        => 'fname',
946
+							'QST_type'          => 'TEXT',
947
+							'QST_required'      => 1,
948
+							'QST_required_text' => __('This field is required', 'event_espresso'),
949
+							'QST_order'         => 1,
950
+							'QST_admin_only'    => 0,
951
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
952
+							'QST_wp_user'       => self::get_default_creator_id(),
953
+							'QST_deleted'       => 0,
954
+						);
955
+						break;
956
+					case 'lname':
957
+						$QST_values = array(
958
+							'QST_display_text'  => __('Last Name', 'event_espresso'),
959
+							'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
960
+							'QST_system'        => 'lname',
961
+							'QST_type'          => 'TEXT',
962
+							'QST_required'      => 1,
963
+							'QST_required_text' => __('This field is required', 'event_espresso'),
964
+							'QST_order'         => 2,
965
+							'QST_admin_only'    => 0,
966
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
967
+							'QST_wp_user'       => self::get_default_creator_id(),
968
+							'QST_deleted'       => 0,
969
+						);
970
+						break;
971
+					case 'email':
972
+						$QST_values = array(
973
+							'QST_display_text'  => __('Email Address', 'event_espresso'),
974
+							'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
975
+							'QST_system'        => 'email',
976
+							'QST_type'          => 'EMAIL',
977
+							'QST_required'      => 1,
978
+							'QST_required_text' => __('This field is required', 'event_espresso'),
979
+							'QST_order'         => 3,
980
+							'QST_admin_only'    => 0,
981
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
982
+							'QST_wp_user'       => self::get_default_creator_id(),
983
+							'QST_deleted'       => 0,
984
+						);
985
+						break;
986
+					case 'address':
987
+						$QST_values = array(
988
+							'QST_display_text'  => __('Address', 'event_espresso'),
989
+							'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
990
+							'QST_system'        => 'address',
991
+							'QST_type'          => 'TEXT',
992
+							'QST_required'      => 0,
993
+							'QST_required_text' => __('This field is required', 'event_espresso'),
994
+							'QST_order'         => 4,
995
+							'QST_admin_only'    => 0,
996
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
997
+							'QST_wp_user'       => self::get_default_creator_id(),
998
+							'QST_deleted'       => 0,
999
+						);
1000
+						break;
1001
+					case 'address2':
1002
+						$QST_values = array(
1003
+							'QST_display_text'  => __('Address2', 'event_espresso'),
1004
+							'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1005
+							'QST_system'        => 'address2',
1006
+							'QST_type'          => 'TEXT',
1007
+							'QST_required'      => 0,
1008
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1009
+							'QST_order'         => 5,
1010
+							'QST_admin_only'    => 0,
1011
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1012
+							'QST_wp_user'       => self::get_default_creator_id(),
1013
+							'QST_deleted'       => 0,
1014
+						);
1015
+						break;
1016
+					case 'city':
1017
+						$QST_values = array(
1018
+							'QST_display_text'  => __('City', 'event_espresso'),
1019
+							'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1020
+							'QST_system'        => 'city',
1021
+							'QST_type'          => 'TEXT',
1022
+							'QST_required'      => 0,
1023
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1024
+							'QST_order'         => 6,
1025
+							'QST_admin_only'    => 0,
1026
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1027
+							'QST_wp_user'       => self::get_default_creator_id(),
1028
+							'QST_deleted'       => 0,
1029
+						);
1030
+						break;
1031
+					case 'country':
1032
+						$QST_values = array(
1033
+							'QST_display_text'  => __('Country', 'event_espresso'),
1034
+							'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1035
+							'QST_system'        => 'country',
1036
+							'QST_type'          => 'COUNTRY',
1037
+							'QST_required'      => 0,
1038
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1039
+							'QST_order'         => 7,
1040
+							'QST_admin_only'    => 0,
1041
+							'QST_wp_user'       => self::get_default_creator_id(),
1042
+							'QST_deleted'       => 0,
1043
+						);
1044
+						break;
1045
+					case 'state':
1046
+						$QST_values = array(
1047
+							'QST_display_text'  => __('State/Province', 'event_espresso'),
1048
+							'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1049
+							'QST_system'        => 'state',
1050
+							'QST_type'          => 'STATE',
1051
+							'QST_required'      => 0,
1052
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1053
+							'QST_order'         => 8,
1054
+							'QST_admin_only'    => 0,
1055
+							'QST_wp_user'       => self::get_default_creator_id(),
1056
+							'QST_deleted'       => 0,
1057
+						);
1058
+						break;
1059
+					case 'zip':
1060
+						$QST_values = array(
1061
+							'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1062
+							'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1063
+							'QST_system'        => 'zip',
1064
+							'QST_type'          => 'TEXT',
1065
+							'QST_required'      => 0,
1066
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1067
+							'QST_order'         => 9,
1068
+							'QST_admin_only'    => 0,
1069
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1070
+							'QST_wp_user'       => self::get_default_creator_id(),
1071
+							'QST_deleted'       => 0,
1072
+						);
1073
+						break;
1074
+					case 'phone':
1075
+						$QST_values = array(
1076
+							'QST_display_text'  => __('Phone Number', 'event_espresso'),
1077
+							'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1078
+							'QST_system'        => 'phone',
1079
+							'QST_type'          => 'TEXT',
1080
+							'QST_required'      => 0,
1081
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1082
+							'QST_order'         => 10,
1083
+							'QST_admin_only'    => 0,
1084
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1085
+							'QST_wp_user'       => self::get_default_creator_id(),
1086
+							'QST_deleted'       => 0,
1087
+						);
1088
+						break;
1089
+				}
1090
+				if (! empty($QST_values)) {
1091
+					// insert system question
1092
+					$wpdb->insert(
1093
+						$table_name,
1094
+						$QST_values,
1095
+						array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1096
+					);
1097
+					$QST_ID = $wpdb->insert_id;
1098
+					// QUESTION GROUP QUESTIONS
1099
+					if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1100
+						$system_question_we_want = EEM_Question_Group::system_personal;
1101
+					} else {
1102
+						$system_question_we_want = EEM_Question_Group::system_address;
1103
+					}
1104
+					if (isset($QSG_IDs[$system_question_we_want])) {
1105
+						$QSG_ID = $QSG_IDs[$system_question_we_want];
1106
+					} else {
1107
+						$id_col = EEM_Question_Group::instance()
1108
+													->get_col(array(array('QSG_system' => $system_question_we_want)));
1109
+						if (is_array($id_col)) {
1110
+							$QSG_ID = reset($id_col);
1111
+						} else {
1112
+							//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
1113
+							EE_Log::instance()->log(
1114
+								__FILE__,
1115
+								__FUNCTION__,
1116
+								sprintf(
1117
+									__(
1118
+										'Could not associate question %1$s to a question group because no system question
1119 1119
                                          group existed',
1120
-                                        'event_espresso'
1121
-                                    ),
1122
-                                    $QST_ID),
1123
-                                'error');
1124
-                            continue;
1125
-                        }
1126
-                    }
1127
-                    // add system questions to groups
1128
-                    $wpdb->insert(
1129
-                        \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1130
-                        array(
1131
-                            'QSG_ID'    => $QSG_ID,
1132
-                            'QST_ID'    => $QST_ID,
1133
-                            'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1134
-                        ),
1135
-                        array('%d', '%d', '%d')
1136
-                    );
1137
-                }
1138
-            }
1139
-        }
1140
-    }
1141
-
1142
-
1143
-    /**
1144
-     * Makes sure the default payment method (Invoice) is active.
1145
-     * This used to be done automatically as part of constructing the old gateways config
1146
-     *
1147
-     * @throws \EE_Error
1148
-     */
1149
-    public static function insert_default_payment_methods()
1150
-    {
1151
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1152
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
1153
-            EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1154
-        } else {
1155
-            EEM_Payment_Method::instance()->verify_button_urls();
1156
-        }
1157
-    }
1158
-
1159
-    /**
1160
-     * insert_default_status_codes
1161
-     *
1162
-     * @access public
1163
-     * @static
1164
-     * @return void
1165
-     */
1166
-    public static function insert_default_status_codes()
1167
-    {
1168
-
1169
-        global $wpdb;
1170
-
1171
-        if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1172
-
1173
-            $table_name = EEM_Status::instance()->table();
1174
-
1175
-            $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' );";
1176
-            $wpdb->query($SQL);
1177
-
1178
-            $SQL = "INSERT INTO $table_name
1120
+										'event_espresso'
1121
+									),
1122
+									$QST_ID),
1123
+								'error');
1124
+							continue;
1125
+						}
1126
+					}
1127
+					// add system questions to groups
1128
+					$wpdb->insert(
1129
+						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1130
+						array(
1131
+							'QSG_ID'    => $QSG_ID,
1132
+							'QST_ID'    => $QST_ID,
1133
+							'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1134
+						),
1135
+						array('%d', '%d', '%d')
1136
+					);
1137
+				}
1138
+			}
1139
+		}
1140
+	}
1141
+
1142
+
1143
+	/**
1144
+	 * Makes sure the default payment method (Invoice) is active.
1145
+	 * This used to be done automatically as part of constructing the old gateways config
1146
+	 *
1147
+	 * @throws \EE_Error
1148
+	 */
1149
+	public static function insert_default_payment_methods()
1150
+	{
1151
+		if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1152
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
1153
+			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1154
+		} else {
1155
+			EEM_Payment_Method::instance()->verify_button_urls();
1156
+		}
1157
+	}
1158
+
1159
+	/**
1160
+	 * insert_default_status_codes
1161
+	 *
1162
+	 * @access public
1163
+	 * @static
1164
+	 * @return void
1165
+	 */
1166
+	public static function insert_default_status_codes()
1167
+	{
1168
+
1169
+		global $wpdb;
1170
+
1171
+		if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1172
+
1173
+			$table_name = EEM_Status::instance()->table();
1174
+
1175
+			$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' );";
1176
+			$wpdb->query($SQL);
1177
+
1178
+			$SQL = "INSERT INTO $table_name
1179 1179
 					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1180 1180
 					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1181 1181
 					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
@@ -1215,521 +1215,521 @@  discard block
 block discarded – undo
1215 1215
 					('MID', 'IDLE', 'message', 0, NULL, 1),
1216 1216
 					('MRS', 'RESEND', 'message', 0, NULL, 1),
1217 1217
 					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1218
-            $wpdb->query($SQL);
1219
-
1220
-        }
1221
-
1222
-    }
1223
-
1224
-
1225
-    /**
1226
-     * create_upload_directories
1227
-     * Creates folders in the uploads directory to facilitate addons and templates
1228
-     *
1229
-     * @access public
1230
-     * @static
1231
-     * @return boolean success of verifying upload directories exist
1232
-     */
1233
-    public static function create_upload_directories()
1234
-    {
1235
-        // Create the required folders
1236
-        $folders = array(
1237
-            EVENT_ESPRESSO_TEMPLATE_DIR,
1238
-            EVENT_ESPRESSO_GATEWAY_DIR,
1239
-            EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1240
-            EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1241
-            EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1242
-        );
1243
-        foreach ($folders as $folder) {
1244
-            try {
1245
-                EEH_File::ensure_folder_exists_and_is_writable($folder);
1246
-                @ chmod($folder, 0755);
1247
-            } catch (EE_Error $e) {
1248
-                EE_Error::add_error(
1249
-                    sprintf(
1250
-                        __('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1251
-                        $folder,
1252
-                        '<br />' . $e->getMessage()
1253
-                    ),
1254
-                    __FILE__, __FUNCTION__, __LINE__
1255
-                );
1256
-                //indicate we'll need to fix this later
1257
-                update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1258
-                return false;
1259
-            }
1260
-        }
1261
-        //just add the .htaccess file to the logs directory to begin with. Even if logging
1262
-        //is disabled, there might be activation errors recorded in there
1263
-        EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1264
-        //remember EE's folders are all good
1265
-        delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1266
-        return true;
1267
-    }
1268
-
1269
-    /**
1270
-     * Whether the upload directories need to be fixed or not.
1271
-     * If EE is installed but filesystem access isn't initially available,
1272
-     * we need to get the user's filesystem credentials and THEN create them,
1273
-     * so there might be period of time when EE is installed but its
1274
-     * upload directories aren't available. This indicates such a state
1275
-     *
1276
-     * @return boolean
1277
-     */
1278
-    public static function upload_directories_incomplete()
1279
-    {
1280
-        return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1281
-    }
1282
-
1283
-
1284
-    /**
1285
-     * generate_default_message_templates
1286
-     *
1287
-     * @static
1288
-     * @throws EE_Error
1289
-     * @return bool     true means new templates were created.
1290
-     *                  false means no templates were created.
1291
-     *                  This is NOT an error flag. To check for errors you will want
1292
-     *                  to use either EE_Error or a try catch for an EE_Error exception.
1293
-     */
1294
-    public static function generate_default_message_templates()
1295
-    {
1296
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1297
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1298
-        /*
1218
+			$wpdb->query($SQL);
1219
+
1220
+		}
1221
+
1222
+	}
1223
+
1224
+
1225
+	/**
1226
+	 * create_upload_directories
1227
+	 * Creates folders in the uploads directory to facilitate addons and templates
1228
+	 *
1229
+	 * @access public
1230
+	 * @static
1231
+	 * @return boolean success of verifying upload directories exist
1232
+	 */
1233
+	public static function create_upload_directories()
1234
+	{
1235
+		// Create the required folders
1236
+		$folders = array(
1237
+			EVENT_ESPRESSO_TEMPLATE_DIR,
1238
+			EVENT_ESPRESSO_GATEWAY_DIR,
1239
+			EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1240
+			EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1241
+			EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1242
+		);
1243
+		foreach ($folders as $folder) {
1244
+			try {
1245
+				EEH_File::ensure_folder_exists_and_is_writable($folder);
1246
+				@ chmod($folder, 0755);
1247
+			} catch (EE_Error $e) {
1248
+				EE_Error::add_error(
1249
+					sprintf(
1250
+						__('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1251
+						$folder,
1252
+						'<br />' . $e->getMessage()
1253
+					),
1254
+					__FILE__, __FUNCTION__, __LINE__
1255
+				);
1256
+				//indicate we'll need to fix this later
1257
+				update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1258
+				return false;
1259
+			}
1260
+		}
1261
+		//just add the .htaccess file to the logs directory to begin with. Even if logging
1262
+		//is disabled, there might be activation errors recorded in there
1263
+		EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1264
+		//remember EE's folders are all good
1265
+		delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1266
+		return true;
1267
+	}
1268
+
1269
+	/**
1270
+	 * Whether the upload directories need to be fixed or not.
1271
+	 * If EE is installed but filesystem access isn't initially available,
1272
+	 * we need to get the user's filesystem credentials and THEN create them,
1273
+	 * so there might be period of time when EE is installed but its
1274
+	 * upload directories aren't available. This indicates such a state
1275
+	 *
1276
+	 * @return boolean
1277
+	 */
1278
+	public static function upload_directories_incomplete()
1279
+	{
1280
+		return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1281
+	}
1282
+
1283
+
1284
+	/**
1285
+	 * generate_default_message_templates
1286
+	 *
1287
+	 * @static
1288
+	 * @throws EE_Error
1289
+	 * @return bool     true means new templates were created.
1290
+	 *                  false means no templates were created.
1291
+	 *                  This is NOT an error flag. To check for errors you will want
1292
+	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1293
+	 */
1294
+	public static function generate_default_message_templates()
1295
+	{
1296
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1297
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1298
+		/*
1299 1299
          * This first method is taking care of ensuring any default messengers
1300 1300
          * that should be made active and have templates generated are done.
1301 1301
          */
1302
-        $new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1303
-            $message_resource_manager
1304
-        );
1305
-        /**
1306
-         * This method is verifying there are no NEW default message types
1307
-         * for ACTIVE messengers that need activated (and corresponding templates setup).
1308
-         */
1309
-        $new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1310
-            $message_resource_manager
1311
-        );
1312
-        //after all is done, let's persist these changes to the db.
1313
-        $message_resource_manager->update_has_activated_messengers_option();
1314
-        $message_resource_manager->update_active_messengers_option();
1315
-        // will return true if either of these are true.  Otherwise will return false.
1316
-        return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1317
-    }
1318
-
1319
-
1320
-
1321
-    /**
1322
-     * @param \EE_Message_Resource_Manager $message_resource_manager
1323
-     * @return array|bool
1324
-     * @throws \EE_Error
1325
-     */
1326
-    protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1327
-        EE_Message_Resource_Manager $message_resource_manager
1328
-    ) {
1329
-        /** @type EE_messenger[] $active_messengers */
1330
-        $active_messengers = $message_resource_manager->active_messengers();
1331
-        $installed_message_types = $message_resource_manager->installed_message_types();
1332
-        $templates_created = false;
1333
-        foreach ($active_messengers as $active_messenger) {
1334
-            $default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1335
-            $default_message_type_names_to_activate = array();
1336
-            // looping through each default message type reported by the messenger
1337
-            // and setup the actual message types to activate.
1338
-            foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1339
-                // if already active or has already been activated before we skip
1340
-                // (otherwise we might reactivate something user's intentionally deactivated.)
1341
-                // we also skip if the message type is not installed.
1342
-                if (
1343
-                    $message_resource_manager->has_message_type_been_activated_for_messenger(
1344
-                        $default_message_type_name_for_messenger,
1345
-                        $active_messenger->name
1346
-                    )
1347
-                    || $message_resource_manager->is_message_type_active_for_messenger(
1348
-                        $active_messenger->name,
1349
-                        $default_message_type_name_for_messenger
1350
-                    )
1351
-                    || ! isset($installed_message_types[$default_message_type_name_for_messenger])
1352
-                ) {
1353
-                    continue;
1354
-                }
1355
-                $default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1356
-            }
1357
-            //let's activate!
1358
-            $message_resource_manager->ensure_message_types_are_active(
1359
-                $default_message_type_names_to_activate,
1360
-                $active_messenger->name,
1361
-                false
1362
-            );
1363
-            //activate the templates for these message types
1364
-            if ( ! empty($default_message_type_names_to_activate)) {
1365
-                $templates_created = EEH_MSG_Template::generate_new_templates(
1366
-                    $active_messenger->name,
1367
-                    $default_message_type_names_for_messenger,
1368
-                    '',
1369
-                    true
1370
-                );
1371
-            }
1372
-        }
1373
-        return $templates_created;
1374
-    }
1375
-
1376
-
1377
-
1378
-    /**
1379
-     * This will activate and generate default messengers and default message types for those messengers.
1380
-     *
1381
-     * @param EE_message_Resource_Manager $message_resource_manager
1382
-     * @return array|bool  True means there were default messengers and message type templates generated.
1383
-     *                     False means that there were no templates generated
1384
-     *                     (which could simply mean there are no default message types for a messenger).
1385
-     * @throws EE_Error
1386
-     */
1387
-    protected static function _activate_and_generate_default_messengers_and_message_templates(
1388
-        EE_Message_Resource_Manager $message_resource_manager
1389
-    ) {
1390
-        /** @type EE_messenger[] $messengers_to_generate */
1391
-        $messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1392
-        $installed_message_types = $message_resource_manager->installed_message_types();
1393
-        $templates_generated = false;
1394
-        foreach ($messengers_to_generate as $messenger_to_generate) {
1395
-            $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1396
-            //verify the default message types match an installed message type.
1397
-            foreach ($default_message_type_names_for_messenger as $key => $name) {
1398
-                if (
1399
-                    ! isset($installed_message_types[$name])
1400
-                    || $message_resource_manager->has_message_type_been_activated_for_messenger(
1401
-                        $name,
1402
-                        $messenger_to_generate->name
1403
-                    )
1404
-                ) {
1405
-                    unset($default_message_type_names_for_messenger[$key]);
1406
-                }
1407
-            }
1408
-            // in previous iterations, the active_messengers option in the db
1409
-            // needed updated before calling create templates. however with the changes this may not be necessary.
1410
-            // This comment is left here just in case we discover that we _do_ need to update before
1411
-            // passing off to create templates (after the refactor is done).
1412
-            // @todo remove this comment when determined not necessary.
1413
-            $message_resource_manager->activate_messenger(
1414
-                $messenger_to_generate->name,
1415
-                $default_message_type_names_for_messenger,
1416
-                false
1417
-            );
1418
-            //create any templates needing created (or will reactivate templates already generated as necessary).
1419
-            if ( ! empty($default_message_type_names_for_messenger)) {
1420
-                $templates_generated = EEH_MSG_Template::generate_new_templates(
1421
-                    $messenger_to_generate->name,
1422
-                    $default_message_type_names_for_messenger,
1423
-                    '',
1424
-                    true
1425
-                );
1426
-            }
1427
-        }
1428
-        return $templates_generated;
1429
-    }
1430
-
1431
-
1432
-    /**
1433
-     * This returns the default messengers to generate templates for on activation of EE.
1434
-     * It considers:
1435
-     * - whether a messenger is already active in the db.
1436
-     * - whether a messenger has been made active at any time in the past.
1437
-     *
1438
-     * @static
1439
-     * @param  EE_Message_Resource_Manager $message_resource_manager
1440
-     * @return EE_messenger[]
1441
-     */
1442
-    protected static function _get_default_messengers_to_generate_on_activation(
1443
-        EE_Message_Resource_Manager $message_resource_manager
1444
-    ) {
1445
-        $active_messengers    = $message_resource_manager->active_messengers();
1446
-        $installed_messengers = $message_resource_manager->installed_messengers();
1447
-        $has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1448
-
1449
-        $messengers_to_generate = array();
1450
-        foreach ($installed_messengers as $installed_messenger) {
1451
-            //if installed messenger is a messenger that should be activated on install
1452
-            //and is not already active
1453
-            //and has never been activated
1454
-            if (
1455
-                ! $installed_messenger->activate_on_install
1456
-                || isset($active_messengers[$installed_messenger->name])
1457
-                || isset($has_activated[$installed_messenger->name])
1458
-            ) {
1459
-                continue;
1460
-            }
1461
-            $messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1462
-        }
1463
-        return $messengers_to_generate;
1464
-    }
1465
-
1466
-
1467
-    /**
1468
-     * This simply validates active message types to ensure they actually match installed
1469
-     * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1470
-     * rows are set inactive.
1471
-     * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1472
-     * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1473
-     * are still handled in here.
1474
-     *
1475
-     * @since 4.3.1
1476
-     * @return void
1477
-     */
1478
-    public static function validate_messages_system()
1479
-    {
1480
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1481
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1482
-        $message_resource_manager->validate_active_message_types_are_installed();
1483
-        do_action('AHEE__EEH_Activation__validate_messages_system');
1484
-    }
1485
-
1486
-
1487
-    /**
1488
-     * create_no_ticket_prices_array
1489
-     *
1490
-     * @access public
1491
-     * @static
1492
-     * @return void
1493
-     */
1494
-    public static function create_no_ticket_prices_array()
1495
-    {
1496
-        // this creates an array for tracking events that have no active ticket prices created
1497
-        // this allows us to warn admins of the situation so that it can be corrected
1498
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1499
-        if (! $espresso_no_ticket_prices) {
1500
-            add_option('ee_no_ticket_prices', array(), '', false);
1501
-        }
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * plugin_deactivation
1507
-     *
1508
-     * @access public
1509
-     * @static
1510
-     * @return void
1511
-     */
1512
-    public static function plugin_deactivation()
1513
-    {
1514
-    }
1515
-
1516
-
1517
-    /**
1518
-     * Finds all our EE4 custom post types, and deletes them and their associated data
1519
-     * (like post meta or term relations)
1520
-     *
1521
-     * @global wpdb $wpdb
1522
-     * @throws \EE_Error
1523
-     */
1524
-    public static function delete_all_espresso_cpt_data()
1525
-    {
1526
-        global $wpdb;
1527
-        //get all the CPT post_types
1528
-        $ee_post_types = array();
1529
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1530
-            if (method_exists($model_name, 'instance')) {
1531
-                $model_obj = call_user_func(array($model_name, 'instance'));
1532
-                if ($model_obj instanceof EEM_CPT_Base) {
1533
-                    $ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1534
-                }
1535
-            }
1536
-        }
1537
-        //get all our CPTs
1538
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1539
-        $cpt_ids = $wpdb->get_col($query);
1540
-        //delete each post meta and term relations too
1541
-        foreach ($cpt_ids as $post_id) {
1542
-            wp_delete_post($post_id, true);
1543
-        }
1544
-    }
1545
-
1546
-    /**
1547
-     * Deletes all EE custom tables
1548
-     *
1549
-     * @return array
1550
-     */
1551
-    public static function drop_espresso_tables()
1552
-    {
1553
-        $tables = array();
1554
-        // load registry
1555
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1556
-            if (method_exists($model_name, 'instance')) {
1557
-                $model_obj = call_user_func(array($model_name, 'instance'));
1558
-                if ($model_obj instanceof EEM_Base) {
1559
-                    foreach ($model_obj->get_tables() as $table) {
1560
-                        if (strpos($table->get_table_name(), 'esp_')
1561
-                            &&
1562
-                            (
1563
-                                is_main_site()//main site? nuke them all
1564
-                                || ! $table->is_global()//not main site,but not global either. nuke it
1565
-                            )
1566
-                        ) {
1567
-                            $tables[$table->get_table_name()] = $table->get_table_name();
1568
-                        }
1569
-                    }
1570
-                }
1571
-            }
1572
-        }
1573
-
1574
-        //there are some tables whose models were removed.
1575
-        //they should be removed when removing all EE core's data
1576
-        $tables_without_models = array(
1577
-            'esp_promotion',
1578
-            'esp_promotion_applied',
1579
-            'esp_promotion_object',
1580
-            'esp_promotion_rule',
1581
-            'esp_rule',
1582
-        );
1583
-        foreach ($tables_without_models as $table) {
1584
-            $tables[$table] = $table;
1585
-        }
1586
-        return \EEH_Activation::getTableManager()->dropTables($tables);
1587
-    }
1588
-
1589
-
1590
-
1591
-    /**
1592
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
1593
-     * each table name provided has a wpdb prefix attached, and that it exists.
1594
-     * Returns the list actually deleted
1595
-     *
1596
-     * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1597
-     * @global WPDB $wpdb
1598
-     * @param array $table_names
1599
-     * @return array of table names which we deleted
1600
-     */
1601
-    public static function drop_tables($table_names)
1602
-    {
1603
-        return \EEH_Activation::getTableManager()->dropTables($table_names);
1604
-    }
1605
-
1606
-
1607
-
1608
-    /**
1609
-     * plugin_uninstall
1610
-     *
1611
-     * @access public
1612
-     * @static
1613
-     * @param bool $remove_all
1614
-     * @return void
1615
-     */
1616
-    public static function delete_all_espresso_tables_and_data($remove_all = true)
1617
-    {
1618
-        global $wpdb;
1619
-        self::drop_espresso_tables();
1620
-        $wp_options_to_delete = array(
1621
-            'ee_no_ticket_prices'                => true,
1622
-            'ee_active_messengers'               => true,
1623
-            'ee_has_activated_messenger'         => true,
1624
-            'ee_flush_rewrite_rules'             => true,
1625
-            'ee_config'                          => false,
1626
-            'ee_data_migration_current_db_state' => true,
1627
-            'ee_data_migration_mapping_'         => false,
1628
-            'ee_data_migration_script_'          => false,
1629
-            'ee_data_migrations'                 => true,
1630
-            'ee_dms_map'                         => false,
1631
-            'ee_notices'                         => true,
1632
-            'lang_file_check_'                   => false,
1633
-            'ee_maintenance_mode'                => true,
1634
-            'ee_ueip_optin'                      => true,
1635
-            'ee_ueip_has_notified'               => true,
1636
-            'ee_plugin_activation_errors'        => true,
1637
-            'ee_id_mapping_from'                 => false,
1638
-            'espresso_persistent_admin_notices'  => true,
1639
-            'ee_encryption_key'                  => true,
1640
-            'pue_force_upgrade_'                 => false,
1641
-            'pue_json_error_'                    => false,
1642
-            'pue_install_key_'                   => false,
1643
-            'pue_verification_error_'            => false,
1644
-            'pu_dismissed_upgrade_'              => false,
1645
-            'external_updates-'                  => false,
1646
-            'ee_extra_data'                      => true,
1647
-            'ee_ssn_'                            => false,
1648
-            'ee_rss_'                            => false,
1649
-            'ee_rte_n_tx_'                       => false,
1650
-            'ee_pers_admin_notices'              => true,
1651
-            'ee_job_parameters_'                 => false,
1652
-            'ee_upload_directories_incomplete'   => true,
1653
-            'ee_verified_db_collations'          => true,
1654
-        );
1655
-        if (is_main_site()) {
1656
-            $wp_options_to_delete['ee_network_config'] = true;
1657
-        }
1658
-        $undeleted_options = array();
1659
-        foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1660
-            if ($no_wildcard) {
1661
-                if ( ! delete_option($option_name)) {
1662
-                    $undeleted_options[] = $option_name;
1663
-                }
1664
-            } else {
1665
-                $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1666
-                foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1667
-                    if ( ! delete_option($option_name_from_wildcard)) {
1668
-                        $undeleted_options[] = $option_name_from_wildcard;
1669
-                    }
1670
-                }
1671
-            }
1672
-        }
1673
-        //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1674
-        remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1675
-        if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1676
-            $db_update_sans_ee4 = array();
1677
-            foreach ($espresso_db_update as $version => $times_activated) {
1678
-                if ((string)$version[0] === '3') {//if its NON EE4
1679
-                    $db_update_sans_ee4[$version] = $times_activated;
1680
-                }
1681
-            }
1682
-            update_option('espresso_db_update', $db_update_sans_ee4);
1683
-        }
1684
-        $errors = '';
1685
-        if ( ! empty($undeleted_options)) {
1686
-            $errors .= sprintf(
1687
-                __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1688
-                '<br/>',
1689
-                implode(',<br/>', $undeleted_options)
1690
-            );
1691
-        }
1692
-        if ( ! empty($errors)) {
1693
-            EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1694
-        }
1695
-    }
1696
-
1697
-    /**
1698
-     * Gets the mysql error code from the last used query by wpdb
1699
-     *
1700
-     * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1701
-     */
1702
-    public static function last_wpdb_error_code()
1703
-    {
1704
-        global $wpdb;
1705
-        if ($wpdb->use_mysqli) {
1706
-            return mysqli_errno($wpdb->dbh);
1707
-        } else {
1708
-            return mysql_errno($wpdb->dbh);
1709
-        }
1710
-    }
1711
-
1712
-    /**
1713
-     * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1714
-     *
1715
-     * @global wpdb  $wpdb
1716
-     * @deprecated instead use TableAnalysis::tableExists()
1717
-     * @param string $table_name with or without $wpdb->prefix
1718
-     * @return boolean
1719
-     */
1720
-    public static function table_exists($table_name)
1721
-    {
1722
-        return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1723
-    }
1724
-
1725
-    /**
1726
-     * Resets the cache on EEH_Activation
1727
-     */
1728
-    public static function reset()
1729
-    {
1730
-        self::$_default_creator_id                             = null;
1731
-        self::$_initialized_db_content_already_in_this_request = false;
1732
-    }
1302
+		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1303
+			$message_resource_manager
1304
+		);
1305
+		/**
1306
+		 * This method is verifying there are no NEW default message types
1307
+		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1308
+		 */
1309
+		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1310
+			$message_resource_manager
1311
+		);
1312
+		//after all is done, let's persist these changes to the db.
1313
+		$message_resource_manager->update_has_activated_messengers_option();
1314
+		$message_resource_manager->update_active_messengers_option();
1315
+		// will return true if either of these are true.  Otherwise will return false.
1316
+		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1317
+	}
1318
+
1319
+
1320
+
1321
+	/**
1322
+	 * @param \EE_Message_Resource_Manager $message_resource_manager
1323
+	 * @return array|bool
1324
+	 * @throws \EE_Error
1325
+	 */
1326
+	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1327
+		EE_Message_Resource_Manager $message_resource_manager
1328
+	) {
1329
+		/** @type EE_messenger[] $active_messengers */
1330
+		$active_messengers = $message_resource_manager->active_messengers();
1331
+		$installed_message_types = $message_resource_manager->installed_message_types();
1332
+		$templates_created = false;
1333
+		foreach ($active_messengers as $active_messenger) {
1334
+			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1335
+			$default_message_type_names_to_activate = array();
1336
+			// looping through each default message type reported by the messenger
1337
+			// and setup the actual message types to activate.
1338
+			foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1339
+				// if already active or has already been activated before we skip
1340
+				// (otherwise we might reactivate something user's intentionally deactivated.)
1341
+				// we also skip if the message type is not installed.
1342
+				if (
1343
+					$message_resource_manager->has_message_type_been_activated_for_messenger(
1344
+						$default_message_type_name_for_messenger,
1345
+						$active_messenger->name
1346
+					)
1347
+					|| $message_resource_manager->is_message_type_active_for_messenger(
1348
+						$active_messenger->name,
1349
+						$default_message_type_name_for_messenger
1350
+					)
1351
+					|| ! isset($installed_message_types[$default_message_type_name_for_messenger])
1352
+				) {
1353
+					continue;
1354
+				}
1355
+				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1356
+			}
1357
+			//let's activate!
1358
+			$message_resource_manager->ensure_message_types_are_active(
1359
+				$default_message_type_names_to_activate,
1360
+				$active_messenger->name,
1361
+				false
1362
+			);
1363
+			//activate the templates for these message types
1364
+			if ( ! empty($default_message_type_names_to_activate)) {
1365
+				$templates_created = EEH_MSG_Template::generate_new_templates(
1366
+					$active_messenger->name,
1367
+					$default_message_type_names_for_messenger,
1368
+					'',
1369
+					true
1370
+				);
1371
+			}
1372
+		}
1373
+		return $templates_created;
1374
+	}
1375
+
1376
+
1377
+
1378
+	/**
1379
+	 * This will activate and generate default messengers and default message types for those messengers.
1380
+	 *
1381
+	 * @param EE_message_Resource_Manager $message_resource_manager
1382
+	 * @return array|bool  True means there were default messengers and message type templates generated.
1383
+	 *                     False means that there were no templates generated
1384
+	 *                     (which could simply mean there are no default message types for a messenger).
1385
+	 * @throws EE_Error
1386
+	 */
1387
+	protected static function _activate_and_generate_default_messengers_and_message_templates(
1388
+		EE_Message_Resource_Manager $message_resource_manager
1389
+	) {
1390
+		/** @type EE_messenger[] $messengers_to_generate */
1391
+		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1392
+		$installed_message_types = $message_resource_manager->installed_message_types();
1393
+		$templates_generated = false;
1394
+		foreach ($messengers_to_generate as $messenger_to_generate) {
1395
+			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1396
+			//verify the default message types match an installed message type.
1397
+			foreach ($default_message_type_names_for_messenger as $key => $name) {
1398
+				if (
1399
+					! isset($installed_message_types[$name])
1400
+					|| $message_resource_manager->has_message_type_been_activated_for_messenger(
1401
+						$name,
1402
+						$messenger_to_generate->name
1403
+					)
1404
+				) {
1405
+					unset($default_message_type_names_for_messenger[$key]);
1406
+				}
1407
+			}
1408
+			// in previous iterations, the active_messengers option in the db
1409
+			// needed updated before calling create templates. however with the changes this may not be necessary.
1410
+			// This comment is left here just in case we discover that we _do_ need to update before
1411
+			// passing off to create templates (after the refactor is done).
1412
+			// @todo remove this comment when determined not necessary.
1413
+			$message_resource_manager->activate_messenger(
1414
+				$messenger_to_generate->name,
1415
+				$default_message_type_names_for_messenger,
1416
+				false
1417
+			);
1418
+			//create any templates needing created (or will reactivate templates already generated as necessary).
1419
+			if ( ! empty($default_message_type_names_for_messenger)) {
1420
+				$templates_generated = EEH_MSG_Template::generate_new_templates(
1421
+					$messenger_to_generate->name,
1422
+					$default_message_type_names_for_messenger,
1423
+					'',
1424
+					true
1425
+				);
1426
+			}
1427
+		}
1428
+		return $templates_generated;
1429
+	}
1430
+
1431
+
1432
+	/**
1433
+	 * This returns the default messengers to generate templates for on activation of EE.
1434
+	 * It considers:
1435
+	 * - whether a messenger is already active in the db.
1436
+	 * - whether a messenger has been made active at any time in the past.
1437
+	 *
1438
+	 * @static
1439
+	 * @param  EE_Message_Resource_Manager $message_resource_manager
1440
+	 * @return EE_messenger[]
1441
+	 */
1442
+	protected static function _get_default_messengers_to_generate_on_activation(
1443
+		EE_Message_Resource_Manager $message_resource_manager
1444
+	) {
1445
+		$active_messengers    = $message_resource_manager->active_messengers();
1446
+		$installed_messengers = $message_resource_manager->installed_messengers();
1447
+		$has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1448
+
1449
+		$messengers_to_generate = array();
1450
+		foreach ($installed_messengers as $installed_messenger) {
1451
+			//if installed messenger is a messenger that should be activated on install
1452
+			//and is not already active
1453
+			//and has never been activated
1454
+			if (
1455
+				! $installed_messenger->activate_on_install
1456
+				|| isset($active_messengers[$installed_messenger->name])
1457
+				|| isset($has_activated[$installed_messenger->name])
1458
+			) {
1459
+				continue;
1460
+			}
1461
+			$messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1462
+		}
1463
+		return $messengers_to_generate;
1464
+	}
1465
+
1466
+
1467
+	/**
1468
+	 * This simply validates active message types to ensure they actually match installed
1469
+	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1470
+	 * rows are set inactive.
1471
+	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1472
+	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1473
+	 * are still handled in here.
1474
+	 *
1475
+	 * @since 4.3.1
1476
+	 * @return void
1477
+	 */
1478
+	public static function validate_messages_system()
1479
+	{
1480
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1481
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1482
+		$message_resource_manager->validate_active_message_types_are_installed();
1483
+		do_action('AHEE__EEH_Activation__validate_messages_system');
1484
+	}
1485
+
1486
+
1487
+	/**
1488
+	 * create_no_ticket_prices_array
1489
+	 *
1490
+	 * @access public
1491
+	 * @static
1492
+	 * @return void
1493
+	 */
1494
+	public static function create_no_ticket_prices_array()
1495
+	{
1496
+		// this creates an array for tracking events that have no active ticket prices created
1497
+		// this allows us to warn admins of the situation so that it can be corrected
1498
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1499
+		if (! $espresso_no_ticket_prices) {
1500
+			add_option('ee_no_ticket_prices', array(), '', false);
1501
+		}
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * plugin_deactivation
1507
+	 *
1508
+	 * @access public
1509
+	 * @static
1510
+	 * @return void
1511
+	 */
1512
+	public static function plugin_deactivation()
1513
+	{
1514
+	}
1515
+
1516
+
1517
+	/**
1518
+	 * Finds all our EE4 custom post types, and deletes them and their associated data
1519
+	 * (like post meta or term relations)
1520
+	 *
1521
+	 * @global wpdb $wpdb
1522
+	 * @throws \EE_Error
1523
+	 */
1524
+	public static function delete_all_espresso_cpt_data()
1525
+	{
1526
+		global $wpdb;
1527
+		//get all the CPT post_types
1528
+		$ee_post_types = array();
1529
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1530
+			if (method_exists($model_name, 'instance')) {
1531
+				$model_obj = call_user_func(array($model_name, 'instance'));
1532
+				if ($model_obj instanceof EEM_CPT_Base) {
1533
+					$ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1534
+				}
1535
+			}
1536
+		}
1537
+		//get all our CPTs
1538
+		$query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1539
+		$cpt_ids = $wpdb->get_col($query);
1540
+		//delete each post meta and term relations too
1541
+		foreach ($cpt_ids as $post_id) {
1542
+			wp_delete_post($post_id, true);
1543
+		}
1544
+	}
1545
+
1546
+	/**
1547
+	 * Deletes all EE custom tables
1548
+	 *
1549
+	 * @return array
1550
+	 */
1551
+	public static function drop_espresso_tables()
1552
+	{
1553
+		$tables = array();
1554
+		// load registry
1555
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1556
+			if (method_exists($model_name, 'instance')) {
1557
+				$model_obj = call_user_func(array($model_name, 'instance'));
1558
+				if ($model_obj instanceof EEM_Base) {
1559
+					foreach ($model_obj->get_tables() as $table) {
1560
+						if (strpos($table->get_table_name(), 'esp_')
1561
+							&&
1562
+							(
1563
+								is_main_site()//main site? nuke them all
1564
+								|| ! $table->is_global()//not main site,but not global either. nuke it
1565
+							)
1566
+						) {
1567
+							$tables[$table->get_table_name()] = $table->get_table_name();
1568
+						}
1569
+					}
1570
+				}
1571
+			}
1572
+		}
1573
+
1574
+		//there are some tables whose models were removed.
1575
+		//they should be removed when removing all EE core's data
1576
+		$tables_without_models = array(
1577
+			'esp_promotion',
1578
+			'esp_promotion_applied',
1579
+			'esp_promotion_object',
1580
+			'esp_promotion_rule',
1581
+			'esp_rule',
1582
+		);
1583
+		foreach ($tables_without_models as $table) {
1584
+			$tables[$table] = $table;
1585
+		}
1586
+		return \EEH_Activation::getTableManager()->dropTables($tables);
1587
+	}
1588
+
1589
+
1590
+
1591
+	/**
1592
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1593
+	 * each table name provided has a wpdb prefix attached, and that it exists.
1594
+	 * Returns the list actually deleted
1595
+	 *
1596
+	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1597
+	 * @global WPDB $wpdb
1598
+	 * @param array $table_names
1599
+	 * @return array of table names which we deleted
1600
+	 */
1601
+	public static function drop_tables($table_names)
1602
+	{
1603
+		return \EEH_Activation::getTableManager()->dropTables($table_names);
1604
+	}
1605
+
1606
+
1607
+
1608
+	/**
1609
+	 * plugin_uninstall
1610
+	 *
1611
+	 * @access public
1612
+	 * @static
1613
+	 * @param bool $remove_all
1614
+	 * @return void
1615
+	 */
1616
+	public static function delete_all_espresso_tables_and_data($remove_all = true)
1617
+	{
1618
+		global $wpdb;
1619
+		self::drop_espresso_tables();
1620
+		$wp_options_to_delete = array(
1621
+			'ee_no_ticket_prices'                => true,
1622
+			'ee_active_messengers'               => true,
1623
+			'ee_has_activated_messenger'         => true,
1624
+			'ee_flush_rewrite_rules'             => true,
1625
+			'ee_config'                          => false,
1626
+			'ee_data_migration_current_db_state' => true,
1627
+			'ee_data_migration_mapping_'         => false,
1628
+			'ee_data_migration_script_'          => false,
1629
+			'ee_data_migrations'                 => true,
1630
+			'ee_dms_map'                         => false,
1631
+			'ee_notices'                         => true,
1632
+			'lang_file_check_'                   => false,
1633
+			'ee_maintenance_mode'                => true,
1634
+			'ee_ueip_optin'                      => true,
1635
+			'ee_ueip_has_notified'               => true,
1636
+			'ee_plugin_activation_errors'        => true,
1637
+			'ee_id_mapping_from'                 => false,
1638
+			'espresso_persistent_admin_notices'  => true,
1639
+			'ee_encryption_key'                  => true,
1640
+			'pue_force_upgrade_'                 => false,
1641
+			'pue_json_error_'                    => false,
1642
+			'pue_install_key_'                   => false,
1643
+			'pue_verification_error_'            => false,
1644
+			'pu_dismissed_upgrade_'              => false,
1645
+			'external_updates-'                  => false,
1646
+			'ee_extra_data'                      => true,
1647
+			'ee_ssn_'                            => false,
1648
+			'ee_rss_'                            => false,
1649
+			'ee_rte_n_tx_'                       => false,
1650
+			'ee_pers_admin_notices'              => true,
1651
+			'ee_job_parameters_'                 => false,
1652
+			'ee_upload_directories_incomplete'   => true,
1653
+			'ee_verified_db_collations'          => true,
1654
+		);
1655
+		if (is_main_site()) {
1656
+			$wp_options_to_delete['ee_network_config'] = true;
1657
+		}
1658
+		$undeleted_options = array();
1659
+		foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1660
+			if ($no_wildcard) {
1661
+				if ( ! delete_option($option_name)) {
1662
+					$undeleted_options[] = $option_name;
1663
+				}
1664
+			} else {
1665
+				$option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1666
+				foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1667
+					if ( ! delete_option($option_name_from_wildcard)) {
1668
+						$undeleted_options[] = $option_name_from_wildcard;
1669
+					}
1670
+				}
1671
+			}
1672
+		}
1673
+		//also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1674
+		remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1675
+		if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1676
+			$db_update_sans_ee4 = array();
1677
+			foreach ($espresso_db_update as $version => $times_activated) {
1678
+				if ((string)$version[0] === '3') {//if its NON EE4
1679
+					$db_update_sans_ee4[$version] = $times_activated;
1680
+				}
1681
+			}
1682
+			update_option('espresso_db_update', $db_update_sans_ee4);
1683
+		}
1684
+		$errors = '';
1685
+		if ( ! empty($undeleted_options)) {
1686
+			$errors .= sprintf(
1687
+				__('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1688
+				'<br/>',
1689
+				implode(',<br/>', $undeleted_options)
1690
+			);
1691
+		}
1692
+		if ( ! empty($errors)) {
1693
+			EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1694
+		}
1695
+	}
1696
+
1697
+	/**
1698
+	 * Gets the mysql error code from the last used query by wpdb
1699
+	 *
1700
+	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1701
+	 */
1702
+	public static function last_wpdb_error_code()
1703
+	{
1704
+		global $wpdb;
1705
+		if ($wpdb->use_mysqli) {
1706
+			return mysqli_errno($wpdb->dbh);
1707
+		} else {
1708
+			return mysql_errno($wpdb->dbh);
1709
+		}
1710
+	}
1711
+
1712
+	/**
1713
+	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1714
+	 *
1715
+	 * @global wpdb  $wpdb
1716
+	 * @deprecated instead use TableAnalysis::tableExists()
1717
+	 * @param string $table_name with or without $wpdb->prefix
1718
+	 * @return boolean
1719
+	 */
1720
+	public static function table_exists($table_name)
1721
+	{
1722
+		return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1723
+	}
1724
+
1725
+	/**
1726
+	 * Resets the cache on EEH_Activation
1727
+	 */
1728
+	public static function reset()
1729
+	{
1730
+		self::$_default_creator_id                             = null;
1731
+		self::$_initialized_db_content_already_in_this_request = false;
1732
+	}
1733 1733
 }
1734 1734
 // End of file EEH_Activation.helper.php
1735 1735
 // Location: /helpers/EEH_Activation.core.php
Please login to merge, or discard this patch.
admin_pages/transactions/EE_Admin_Transactions_List_Table.class.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
      *
103 103
      * @abstract
104 104
      * @access protected
105
-     * @return array
105
+     * @return string[]
106 106
      */
107 107
     protected function _get_table_filters()
108 108
     {
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
      *    column_TXN_paid
266 266
      *
267 267
      * @param \EE_Transaction $transaction
268
-     * @return mixed|string
268
+     * @return string
269 269
      * @throws \EE_Error
270 270
      */
271 271
     public function column_TXN_paid(EE_Transaction $transaction)
Please login to merge, or discard this patch.
Indentation   +606 added lines, -606 removed lines patch added patch discarded remove patch
@@ -13,114 +13,114 @@  discard block
 block discarded – undo
13 13
 class EE_Admin_Transactions_List_Table extends EE_Admin_List_Table
14 14
 {
15 15
 
16
-    private $_status;
17
-
18
-
19
-    /**
20
-     * @param \Transactions_Admin_Page $admin_page
21
-     */
22
-    public function __construct(\Transactions_Admin_Page $admin_page)
23
-    {
24
-        parent::__construct($admin_page);
25
-        $this->_status = $this->_admin_page->get_transaction_status_array();
26
-    }
27
-
28
-
29
-    /**
30
-     *_setup_data
31
-     */
32
-    protected function _setup_data()
33
-    {
34
-        $this->_data           = $this->_admin_page->get_transactions($this->_per_page);
35
-        $status                = ! empty($this->_req_data['status']) ? $this->_req_data['status'] : 'all';
36
-        $this->_all_data_count = $this->_admin_page->get_transactions($this->_per_page, true, $status);
37
-    }
38
-
39
-
40
-    /**
41
-     *_set_properties
42
-     */
43
-    protected function _set_properties()
44
-    {
45
-        $this->_wp_list_args = array(
46
-            'singular' => __('transaction', 'event_espresso'),
47
-            'plural'   => __('transactions', 'event_espresso'),
48
-            'ajax'     => true,
49
-            'screen'   => $this->_admin_page->get_current_screen()->id,
50
-        );
51
-        $ID_column_name      = __('ID', 'event_espresso');
52
-        $ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
53
-        $ID_column_name      .= __('Transaction Date', 'event_espresso');
54
-        $ID_column_name      .= '</span> ';
55
-        $this->_columns      = array(
56
-            'TXN_ID'        => $ID_column_name,
57
-            'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
58
-            'TXN_total'     => __('Total', 'event_espresso'),
59
-            'TXN_paid'      => __('Paid', 'event_espresso'),
60
-            'ATT_fname'     => __('Primary Registrant', 'event_espresso'),
61
-            'event_name'    => __('Event', 'event_espresso'),
62
-            'actions'       => __('Actions', 'event_espresso'),
63
-        );
64
-
65
-        $this->_sortable_columns = array(
66
-            'TXN_ID'        => array('TXN_ID' => false),
67
-            'event_name'    => array('event_name' => false),
68
-            'ATT_fname'     => array('ATT_fname' => false),
69
-            'TXN_timestamp' => array('TXN_timestamp' => true) //true means its already sorted
70
-        );
71
-
72
-        $this->_primary_column = 'TXN_ID';
73
-
74
-        $this->_hidden_columns = array();
75
-    }
76
-
77
-
78
-    /**
79
-     * This simply sets up the row class for the table rows.
80
-     * Allows for easier overriding of child methods for setting up sorting.
81
-     *
82
-     * @param  EE_Transaction $transaction the current item
83
-     * @return string
84
-     * @throws \EE_Error
85
-     */
86
-    protected function _get_row_class($transaction)
87
-    {
88
-        $class = parent::_get_row_class($transaction);
89
-        //add status class
90
-        $class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
91
-        if ($this->_has_checkbox_column) {
92
-            $class .= ' has-checkbox-column';
93
-        }
94
-        return $class;
95
-    }
96
-
97
-
98
-    /**
99
-     * _get_table_filters
100
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
101
-     * get's shown in the table.
102
-     *
103
-     * @abstract
104
-     * @access protected
105
-     * @return array
106
-     */
107
-    protected function _get_table_filters()
108
-    {
109
-        $filters    = array();
110
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
111
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
112
-            : date(
113
-                'm/d/Y',
114
-                strtotime('-10 year')
115
-            );
116
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
117
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
118
-            : date(
119
-                'm/d/Y',
120
-                current_time('timestamp')
121
-            );
122
-        ob_start();
123
-        ?>
16
+	private $_status;
17
+
18
+
19
+	/**
20
+	 * @param \Transactions_Admin_Page $admin_page
21
+	 */
22
+	public function __construct(\Transactions_Admin_Page $admin_page)
23
+	{
24
+		parent::__construct($admin_page);
25
+		$this->_status = $this->_admin_page->get_transaction_status_array();
26
+	}
27
+
28
+
29
+	/**
30
+	 *_setup_data
31
+	 */
32
+	protected function _setup_data()
33
+	{
34
+		$this->_data           = $this->_admin_page->get_transactions($this->_per_page);
35
+		$status                = ! empty($this->_req_data['status']) ? $this->_req_data['status'] : 'all';
36
+		$this->_all_data_count = $this->_admin_page->get_transactions($this->_per_page, true, $status);
37
+	}
38
+
39
+
40
+	/**
41
+	 *_set_properties
42
+	 */
43
+	protected function _set_properties()
44
+	{
45
+		$this->_wp_list_args = array(
46
+			'singular' => __('transaction', 'event_espresso'),
47
+			'plural'   => __('transactions', 'event_espresso'),
48
+			'ajax'     => true,
49
+			'screen'   => $this->_admin_page->get_current_screen()->id,
50
+		);
51
+		$ID_column_name      = __('ID', 'event_espresso');
52
+		$ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
53
+		$ID_column_name      .= __('Transaction Date', 'event_espresso');
54
+		$ID_column_name      .= '</span> ';
55
+		$this->_columns      = array(
56
+			'TXN_ID'        => $ID_column_name,
57
+			'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
58
+			'TXN_total'     => __('Total', 'event_espresso'),
59
+			'TXN_paid'      => __('Paid', 'event_espresso'),
60
+			'ATT_fname'     => __('Primary Registrant', 'event_espresso'),
61
+			'event_name'    => __('Event', 'event_espresso'),
62
+			'actions'       => __('Actions', 'event_espresso'),
63
+		);
64
+
65
+		$this->_sortable_columns = array(
66
+			'TXN_ID'        => array('TXN_ID' => false),
67
+			'event_name'    => array('event_name' => false),
68
+			'ATT_fname'     => array('ATT_fname' => false),
69
+			'TXN_timestamp' => array('TXN_timestamp' => true) //true means its already sorted
70
+		);
71
+
72
+		$this->_primary_column = 'TXN_ID';
73
+
74
+		$this->_hidden_columns = array();
75
+	}
76
+
77
+
78
+	/**
79
+	 * This simply sets up the row class for the table rows.
80
+	 * Allows for easier overriding of child methods for setting up sorting.
81
+	 *
82
+	 * @param  EE_Transaction $transaction the current item
83
+	 * @return string
84
+	 * @throws \EE_Error
85
+	 */
86
+	protected function _get_row_class($transaction)
87
+	{
88
+		$class = parent::_get_row_class($transaction);
89
+		//add status class
90
+		$class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
91
+		if ($this->_has_checkbox_column) {
92
+			$class .= ' has-checkbox-column';
93
+		}
94
+		return $class;
95
+	}
96
+
97
+
98
+	/**
99
+	 * _get_table_filters
100
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
101
+	 * get's shown in the table.
102
+	 *
103
+	 * @abstract
104
+	 * @access protected
105
+	 * @return array
106
+	 */
107
+	protected function _get_table_filters()
108
+	{
109
+		$filters    = array();
110
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
111
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
112
+			: date(
113
+				'm/d/Y',
114
+				strtotime('-10 year')
115
+			);
116
+		$end_date   = isset($this->_req_data['txn-filter-end-date'])
117
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
118
+			: date(
119
+				'm/d/Y',
120
+				current_time('timestamp')
121
+			);
122
+		ob_start();
123
+		?>
124 124
         <label for="txn-filter-start-date">Display Transactions from </label>
125 125
         <input id="txn-filter-start-date" class="datepicker" type="text" value="<?php echo $start_date; ?>"
126 126
                name="txn-filter-start-date" size="15"/>
@@ -128,534 +128,534 @@  discard block
 block discarded – undo
128 128
         <input id="txn-filter-end-date" class="datepicker" type="text" value="<?php echo $end_date; ?>"
129 129
                name="txn-filter-end-date" size="15"/>
130 130
         <?php
131
-        $filters[] = ob_get_contents();
132
-        ob_end_clean();
133
-        return $filters;
134
-    }
135
-
136
-
137
-    /**
138
-     *_add_view_counts
139
-     */
140
-    protected function _add_view_counts()
141
-    {
142
-        $this->_views['all']['count']       = $this->_admin_page->get_transactions($this->_per_page, true, 'all');
143
-        $this->_views['abandoned']['count'] = $this->_admin_page->get_transactions($this->_per_page, true, 'abandoned');
144
-        $this->_views['failed']['count']    = $this->_admin_page->get_transactions($this->_per_page, true, 'failed');
145
-    }
146
-
147
-
148
-    /**
149
-     *    column TXN_ID
150
-     *
151
-     * @param \EE_Transaction $transaction
152
-     * @return string
153
-     * @throws \EE_Error
154
-     */
155
-    public function column_TXN_ID(EE_Transaction $transaction)
156
-    {
157
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
158
-            'action' => 'view_transaction',
159
-            'TXN_ID' => $transaction->ID(),
160
-        ), TXN_ADMIN_URL);
161
-        $content      = '<a href="' . $view_lnk_url . '"'
162
-                        . ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
163
-                        . $transaction->ID()
164
-                        . '</a>';
165
-
166
-        //txn timestamp
167
-        $content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
168
-        return $content;
169
-    }
170
-
171
-
172
-    /**
173
-     * @param \EE_Transaction $transaction
174
-     * @return string
175
-     * @throws \EE_Error
176
-     */
177
-    protected function _get_txn_timestamp(EE_Transaction $transaction)
178
-    {
179
-        //txn timestamp
180
-        // is TXN less than 2 hours old ?
181
-        if (($transaction->failed() || $transaction->is_abandoned())
182
-            && (
183
-                (time() - EE_Registry::instance()->SSN->lifespan()) < $transaction->datetime(false, true)
184
-            )
185
-        ) {
186
-            $timestamp = esc_html__('TXN in progress...', 'event_espresso');
187
-        } else {
188
-            $timestamp = $transaction->get_i18n_datetime('TXN_timestamp');
189
-        }
190
-        return $timestamp;
191
-    }
192
-
193
-
194
-    /**
195
-     *    column_cb
196
-     *
197
-     * @param \EE_Transaction $transaction
198
-     * @return string
199
-     * @throws \EE_Error
200
-     */
201
-    public function column_cb($transaction)
202
-    {
203
-        return sprintf(
204
-            '<input type="checkbox" name="%1$s[]" value="%2$s" />',
205
-            $this->_wp_list_args['singular'],
206
-            $transaction->ID()
207
-        );
208
-    }
209
-
210
-
211
-    /**
212
-     *    column_TXN_timestamp
213
-     *
214
-     * @param \EE_Transaction $transaction
215
-     * @return string
216
-     * @throws \EE_Error
217
-     */
218
-    public function column_TXN_timestamp(EE_Transaction $transaction)
219
-    {
220
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
221
-            'action' => 'view_transaction',
222
-            'TXN_ID' => $transaction->ID(),
223
-        ), TXN_ADMIN_URL);
224
-        $txn_date     = '<a href="' . $view_lnk_url . '"'
225
-                        . ' title="'
226
-                        . esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
227
-                        . $this->_get_txn_timestamp($transaction)
228
-                        . '</a>';
229
-        //status
230
-        $txn_date .= '<br><span class="ee-status-text-small">'
231
-                     . EEH_Template::pretty_status(
232
-                         $transaction->status_ID(),
233
-                         false,
234
-                         'sentence'
235
-                     )
236
-                     . '</span>';
237
-        return $txn_date;
238
-    }
239
-
240
-
241
-    /**
242
-     *    column_TXN_total
243
-     *
244
-     * @param \EE_Transaction $transaction
245
-     * @return string
246
-     * @throws \EE_Error
247
-     */
248
-    public function column_TXN_total(EE_Transaction $transaction)
249
-    {
250
-        if ($transaction->get('TXN_total') > 0) {
251
-            return '<span class="txn-pad-rght">'
252
-                   . apply_filters(
253
-                       'FHEE__EE_Admin_Transactions_List_Table__column_TXN_total__TXN_total',
254
-                       $transaction->get_pretty('TXN_total'),
255
-                       $transaction
256
-                   )
257
-                   . '</span>';
258
-        } else {
259
-            return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
260
-        }
261
-    }
262
-
263
-
264
-    /**
265
-     *    column_TXN_paid
266
-     *
267
-     * @param \EE_Transaction $transaction
268
-     * @return mixed|string
269
-     * @throws \EE_Error
270
-     */
271
-    public function column_TXN_paid(EE_Transaction $transaction)
272
-    {
273
-        $transaction_total = $transaction->get('TXN_total');
274
-        $transaction_paid  = $transaction->get('TXN_paid');
275
-
276
-        if (\EEH_Money::compare_floats($transaction_total, 0, '>')) {
277
-            // monies owing
278
-            $span_class = 'txn-overview-part-payment-spn';
279
-            if (\EEH_Money::compare_floats($transaction_paid, $transaction_total, '>=')) {
280
-                // paid in full
281
-                $span_class = 'txn-overview-full-payment-spn';
282
-            } elseif (\EEH_Money::compare_floats($transaction_paid, 0, '==')) {
283
-                // no payments made
284
-                $span_class = 'txn-overview-no-payment-spn';
285
-            }
286
-        } else {
287
-            $span_class       = 'txn-overview-free-event-spn';
288
-            $transaction_paid = 0;
289
-        }
290
-
291
-        $payment_method      = $transaction->payment_method();
292
-        $payment_method_name = $payment_method instanceof EE_Payment_Method
293
-            ? $payment_method->admin_name()
294
-            : esc_html__('Unknown', 'event_espresso');
295
-        $transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
296
-
297
-        $content = '<span class="' . $span_class . ' txn-pad-rght">'
298
-                   . $transaction_paid_content
299
-                   . '</span>';
300
-        if ($transaction_paid > 0) {
301
-            $content .= '<br><span class="ee-status-text-small">'
302
-                        . sprintf(
303
-                            esc_html__('...via %s', 'event_espresso'),
304
-                            $payment_method_name
305
-                        )
306
-                        . '</span>';
307
-        }
308
-        return $content;
309
-    }
310
-
311
-
312
-    /**
313
-     *    column_ATT_fname
314
-     *
315
-     * @param \EE_Transaction $transaction
316
-     * @return string
317
-     * @throws \EE_Error
318
-     */
319
-    public function column_ATT_fname(EE_Transaction $transaction)
320
-    {
321
-        $primary_reg = $transaction->primary_registration();
322
-        $attendee    = $primary_reg->get_first_related('Attendee');
323
-        if ($attendee instanceof EE_Attendee) {
324
-            $edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
325
-                'action'  => 'view_registration',
326
-                '_REG_ID' => $primary_reg->ID(),
327
-            ), REG_ADMIN_URL);
328
-            $content      = EE_Registry::instance()->CAP->current_user_can(
329
-                'ee_read_registration',
330
-                'espresso_registrations_view_registration',
331
-                $primary_reg->ID()
332
-            )
333
-                ? '<a href="' . $edit_lnk_url . '"'
334
-                    . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
335
-                    . $attendee->full_name()
336
-                    . '</a>'
337
-                : $attendee->full_name();
338
-            $content      .= '<br>' . $attendee->email();
339
-            return $content;
340
-        }
341
-        return $transaction->failed() || $transaction->is_abandoned()
342
-            ? esc_html__('no contact record.', 'event_espresso')
343
-            : esc_html__(
344
-                'No contact record, because the transaction was abandoned or the registration process failed.',
345
-                'event_espresso'
346
-            );
347
-    }
348
-
349
-
350
-    /**
351
-     *    column_ATT_email
352
-     *
353
-     * @param \EE_Transaction $transaction
354
-     * @return string
355
-     * @throws \EE_Error
356
-     */
357
-    public function column_ATT_email(EE_Transaction $transaction)
358
-    {
359
-        $attendee = $transaction->primary_registration()->get_first_related('Attendee');
360
-        if (! empty($attendee)) {
361
-            return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
362
-                   . $attendee->get('ATT_email')
363
-                   . '</a>';
364
-        } else {
365
-            return $transaction->failed() || $transaction->is_abandoned()
366
-                ? esc_html__('no contact record.', 'event_espresso')
367
-                : esc_html__(
368
-                    'No contact record, because the transaction was abandoned or the registration process failed.',
369
-                    'event_espresso'
370
-                );
371
-        }
372
-    }
373
-
374
-
375
-    /**
376
-     *    column_event_name
377
-     *
378
-     * @param \EE_Transaction $transaction
379
-     * @return string
380
-     * @throws \EE_Error
381
-     */
382
-    public function column_event_name(EE_Transaction $transaction)
383
-    {
384
-        $actions = array();
385
-        $event   = $transaction->primary_registration()->get_first_related('Event');
386
-        if (! empty($event)) {
387
-            $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
388
-                array('action' => 'edit', 'post' => $event->ID()),
389
-                EVENTS_ADMIN_URL
390
-            );
391
-            $event_name     = $event->get('EVT_name');
392
-
393
-            //filter this view by transactions for this event
394
-            $txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
395
-                'action' => 'default',
396
-                'EVT_ID' => $event->ID(),
397
-            ));
398
-            if (EE_Registry::instance()->CAP->current_user_can(
399
-                'ee_edit_event',
400
-                'espresso_events_edit',
401
-                $event->ID()
402
-            )) {
403
-                $actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
404
-                        . ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
405
-                        . esc_html__('View Transactions for this event', 'event_espresso')
406
-                        . '</a>';
407
-            }
408
-
409
-            return sprintf(
410
-                '%1$s %2$s',
411
-                EE_Registry::instance()->CAP->current_user_can(
412
-                    'ee_edit_event',
413
-                    'espresso_events_edit',
414
-                    $event->ID()
415
-                )
416
-                    ? '<a href="' . $edit_event_url . '"'
417
-                        . ' title="'
418
-                        . sprintf(
419
-                            esc_attr__('Edit Event: %s', 'event_espresso'),
420
-                            $event->get('EVT_name')
421
-                        )
422
-                        . '">'
423
-                        . wp_trim_words(
424
-                            $event_name,
425
-                            30,
426
-                            '...'
427
-                        )
428
-                        . '</a>'
429
-                        : wp_trim_words($event_name, 30, '...'),
430
-                $this->row_actions($actions)
431
-            );
432
-        } else {
433
-            return esc_html__(
434
-                'The event associated with this transaction via the primary registration cannot be retrieved.',
435
-                'event_espresso'
436
-            );
437
-        }
438
-    }
439
-
440
-
441
-    /**
442
-     *    column_actions
443
-     *
444
-     * @param \EE_Transaction $transaction
445
-     * @return string
446
-     * @throws \EE_Error
447
-     */
448
-    public function column_actions(EE_Transaction $transaction)
449
-    {
450
-        return $this->_action_string(
451
-            $this->get_transaction_details_link($transaction)
452
-            . $this->get_invoice_link($transaction)
453
-            . $this->get_receipt_link($transaction)
454
-            . $this->get_primary_registration_details_link($transaction)
455
-            . $this->get_send_payment_reminder_trigger_link($transaction)
456
-            . $this->get_payment_overview_link($transaction)
457
-            . $this->get_related_messages_link($transaction),
458
-            $transaction,
459
-            'ul',
460
-            'txn-overview-actions-ul'
461
-        );
462
-    }
463
-
464
-
465
-    /**
466
-     * Get the transaction details link.
467
-     * @param EE_Transaction $transaction
468
-     * @return string
469
-     * @throws EE_Error
470
-     */
471
-    protected function get_transaction_details_link(EE_Transaction $transaction)
472
-    {
473
-        $url          = EE_Admin_Page::add_query_args_and_nonce(array(
474
-            'action' => 'view_transaction',
475
-            'TXN_ID' => $transaction->ID(),
476
-        ), TXN_ADMIN_URL);
477
-        return '
131
+		$filters[] = ob_get_contents();
132
+		ob_end_clean();
133
+		return $filters;
134
+	}
135
+
136
+
137
+	/**
138
+	 *_add_view_counts
139
+	 */
140
+	protected function _add_view_counts()
141
+	{
142
+		$this->_views['all']['count']       = $this->_admin_page->get_transactions($this->_per_page, true, 'all');
143
+		$this->_views['abandoned']['count'] = $this->_admin_page->get_transactions($this->_per_page, true, 'abandoned');
144
+		$this->_views['failed']['count']    = $this->_admin_page->get_transactions($this->_per_page, true, 'failed');
145
+	}
146
+
147
+
148
+	/**
149
+	 *    column TXN_ID
150
+	 *
151
+	 * @param \EE_Transaction $transaction
152
+	 * @return string
153
+	 * @throws \EE_Error
154
+	 */
155
+	public function column_TXN_ID(EE_Transaction $transaction)
156
+	{
157
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
158
+			'action' => 'view_transaction',
159
+			'TXN_ID' => $transaction->ID(),
160
+		), TXN_ADMIN_URL);
161
+		$content      = '<a href="' . $view_lnk_url . '"'
162
+						. ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
163
+						. $transaction->ID()
164
+						. '</a>';
165
+
166
+		//txn timestamp
167
+		$content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
168
+		return $content;
169
+	}
170
+
171
+
172
+	/**
173
+	 * @param \EE_Transaction $transaction
174
+	 * @return string
175
+	 * @throws \EE_Error
176
+	 */
177
+	protected function _get_txn_timestamp(EE_Transaction $transaction)
178
+	{
179
+		//txn timestamp
180
+		// is TXN less than 2 hours old ?
181
+		if (($transaction->failed() || $transaction->is_abandoned())
182
+			&& (
183
+				(time() - EE_Registry::instance()->SSN->lifespan()) < $transaction->datetime(false, true)
184
+			)
185
+		) {
186
+			$timestamp = esc_html__('TXN in progress...', 'event_espresso');
187
+		} else {
188
+			$timestamp = $transaction->get_i18n_datetime('TXN_timestamp');
189
+		}
190
+		return $timestamp;
191
+	}
192
+
193
+
194
+	/**
195
+	 *    column_cb
196
+	 *
197
+	 * @param \EE_Transaction $transaction
198
+	 * @return string
199
+	 * @throws \EE_Error
200
+	 */
201
+	public function column_cb($transaction)
202
+	{
203
+		return sprintf(
204
+			'<input type="checkbox" name="%1$s[]" value="%2$s" />',
205
+			$this->_wp_list_args['singular'],
206
+			$transaction->ID()
207
+		);
208
+	}
209
+
210
+
211
+	/**
212
+	 *    column_TXN_timestamp
213
+	 *
214
+	 * @param \EE_Transaction $transaction
215
+	 * @return string
216
+	 * @throws \EE_Error
217
+	 */
218
+	public function column_TXN_timestamp(EE_Transaction $transaction)
219
+	{
220
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
221
+			'action' => 'view_transaction',
222
+			'TXN_ID' => $transaction->ID(),
223
+		), TXN_ADMIN_URL);
224
+		$txn_date     = '<a href="' . $view_lnk_url . '"'
225
+						. ' title="'
226
+						. esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
227
+						. $this->_get_txn_timestamp($transaction)
228
+						. '</a>';
229
+		//status
230
+		$txn_date .= '<br><span class="ee-status-text-small">'
231
+					 . EEH_Template::pretty_status(
232
+						 $transaction->status_ID(),
233
+						 false,
234
+						 'sentence'
235
+					 )
236
+					 . '</span>';
237
+		return $txn_date;
238
+	}
239
+
240
+
241
+	/**
242
+	 *    column_TXN_total
243
+	 *
244
+	 * @param \EE_Transaction $transaction
245
+	 * @return string
246
+	 * @throws \EE_Error
247
+	 */
248
+	public function column_TXN_total(EE_Transaction $transaction)
249
+	{
250
+		if ($transaction->get('TXN_total') > 0) {
251
+			return '<span class="txn-pad-rght">'
252
+				   . apply_filters(
253
+					   'FHEE__EE_Admin_Transactions_List_Table__column_TXN_total__TXN_total',
254
+					   $transaction->get_pretty('TXN_total'),
255
+					   $transaction
256
+				   )
257
+				   . '</span>';
258
+		} else {
259
+			return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
260
+		}
261
+	}
262
+
263
+
264
+	/**
265
+	 *    column_TXN_paid
266
+	 *
267
+	 * @param \EE_Transaction $transaction
268
+	 * @return mixed|string
269
+	 * @throws \EE_Error
270
+	 */
271
+	public function column_TXN_paid(EE_Transaction $transaction)
272
+	{
273
+		$transaction_total = $transaction->get('TXN_total');
274
+		$transaction_paid  = $transaction->get('TXN_paid');
275
+
276
+		if (\EEH_Money::compare_floats($transaction_total, 0, '>')) {
277
+			// monies owing
278
+			$span_class = 'txn-overview-part-payment-spn';
279
+			if (\EEH_Money::compare_floats($transaction_paid, $transaction_total, '>=')) {
280
+				// paid in full
281
+				$span_class = 'txn-overview-full-payment-spn';
282
+			} elseif (\EEH_Money::compare_floats($transaction_paid, 0, '==')) {
283
+				// no payments made
284
+				$span_class = 'txn-overview-no-payment-spn';
285
+			}
286
+		} else {
287
+			$span_class       = 'txn-overview-free-event-spn';
288
+			$transaction_paid = 0;
289
+		}
290
+
291
+		$payment_method      = $transaction->payment_method();
292
+		$payment_method_name = $payment_method instanceof EE_Payment_Method
293
+			? $payment_method->admin_name()
294
+			: esc_html__('Unknown', 'event_espresso');
295
+		$transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
296
+
297
+		$content = '<span class="' . $span_class . ' txn-pad-rght">'
298
+				   . $transaction_paid_content
299
+				   . '</span>';
300
+		if ($transaction_paid > 0) {
301
+			$content .= '<br><span class="ee-status-text-small">'
302
+						. sprintf(
303
+							esc_html__('...via %s', 'event_espresso'),
304
+							$payment_method_name
305
+						)
306
+						. '</span>';
307
+		}
308
+		return $content;
309
+	}
310
+
311
+
312
+	/**
313
+	 *    column_ATT_fname
314
+	 *
315
+	 * @param \EE_Transaction $transaction
316
+	 * @return string
317
+	 * @throws \EE_Error
318
+	 */
319
+	public function column_ATT_fname(EE_Transaction $transaction)
320
+	{
321
+		$primary_reg = $transaction->primary_registration();
322
+		$attendee    = $primary_reg->get_first_related('Attendee');
323
+		if ($attendee instanceof EE_Attendee) {
324
+			$edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
325
+				'action'  => 'view_registration',
326
+				'_REG_ID' => $primary_reg->ID(),
327
+			), REG_ADMIN_URL);
328
+			$content      = EE_Registry::instance()->CAP->current_user_can(
329
+				'ee_read_registration',
330
+				'espresso_registrations_view_registration',
331
+				$primary_reg->ID()
332
+			)
333
+				? '<a href="' . $edit_lnk_url . '"'
334
+					. ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
335
+					. $attendee->full_name()
336
+					. '</a>'
337
+				: $attendee->full_name();
338
+			$content      .= '<br>' . $attendee->email();
339
+			return $content;
340
+		}
341
+		return $transaction->failed() || $transaction->is_abandoned()
342
+			? esc_html__('no contact record.', 'event_espresso')
343
+			: esc_html__(
344
+				'No contact record, because the transaction was abandoned or the registration process failed.',
345
+				'event_espresso'
346
+			);
347
+	}
348
+
349
+
350
+	/**
351
+	 *    column_ATT_email
352
+	 *
353
+	 * @param \EE_Transaction $transaction
354
+	 * @return string
355
+	 * @throws \EE_Error
356
+	 */
357
+	public function column_ATT_email(EE_Transaction $transaction)
358
+	{
359
+		$attendee = $transaction->primary_registration()->get_first_related('Attendee');
360
+		if (! empty($attendee)) {
361
+			return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
362
+				   . $attendee->get('ATT_email')
363
+				   . '</a>';
364
+		} else {
365
+			return $transaction->failed() || $transaction->is_abandoned()
366
+				? esc_html__('no contact record.', 'event_espresso')
367
+				: esc_html__(
368
+					'No contact record, because the transaction was abandoned or the registration process failed.',
369
+					'event_espresso'
370
+				);
371
+		}
372
+	}
373
+
374
+
375
+	/**
376
+	 *    column_event_name
377
+	 *
378
+	 * @param \EE_Transaction $transaction
379
+	 * @return string
380
+	 * @throws \EE_Error
381
+	 */
382
+	public function column_event_name(EE_Transaction $transaction)
383
+	{
384
+		$actions = array();
385
+		$event   = $transaction->primary_registration()->get_first_related('Event');
386
+		if (! empty($event)) {
387
+			$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
388
+				array('action' => 'edit', 'post' => $event->ID()),
389
+				EVENTS_ADMIN_URL
390
+			);
391
+			$event_name     = $event->get('EVT_name');
392
+
393
+			//filter this view by transactions for this event
394
+			$txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
395
+				'action' => 'default',
396
+				'EVT_ID' => $event->ID(),
397
+			));
398
+			if (EE_Registry::instance()->CAP->current_user_can(
399
+				'ee_edit_event',
400
+				'espresso_events_edit',
401
+				$event->ID()
402
+			)) {
403
+				$actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
404
+						. ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
405
+						. esc_html__('View Transactions for this event', 'event_espresso')
406
+						. '</a>';
407
+			}
408
+
409
+			return sprintf(
410
+				'%1$s %2$s',
411
+				EE_Registry::instance()->CAP->current_user_can(
412
+					'ee_edit_event',
413
+					'espresso_events_edit',
414
+					$event->ID()
415
+				)
416
+					? '<a href="' . $edit_event_url . '"'
417
+						. ' title="'
418
+						. sprintf(
419
+							esc_attr__('Edit Event: %s', 'event_espresso'),
420
+							$event->get('EVT_name')
421
+						)
422
+						. '">'
423
+						. wp_trim_words(
424
+							$event_name,
425
+							30,
426
+							'...'
427
+						)
428
+						. '</a>'
429
+						: wp_trim_words($event_name, 30, '...'),
430
+				$this->row_actions($actions)
431
+			);
432
+		} else {
433
+			return esc_html__(
434
+				'The event associated with this transaction via the primary registration cannot be retrieved.',
435
+				'event_espresso'
436
+			);
437
+		}
438
+	}
439
+
440
+
441
+	/**
442
+	 *    column_actions
443
+	 *
444
+	 * @param \EE_Transaction $transaction
445
+	 * @return string
446
+	 * @throws \EE_Error
447
+	 */
448
+	public function column_actions(EE_Transaction $transaction)
449
+	{
450
+		return $this->_action_string(
451
+			$this->get_transaction_details_link($transaction)
452
+			. $this->get_invoice_link($transaction)
453
+			. $this->get_receipt_link($transaction)
454
+			. $this->get_primary_registration_details_link($transaction)
455
+			. $this->get_send_payment_reminder_trigger_link($transaction)
456
+			. $this->get_payment_overview_link($transaction)
457
+			. $this->get_related_messages_link($transaction),
458
+			$transaction,
459
+			'ul',
460
+			'txn-overview-actions-ul'
461
+		);
462
+	}
463
+
464
+
465
+	/**
466
+	 * Get the transaction details link.
467
+	 * @param EE_Transaction $transaction
468
+	 * @return string
469
+	 * @throws EE_Error
470
+	 */
471
+	protected function get_transaction_details_link(EE_Transaction $transaction)
472
+	{
473
+		$url          = EE_Admin_Page::add_query_args_and_nonce(array(
474
+			'action' => 'view_transaction',
475
+			'TXN_ID' => $transaction->ID(),
476
+		), TXN_ADMIN_URL);
477
+		return '
478 478
 			<li>
479 479
 				<a href="' . $url . '"'
480
-                    . ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
480
+					. ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
481 481
 					<span class="dashicons dashicons-cart"></span>
482 482
 				</a>
483 483
 			</li>';
484
-    }
485
-
486
-
487
-    /**
488
-     * Get the invoice link for the given registration.
489
-     * @param EE_Transaction $transaction
490
-     * @return string
491
-     * @throws EE_Error
492
-     */
493
-    protected function get_invoice_link(EE_Transaction $transaction)
494
-    {
495
-        $registration = $transaction->primary_registration();
496
-        if ($registration instanceof EE_Registration) {
497
-            $url = $registration->invoice_url();
498
-            //only show invoice link if message type is active.
499
-            if ($registration->attendee() instanceof EE_Attendee
500
-                && EEH_MSG_Template::is_mt_active('invoice')
501
-            ) {
502
-                return '
484
+	}
485
+
486
+
487
+	/**
488
+	 * Get the invoice link for the given registration.
489
+	 * @param EE_Transaction $transaction
490
+	 * @return string
491
+	 * @throws EE_Error
492
+	 */
493
+	protected function get_invoice_link(EE_Transaction $transaction)
494
+	{
495
+		$registration = $transaction->primary_registration();
496
+		if ($registration instanceof EE_Registration) {
497
+			$url = $registration->invoice_url();
498
+			//only show invoice link if message type is active.
499
+			if ($registration->attendee() instanceof EE_Attendee
500
+				&& EEH_MSG_Template::is_mt_active('invoice')
501
+			) {
502
+				return '
503 503
                 <li>
504 504
                     <a title="' . esc_attr__('View Transaction Invoice', 'event_espresso') . '"'
505
-                       . ' target="_blank" href="' . $url . '" class="tiny-text">
505
+					   . ' target="_blank" href="' . $url . '" class="tiny-text">
506 506
                         <span class="dashicons dashicons-media-spreadsheet ee-icon-size-18"></span>
507 507
                     </a>
508 508
                 </li>';
509
-            }
510
-        }
511
-        return '';
512
-    }
513
-
514
-
515
-    /**
516
-     * Get the receipt link for the transaction.
517
-     * @param EE_Transaction $transaction
518
-     * @return string
519
-     * @throws EE_Error
520
-     */
521
-    protected function get_receipt_link(EE_Transaction $transaction)
522
-    {
523
-        $registration = $transaction->primary_registration();
524
-        if ($registration instanceof EE_Registration) {
525
-            $url = $registration->receipt_url();
526
-            //only show receipt link if message type is active.
527
-            if ($registration->attendee() instanceof EE_Attendee
528
-                && EEH_MSG_Template::is_mt_active('receipt')) {
529
-                return '
509
+			}
510
+		}
511
+		return '';
512
+	}
513
+
514
+
515
+	/**
516
+	 * Get the receipt link for the transaction.
517
+	 * @param EE_Transaction $transaction
518
+	 * @return string
519
+	 * @throws EE_Error
520
+	 */
521
+	protected function get_receipt_link(EE_Transaction $transaction)
522
+	{
523
+		$registration = $transaction->primary_registration();
524
+		if ($registration instanceof EE_Registration) {
525
+			$url = $registration->receipt_url();
526
+			//only show receipt link if message type is active.
527
+			if ($registration->attendee() instanceof EE_Attendee
528
+				&& EEH_MSG_Template::is_mt_active('receipt')) {
529
+				return '
530 530
 			<li>
531 531
 				<a title="' . esc_attr__('View Transaction Receipt', 'event_espresso') . '"'
532
-                                  . ' target="_blank" href="' . $url . '" class="tiny-text">
532
+								  . ' target="_blank" href="' . $url . '" class="tiny-text">
533 533
 					<span class="dashicons dashicons-media-default ee-icon-size-18"></span>
534 534
 				</a>
535 535
 			</li>';
536
-            }
537
-        }
538
-        return '';
539
-    }
540
-
541
-
542
-    /**
543
-     * Get the link to view the details for the primary registration.
544
-     * @param EE_Transaction $transaction
545
-     * @return string
546
-     * @throws EE_Error
547
-     */
548
-    protected function get_primary_registration_details_link(EE_Transaction $transaction)
549
-    {
550
-        $registration = $transaction->primary_registration();
551
-        if ($registration instanceof EE_Registration) {
552
-            $url      = EE_Admin_Page::add_query_args_and_nonce(array(
553
-                'action'  => 'view_registration',
554
-                '_REG_ID' => $registration->ID(),
555
-            ), REG_ADMIN_URL);
556
-            return EE_Registry::instance()->CAP->current_user_can(
557
-                'ee_read_registration',
558
-                'espresso_registrations_view_registration',
559
-                $registration->ID()
560
-            )
561
-                ? '
536
+			}
537
+		}
538
+		return '';
539
+	}
540
+
541
+
542
+	/**
543
+	 * Get the link to view the details for the primary registration.
544
+	 * @param EE_Transaction $transaction
545
+	 * @return string
546
+	 * @throws EE_Error
547
+	 */
548
+	protected function get_primary_registration_details_link(EE_Transaction $transaction)
549
+	{
550
+		$registration = $transaction->primary_registration();
551
+		if ($registration instanceof EE_Registration) {
552
+			$url      = EE_Admin_Page::add_query_args_and_nonce(array(
553
+				'action'  => 'view_registration',
554
+				'_REG_ID' => $registration->ID(),
555
+			), REG_ADMIN_URL);
556
+			return EE_Registry::instance()->CAP->current_user_can(
557
+				'ee_read_registration',
558
+				'espresso_registrations_view_registration',
559
+				$registration->ID()
560
+			)
561
+				? '
562 562
 				<li>
563 563
 					<a href="' . $url . '"'
564
-                  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
564
+				  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
565 565
 						<span class="dashicons dashicons-clipboard"></span>
566 566
 					</a>
567 567
 				</li>'
568
-                : '';
569
-        }
570
-        return '';
571
-    }
572
-
573
-
574
-    /**
575
-     * Get send payment reminder trigger link
576
-     * @param EE_Transaction $transaction
577
-     * @return string
578
-     * @throws EE_Error
579
-     */
580
-    protected function get_send_payment_reminder_trigger_link(EE_Transaction $transaction)
581
-    {
582
-        $registration = $transaction->primary_registration();
583
-        if ($registration instanceof EE_Registration
584
-            && $registration->attendee() instanceof EE_Attendee
585
-            && EEH_MSG_Template::is_mt_active('payment_reminder')
586
-            && ! in_array(
587
-                $transaction->status_ID(),
588
-                array(EEM_Transaction::complete_status_code, EEM_Transaction::overpaid_status_code),
589
-                true
590
-            )
591
-            && EE_Registry::instance()->CAP->current_user_can(
592
-                'ee_send_message',
593
-                'espresso_transactions_send_payment_reminder'
594
-            )
595
-        ) {
596
-            $url = EE_Admin_Page::add_query_args_and_nonce(array(
597
-                'action' => 'send_payment_reminder',
598
-                'TXN_ID' => $transaction->ID(),
599
-            ), TXN_ADMIN_URL);
600
-            return  '
568
+				: '';
569
+		}
570
+		return '';
571
+	}
572
+
573
+
574
+	/**
575
+	 * Get send payment reminder trigger link
576
+	 * @param EE_Transaction $transaction
577
+	 * @return string
578
+	 * @throws EE_Error
579
+	 */
580
+	protected function get_send_payment_reminder_trigger_link(EE_Transaction $transaction)
581
+	{
582
+		$registration = $transaction->primary_registration();
583
+		if ($registration instanceof EE_Registration
584
+			&& $registration->attendee() instanceof EE_Attendee
585
+			&& EEH_MSG_Template::is_mt_active('payment_reminder')
586
+			&& ! in_array(
587
+				$transaction->status_ID(),
588
+				array(EEM_Transaction::complete_status_code, EEM_Transaction::overpaid_status_code),
589
+				true
590
+			)
591
+			&& EE_Registry::instance()->CAP->current_user_can(
592
+				'ee_send_message',
593
+				'espresso_transactions_send_payment_reminder'
594
+			)
595
+		) {
596
+			$url = EE_Admin_Page::add_query_args_and_nonce(array(
597
+				'action' => 'send_payment_reminder',
598
+				'TXN_ID' => $transaction->ID(),
599
+			), TXN_ADMIN_URL);
600
+			return  '
601 601
             <li>
602 602
                 <a href="' . $url . '"'
603
-                  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
603
+				  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
604 604
                     <span class="dashicons dashicons-email-alt"></span>
605 605
                 </a>
606 606
             </li>';
607
-        }
608
-        return '';
609
-    }
610
-
611
-
612
-
613
-    /**
614
-     * Get link to filtered view in the message activity list table of messages for this transaction.
615
-     * @param EE_Transaction $transaction
616
-     * @return string
617
-     * @throws EE_Error
618
-     */
619
-    protected function get_related_messages_link(EE_Transaction $transaction)
620
-    {
621
-        $url = EEH_MSG_Template::get_message_action_link(
622
-            'see_notifications_for',
623
-            null,
624
-            array('TXN_ID' => $transaction->ID())
625
-        );
626
-        return EE_Registry::instance()->CAP->current_user_can(
627
-            'ee_read_global_messages',
628
-            'view_filtered_messages'
629
-        )
630
-            ? '<li>' . $url . '</li>'
631
-            : '';
632
-    }
633
-
634
-
635
-    /**
636
-     * Return the link to make a payment on the frontend
637
-     * @param EE_Transaction $transaction
638
-     * @return string
639
-     * @throws EE_Error
640
-     */
641
-    protected function get_payment_overview_link(EE_Transaction $transaction)
642
-    {
643
-        $registration = $transaction->primary_registration();
644
-        if ($registration instanceof EE_Registration
645
-            && $transaction->status_ID() !== EEM_Transaction::complete_status_code
646
-            && $registration->owes_monies_and_can_pay()
647
-        ) {
648
-            return '
607
+		}
608
+		return '';
609
+	}
610
+
611
+
612
+
613
+	/**
614
+	 * Get link to filtered view in the message activity list table of messages for this transaction.
615
+	 * @param EE_Transaction $transaction
616
+	 * @return string
617
+	 * @throws EE_Error
618
+	 */
619
+	protected function get_related_messages_link(EE_Transaction $transaction)
620
+	{
621
+		$url = EEH_MSG_Template::get_message_action_link(
622
+			'see_notifications_for',
623
+			null,
624
+			array('TXN_ID' => $transaction->ID())
625
+		);
626
+		return EE_Registry::instance()->CAP->current_user_can(
627
+			'ee_read_global_messages',
628
+			'view_filtered_messages'
629
+		)
630
+			? '<li>' . $url . '</li>'
631
+			: '';
632
+	}
633
+
634
+
635
+	/**
636
+	 * Return the link to make a payment on the frontend
637
+	 * @param EE_Transaction $transaction
638
+	 * @return string
639
+	 * @throws EE_Error
640
+	 */
641
+	protected function get_payment_overview_link(EE_Transaction $transaction)
642
+	{
643
+		$registration = $transaction->primary_registration();
644
+		if ($registration instanceof EE_Registration
645
+			&& $transaction->status_ID() !== EEM_Transaction::complete_status_code
646
+			&& $registration->owes_monies_and_can_pay()
647
+		) {
648
+			return '
649 649
             <li>
650 650
                 <a title="' . esc_attr__('Make Payment from the Frontend.', 'event_espresso') . '"'
651
-                    . ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
652
-                    . ' class="tiny-text">
651
+					. ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
652
+					. ' class="tiny-text">
653 653
                     <span class="dashicons dashicons-money ee-icon-size-18"></span>
654 654
                 </a>
655 655
             </li>
656 656
             ';
657 657
 
658
-        }
659
-        return '';
660
-    }
658
+		}
659
+		return '';
660
+	}
661 661
 }
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -48,11 +48,11 @@  discard block
 block discarded – undo
48 48
             'ajax'     => true,
49 49
             'screen'   => $this->_admin_page->get_current_screen()->id,
50 50
         );
51
-        $ID_column_name      = __('ID', 'event_espresso');
51
+        $ID_column_name = __('ID', 'event_espresso');
52 52
         $ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
53 53
         $ID_column_name      .= __('Transaction Date', 'event_espresso');
54 54
         $ID_column_name      .= '</span> ';
55
-        $this->_columns      = array(
55
+        $this->_columns = array(
56 56
             'TXN_ID'        => $ID_column_name,
57 57
             'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
58 58
             'TXN_total'     => __('Total', 'event_espresso'),
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
     {
88 88
         $class = parent::_get_row_class($transaction);
89 89
         //add status class
90
-        $class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
90
+        $class .= ' ee-status-strip txn-status-'.$transaction->status_ID();
91 91
         if ($this->_has_checkbox_column) {
92 92
             $class .= ' has-checkbox-column';
93 93
         }
@@ -113,7 +113,7 @@  discard block
 block discarded – undo
113 113
                 'm/d/Y',
114 114
                 strtotime('-10 year')
115 115
             );
116
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
116
+        $end_date = isset($this->_req_data['txn-filter-end-date'])
117 117
             ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
118 118
             : date(
119 119
                 'm/d/Y',
@@ -158,13 +158,13 @@  discard block
 block discarded – undo
158 158
             'action' => 'view_transaction',
159 159
             'TXN_ID' => $transaction->ID(),
160 160
         ), TXN_ADMIN_URL);
161
-        $content      = '<a href="' . $view_lnk_url . '"'
162
-                        . ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
161
+        $content = '<a href="'.$view_lnk_url.'"'
162
+                        . ' title="'.esc_attr__('Go to Transaction Details', 'event_espresso').'">'
163 163
                         . $transaction->ID()
164 164
                         . '</a>';
165 165
 
166 166
         //txn timestamp
167
-        $content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
167
+        $content .= '  <span class="show-on-mobile-view-only">'.$this->_get_txn_timestamp($transaction).'</span>';
168 168
         return $content;
169 169
     }
170 170
 
@@ -221,9 +221,9 @@  discard block
 block discarded – undo
221 221
             'action' => 'view_transaction',
222 222
             'TXN_ID' => $transaction->ID(),
223 223
         ), TXN_ADMIN_URL);
224
-        $txn_date     = '<a href="' . $view_lnk_url . '"'
224
+        $txn_date = '<a href="'.$view_lnk_url.'"'
225 225
                         . ' title="'
226
-                        . esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
226
+                        . esc_attr__('View Transaction Details for TXN #', 'event_espresso').$transaction->ID().'">'
227 227
                         . $this->_get_txn_timestamp($transaction)
228 228
                         . '</a>';
229 229
         //status
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
                    )
257 257
                    . '</span>';
258 258
         } else {
259
-            return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
259
+            return '<span class="txn-overview-free-event-spn">'.esc_html__('free', 'event_espresso').'</span>';
260 260
         }
261 261
     }
262 262
 
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
             : esc_html__('Unknown', 'event_espresso');
295 295
         $transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
296 296
 
297
-        $content = '<span class="' . $span_class . ' txn-pad-rght">'
297
+        $content = '<span class="'.$span_class.' txn-pad-rght">'
298 298
                    . $transaction_paid_content
299 299
                    . '</span>';
300 300
         if ($transaction_paid > 0) {
@@ -325,17 +325,17 @@  discard block
 block discarded – undo
325 325
                 'action'  => 'view_registration',
326 326
                 '_REG_ID' => $primary_reg->ID(),
327 327
             ), REG_ADMIN_URL);
328
-            $content      = EE_Registry::instance()->CAP->current_user_can(
328
+            $content = EE_Registry::instance()->CAP->current_user_can(
329 329
                 'ee_read_registration',
330 330
                 'espresso_registrations_view_registration',
331 331
                 $primary_reg->ID()
332 332
             )
333
-                ? '<a href="' . $edit_lnk_url . '"'
334
-                    . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
333
+                ? '<a href="'.$edit_lnk_url.'"'
334
+                    . ' title="'.esc_attr__('View Registration Details', 'event_espresso').'">'
335 335
                     . $attendee->full_name()
336 336
                     . '</a>'
337 337
                 : $attendee->full_name();
338
-            $content      .= '<br>' . $attendee->email();
338
+            $content .= '<br>'.$attendee->email();
339 339
             return $content;
340 340
         }
341 341
         return $transaction->failed() || $transaction->is_abandoned()
@@ -357,8 +357,8 @@  discard block
 block discarded – undo
357 357
     public function column_ATT_email(EE_Transaction $transaction)
358 358
     {
359 359
         $attendee = $transaction->primary_registration()->get_first_related('Attendee');
360
-        if (! empty($attendee)) {
361
-            return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
360
+        if ( ! empty($attendee)) {
361
+            return '<a href="mailto:'.$attendee->get('ATT_email').'">'
362 362
                    . $attendee->get('ATT_email')
363 363
                    . '</a>';
364 364
         } else {
@@ -383,12 +383,12 @@  discard block
 block discarded – undo
383 383
     {
384 384
         $actions = array();
385 385
         $event   = $transaction->primary_registration()->get_first_related('Event');
386
-        if (! empty($event)) {
386
+        if ( ! empty($event)) {
387 387
             $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
388 388
                 array('action' => 'edit', 'post' => $event->ID()),
389 389
                 EVENTS_ADMIN_URL
390 390
             );
391
-            $event_name     = $event->get('EVT_name');
391
+            $event_name = $event->get('EVT_name');
392 392
 
393 393
             //filter this view by transactions for this event
394 394
             $txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
@@ -400,8 +400,8 @@  discard block
 block discarded – undo
400 400
                 'espresso_events_edit',
401 401
                 $event->ID()
402 402
             )) {
403
-                $actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
404
-                        . ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
403
+                $actions['filter_by_event'] = '<a href="'.$txn_by_event_lnk.'"'
404
+                        . ' title="'.esc_attr__('Filter transactions by this event', 'event_espresso').'">'
405 405
                         . esc_html__('View Transactions for this event', 'event_espresso')
406 406
                         . '</a>';
407 407
             }
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
                     'espresso_events_edit',
414 414
                     $event->ID()
415 415
                 )
416
-                    ? '<a href="' . $edit_event_url . '"'
416
+                    ? '<a href="'.$edit_event_url.'"'
417 417
                         . ' title="'
418 418
                         . sprintf(
419 419
                             esc_attr__('Edit Event: %s', 'event_espresso'),
@@ -470,14 +470,14 @@  discard block
 block discarded – undo
470 470
      */
471 471
     protected function get_transaction_details_link(EE_Transaction $transaction)
472 472
     {
473
-        $url          = EE_Admin_Page::add_query_args_and_nonce(array(
473
+        $url = EE_Admin_Page::add_query_args_and_nonce(array(
474 474
             'action' => 'view_transaction',
475 475
             'TXN_ID' => $transaction->ID(),
476 476
         ), TXN_ADMIN_URL);
477 477
         return '
478 478
 			<li>
479
-				<a href="' . $url . '"'
480
-                    . ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
479
+				<a href="' . $url.'"'
480
+                    . ' title="'.esc_attr__('View Transaction Details', 'event_espresso').'" class="tiny-text">
481 481
 					<span class="dashicons dashicons-cart"></span>
482 482
 				</a>
483 483
 			</li>';
@@ -501,8 +501,8 @@  discard block
 block discarded – undo
501 501
             ) {
502 502
                 return '
503 503
                 <li>
504
-                    <a title="' . esc_attr__('View Transaction Invoice', 'event_espresso') . '"'
505
-                       . ' target="_blank" href="' . $url . '" class="tiny-text">
504
+                    <a title="' . esc_attr__('View Transaction Invoice', 'event_espresso').'"'
505
+                       . ' target="_blank" href="'.$url.'" class="tiny-text">
506 506
                         <span class="dashicons dashicons-media-spreadsheet ee-icon-size-18"></span>
507 507
                     </a>
508 508
                 </li>';
@@ -528,8 +528,8 @@  discard block
 block discarded – undo
528 528
                 && EEH_MSG_Template::is_mt_active('receipt')) {
529 529
                 return '
530 530
 			<li>
531
-				<a title="' . esc_attr__('View Transaction Receipt', 'event_espresso') . '"'
532
-                                  . ' target="_blank" href="' . $url . '" class="tiny-text">
531
+				<a title="' . esc_attr__('View Transaction Receipt', 'event_espresso').'"'
532
+                                  . ' target="_blank" href="'.$url.'" class="tiny-text">
533 533
 					<span class="dashicons dashicons-media-default ee-icon-size-18"></span>
534 534
 				</a>
535 535
 			</li>';
@@ -560,8 +560,8 @@  discard block
 block discarded – undo
560 560
             )
561 561
                 ? '
562 562
 				<li>
563
-					<a href="' . $url . '"'
564
-                  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
563
+					<a href="' . $url.'"'
564
+                  . ' title="'.esc_attr__('View Registration Details', 'event_espresso').'" class="tiny-text">
565 565
 						<span class="dashicons dashicons-clipboard"></span>
566 566
 					</a>
567 567
 				</li>'
@@ -599,8 +599,8 @@  discard block
 block discarded – undo
599 599
             ), TXN_ADMIN_URL);
600 600
             return  '
601 601
             <li>
602
-                <a href="' . $url . '"'
603
-                  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
602
+                <a href="' . $url.'"'
603
+                  . ' title="'.esc_attr__('Send Payment Reminder', 'event_espresso').'" class="tiny-text">
604 604
                     <span class="dashicons dashicons-email-alt"></span>
605 605
                 </a>
606 606
             </li>';
@@ -627,7 +627,7 @@  discard block
 block discarded – undo
627 627
             'ee_read_global_messages',
628 628
             'view_filtered_messages'
629 629
         )
630
-            ? '<li>' . $url . '</li>'
630
+            ? '<li>'.$url.'</li>'
631 631
             : '';
632 632
     }
633 633
 
@@ -647,8 +647,8 @@  discard block
 block discarded – undo
647 647
         ) {
648 648
             return '
649 649
             <li>
650
-                <a title="' . esc_attr__('Make Payment from the Frontend.', 'event_espresso') . '"'
651
-                    . ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
650
+                <a title="' . esc_attr__('Make Payment from the Frontend.', 'event_espresso').'"'
651
+                    . ' target="_blank" href="'.$registration->payment_overview_url(true).'"'
652 652
                     . ' class="tiny-text">
653 653
                     <span class="dashicons dashicons-money ee-icon-size-18"></span>
654 654
                 </a>
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 3 patches
Doc Comments   +4 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1159,7 +1159,7 @@  discard block
 block discarded – undo
1159 1159
      * Sets deleted
1160 1160
      *
1161 1161
      * @param boolean $deleted
1162
-     * @return bool
1162
+     * @return boolean|null
1163 1163
      * @throws EE_Error
1164 1164
      * @throws RuntimeException
1165 1165
      */
@@ -1217,6 +1217,7 @@  discard block
 block discarded – undo
1217 1217
      * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1218 1218
      * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1219 1219
      *                                          consider registration status as well as datetime access.
1220
+     * @param integer $DTT_OR_ID
1220 1221
      * @return bool
1221 1222
      * @throws EE_Error
1222 1223
      */
@@ -1387,7 +1388,7 @@  discard block
 block discarded – undo
1387 1388
      * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1388 1389
      * "Latest" is defined by the `DTT_EVT_start` column.
1389 1390
      *
1390
-     * @return EE_Datetime|null
1391
+     * @return null|EE_Base_Class
1391 1392
      * @throws \EE_Error
1392 1393
      */
1393 1394
     public function get_latest_related_datetime()
@@ -1680,7 +1681,7 @@  discard block
 block discarded – undo
1680 1681
      * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1681 1682
      * Note: if there are no payments on the registration there will be no payment method returned.
1682 1683
      *
1683
-     * @return EE_Payment_Method|null
1684
+     * @return null|EE_Base_Class
1684 1685
      */
1685 1686
     public function payment_method()
1686 1687
     {
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
     {
110 110
         switch ($field_name) {
111 111
             case 'REG_code':
112
-                if (! empty($field_value) && $this->reg_code() === null) {
112
+                if ( ! empty($field_value) && $this->reg_code() === null) {
113 113
                     $this->set_reg_code($field_value, $use_default);
114 114
                 }
115 115
                 break;
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
     public function event()
285 285
     {
286 286
         $event = $this->get_first_related('Event');
287
-        if (! $event instanceof \EE_Event) {
287
+        if ( ! $event instanceof \EE_Event) {
288 288
             throw new EntityNotFoundException('Event ID', $this->event_ID());
289 289
         }
290 290
         return $event;
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
             false,
974 974
             'sentence'
975 975
         );
976
-        $icon   = '';
976
+        $icon = '';
977 977
         switch ($this->status_ID()) {
978 978
             case EEM_Registration::status_id_approved:
979 979
                 $icon = $show_icons
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
                     : '';
1012 1012
                 break;
1013 1013
         }
1014
-        return $icon . $status[$this->status_ID()];
1014
+        return $icon.$status[$this->status_ID()];
1015 1015
     }
1016 1016
 
1017 1017
 
@@ -1229,7 +1229,7 @@  discard block
 block discarded – undo
1229 1229
             return false;
1230 1230
         }
1231 1231
         //is there a datetime ticket that matches this dtt_ID?
1232
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1232
+        if ( ! (EEM_Datetime_Ticket::instance()->exists(array(
1233 1233
             array(
1234 1234
                 'TKT_ID' => $this->get('TKT_ID'),
1235 1235
                 'DTT_ID' => $DTT_ID,
@@ -1258,7 +1258,7 @@  discard block
 block discarded – undo
1258 1258
     {
1259 1259
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1260 1260
 
1261
-        if (! $DTT_ID) {
1261
+        if ( ! $DTT_ID) {
1262 1262
             return false;
1263 1263
         }
1264 1264
 
@@ -1266,7 +1266,7 @@  discard block
 block discarded – undo
1266 1266
 
1267 1267
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1268 1268
         // check-in or not.
1269
-        if (! $max_uses || $max_uses === EE_INF) {
1269
+        if ( ! $max_uses || $max_uses === EE_INF) {
1270 1270
             return true;
1271 1271
         }
1272 1272
 
@@ -1322,7 +1322,7 @@  discard block
 block discarded – undo
1322 1322
             $datetime = $this->get_latest_related_datetime();
1323 1323
             $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1324 1324
             // verify the registration can checkin for the given DTT_ID
1325
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1325
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1326 1326
             EE_Error::add_error(
1327 1327
                 sprintf(
1328 1328
                     esc_html__(
@@ -1505,7 +1505,7 @@  discard block
 block discarded – undo
1505 1505
     public function transaction()
1506 1506
     {
1507 1507
         $transaction = $this->get_first_related('Transaction');
1508
-        if (! $transaction instanceof \EE_Transaction) {
1508
+        if ( ! $transaction instanceof \EE_Transaction) {
1509 1509
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1510 1510
         }
1511 1511
         return $transaction;
@@ -1559,11 +1559,11 @@  discard block
 block discarded – undo
1559 1559
             );
1560 1560
             return;
1561 1561
         }
1562
-        if (! $this->reg_code()) {
1562
+        if ( ! $this->reg_code()) {
1563 1563
             parent::set('REG_code', $REG_code, $use_default);
1564 1564
         } else {
1565 1565
             EE_Error::doing_it_wrong(
1566
-                __CLASS__ . '::' . __FUNCTION__,
1566
+                __CLASS__.'::'.__FUNCTION__,
1567 1567
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1568 1568
                 '4.6.0'
1569 1569
             );
@@ -1713,7 +1713,7 @@  discard block
 block discarded – undo
1713 1713
                 break;
1714 1714
             }
1715 1715
         }
1716
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1716
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1717 1717
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1718 1718
         }
1719 1719
         return $line_item;
Please login to merge, or discard this patch.
Indentation   +1812 added lines, -1812 removed lines patch added patch discarded remove patch
@@ -15,1818 +15,1818 @@
 block discarded – undo
15 15
 {
16 16
 
17 17
 
18
-    /**
19
-     * Used to reference when a registration has never been checked in.
20
-     *
21
-     * @type int
22
-     */
23
-    const checkin_status_never = 2;
24
-
25
-    /**
26
-     * Used to reference when a registration has been checked in.
27
-     *
28
-     * @type int
29
-     */
30
-    const checkin_status_in = 1;
31
-
32
-
33
-    /**
34
-     * Used to reference when a registration has been checked out.
35
-     *
36
-     * @type int
37
-     */
38
-    const checkin_status_out = 0;
39
-
40
-
41
-    /**
42
-     * extra meta key for tracking reg status os trashed registrations
43
-     *
44
-     * @type string
45
-     */
46
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
47
-
48
-
49
-    /**
50
-     * extra meta key for tracking if registration has reserved ticket
51
-     *
52
-     * @type string
53
-     */
54
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
55
-
56
-
57
-    /**
58
-     * @param array  $props_n_values          incoming values
59
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
60
-     *                                        used.)
61
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
62
-     *                                        date_format and the second value is the time format
63
-     * @return EE_Registration
64
-     * @throws EE_Error
65
-     */
66
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
67
-    {
68
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
69
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
70
-    }
71
-
72
-
73
-    /**
74
-     * @param array  $props_n_values  incoming values from the database
75
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
76
-     *                                the website will be used.
77
-     * @return EE_Registration
78
-     */
79
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
80
-    {
81
-        return new self($props_n_values, true, $timezone);
82
-    }
83
-
84
-
85
-    /**
86
-     *        Set Event ID
87
-     *
88
-     * @param        int $EVT_ID Event ID
89
-     * @throws EE_Error
90
-     * @throws RuntimeException
91
-     */
92
-    public function set_event($EVT_ID = 0)
93
-    {
94
-        $this->set('EVT_ID', $EVT_ID);
95
-    }
96
-
97
-
98
-    /**
99
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
100
-     * be routed to internal methods
101
-     *
102
-     * @param string $field_name
103
-     * @param mixed  $field_value
104
-     * @param bool   $use_default
105
-     * @throws \EE_Error
106
-     * @throws \RuntimeException
107
-     */
108
-    public function set($field_name, $field_value, $use_default = false)
109
-    {
110
-        switch ($field_name) {
111
-            case 'REG_code':
112
-                if (! empty($field_value) && $this->reg_code() === null) {
113
-                    $this->set_reg_code($field_value, $use_default);
114
-                }
115
-                break;
116
-            case 'STS_ID':
117
-                $this->set_status($field_value, $use_default);
118
-                break;
119
-            default:
120
-                parent::set($field_name, $field_value, $use_default);
121
-        }
122
-    }
123
-
124
-
125
-    /**
126
-     * Set Status ID
127
-     * updates the registration status and ALSO...
128
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
129
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
130
-     *
131
-     * @param string  $new_STS_ID
132
-     * @param boolean $use_default
133
-     * @return bool
134
-     * @throws \RuntimeException
135
-     * @throws \EE_Error
136
-     */
137
-    public function set_status($new_STS_ID = null, $use_default = false)
138
-    {
139
-        // get current REG_Status
140
-        $old_STS_ID = $this->status_ID();
141
-        // if status has changed
142
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
143
-            && ! empty($old_STS_ID) // and that old status is actually set
144
-            && ! empty($new_STS_ID) // as well as the new status
145
-            && $this->ID() // ensure registration is in the db
146
-        ) {
147
-            // TO approved
148
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
149
-                // reserve a space by incrementing ticket and datetime sold values
150
-                $this->_reserve_registration_space();
151
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID);
152
-                // OR FROM  approved
153
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
154
-                // release a space by decrementing ticket and datetime sold values
155
-                $this->_release_registration_space();
156
-                do_action('AHEE__EE_Registration__set_status__from_approved', $this, $old_STS_ID, $new_STS_ID);
157
-            }
158
-            // update status
159
-            parent::set('STS_ID', $new_STS_ID, $use_default);
160
-            $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID);
161
-            /** @type EE_Transaction_Payments $transaction_payments */
162
-            $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
163
-            $transaction_payments->recalculate_transaction_total($this->transaction(), false);
164
-            $this->transaction()->update_status_based_on_total_paid(true);
165
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID);
166
-            return true;
167
-        }
168
-        //even though the old value matches the new value, it's still good to
169
-        //allow the parent set method to have a say
170
-        parent::set('STS_ID', $new_STS_ID, $use_default);
171
-        return true;
172
-    }
173
-
174
-
175
-    /**
176
-     * update REGs and TXN when cancelled or declined registrations involved
177
-     *
178
-     * @param string $new_STS_ID
179
-     * @param string $old_STS_ID
180
-     * @throws \EE_Error
181
-     */
182
-    private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID)
183
-    {
184
-        // these reg statuses should not be considered in any calculations involving monies owing
185
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
186
-        // true if registration has been cancelled or declined
187
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
188
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
189
-        ) {
190
-            /** @type EE_Registration_Processor $registration_processor */
191
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
192
-            /** @type EE_Transaction_Processor $transaction_processor */
193
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
194
-            // cancelled or declined registration
195
-            $registration_processor->update_registration_after_being_canceled_or_declined(
196
-                $this,
197
-                $closed_reg_statuses
198
-            );
199
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
200
-                $this,
201
-                $closed_reg_statuses,
202
-                false
203
-            );
204
-            do_action('AHEE__EE_Registration__set_status__canceled_or_declined', $this, $old_STS_ID, $new_STS_ID);
205
-            return;
206
-        }
207
-        // true if reinstating cancelled or declined registration
208
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
209
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
210
-        ) {
211
-            /** @type EE_Registration_Processor $registration_processor */
212
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
213
-            /** @type EE_Transaction_Processor $transaction_processor */
214
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
215
-            // reinstating cancelled or declined registration
216
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
217
-                $this,
218
-                $closed_reg_statuses
219
-            );
220
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
221
-                $this,
222
-                $closed_reg_statuses,
223
-                false
224
-            );
225
-            do_action('AHEE__EE_Registration__set_status__after_reinstated', $this, $old_STS_ID, $new_STS_ID);
226
-        }
227
-    }
228
-
229
-
230
-    /**
231
-     *        get Status ID
232
-     */
233
-    public function status_ID()
234
-    {
235
-        return $this->get('STS_ID');
236
-    }
237
-
238
-
239
-    /**
240
-     * increments this registration's related ticket sold and corresponding datetime sold values
241
-     *
242
-     * @return void
243
-     * @throws EE_Error
244
-     * @throws EntityNotFoundException
245
-     */
246
-    private function _reserve_registration_space()
247
-    {
248
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
249
-        // so stop tracking that this reg has a ticket reserved
250
-        $this->release_reserved_ticket();
251
-        $ticket = $this->ticket();
252
-        $ticket->increase_sold();
253
-        $ticket->save();
254
-        // possibly set event status to sold out
255
-        $this->event()->perform_sold_out_status_check();
256
-    }
257
-
258
-
259
-    /**
260
-     * Gets the ticket this registration is for
261
-     *
262
-     * @param boolean $include_archived whether to include archived tickets or not.
263
-     * @return EE_Ticket|EE_Base_Class
264
-     * @throws \EE_Error
265
-     */
266
-    public function ticket($include_archived = true)
267
-    {
268
-        $query_params = array();
269
-        if ($include_archived) {
270
-            $query_params['default_where_conditions'] = 'none';
271
-        }
272
-        return $this->get_first_related('Ticket', $query_params);
273
-    }
274
-
275
-
276
-    /**
277
-     * Gets the event this registration is for
278
-     *
279
-     * @return EE_Event
280
-     * @throws EE_Error
281
-     * @throws EntityNotFoundException
282
-     */
283
-    public function event()
284
-    {
285
-        $event = $this->get_first_related('Event');
286
-        if (! $event instanceof \EE_Event) {
287
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
288
-        }
289
-        return $event;
290
-    }
291
-
292
-
293
-    /**
294
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
295
-     * with the author of the event this registration is for.
296
-     *
297
-     * @since 4.5.0
298
-     * @return int
299
-     * @throws EE_Error
300
-     * @throws EntityNotFoundException
301
-     */
302
-    public function wp_user()
303
-    {
304
-        $event = $this->event();
305
-        if ($event instanceof EE_Event) {
306
-            return $event->wp_user();
307
-        }
308
-        return 0;
309
-    }
310
-
311
-
312
-    /**
313
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
314
-     *
315
-     * @return void
316
-     * @throws \EE_Error
317
-     */
318
-    private function _release_registration_space()
319
-    {
320
-        $ticket = $this->ticket();
321
-        $ticket->decrease_sold();
322
-        $ticket->save();
323
-    }
324
-
325
-
326
-    /**
327
-     * tracks this registration's ticket reservation in extra meta
328
-     * and can increment related ticket reserved and corresponding datetime reserved values
329
-     *
330
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
331
-     * @return void
332
-     * @throws \EE_Error
333
-     */
334
-    public function reserve_ticket($update_ticket = false)
335
-    {
336
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
337
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
338
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
339
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
340
-                $ticket = $this->ticket();
341
-                $ticket->increase_reserved();
342
-                $ticket->save();
343
-            }
344
-        }
345
-    }
346
-
347
-
348
-    /**
349
-     * stops tracking this registration's ticket reservation in extra meta
350
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
351
-     *
352
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
353
-     * @return void
354
-     * @throws \EE_Error
355
-     */
356
-    public function release_reserved_ticket($update_ticket = false)
357
-    {
358
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
359
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
360
-            // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
361
-            if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
362
-                $ticket = $this->ticket();
363
-                $ticket->decrease_reserved();
364
-                $ticket->save();
365
-            }
366
-        }
367
-    }
368
-
369
-
370
-    /**
371
-     * Set Attendee ID
372
-     *
373
-     * @param        int $ATT_ID Attendee ID
374
-     * @throws EE_Error
375
-     * @throws RuntimeException
376
-     */
377
-    public function set_attendee_id($ATT_ID = 0)
378
-    {
379
-        $this->set('ATT_ID', $ATT_ID);
380
-    }
381
-
382
-
383
-    /**
384
-     *        Set Transaction ID
385
-     *
386
-     * @param        int $TXN_ID Transaction ID
387
-     * @throws EE_Error
388
-     * @throws RuntimeException
389
-     */
390
-    public function set_transaction_id($TXN_ID = 0)
391
-    {
392
-        $this->set('TXN_ID', $TXN_ID);
393
-    }
394
-
395
-
396
-    /**
397
-     *        Set Session
398
-     *
399
-     * @param    string $REG_session PHP Session ID
400
-     * @throws EE_Error
401
-     * @throws RuntimeException
402
-     */
403
-    public function set_session($REG_session = '')
404
-    {
405
-        $this->set('REG_session', $REG_session);
406
-    }
407
-
408
-
409
-    /**
410
-     *        Set Registration URL Link
411
-     *
412
-     * @param    string $REG_url_link Registration URL Link
413
-     * @throws EE_Error
414
-     * @throws RuntimeException
415
-     */
416
-    public function set_reg_url_link($REG_url_link = '')
417
-    {
418
-        $this->set('REG_url_link', $REG_url_link);
419
-    }
420
-
421
-
422
-    /**
423
-     *        Set Attendee Counter
424
-     *
425
-     * @param        int $REG_count Primary Attendee
426
-     * @throws EE_Error
427
-     * @throws RuntimeException
428
-     */
429
-    public function set_count($REG_count = 1)
430
-    {
431
-        $this->set('REG_count', $REG_count);
432
-    }
433
-
434
-
435
-    /**
436
-     *        Set Group Size
437
-     *
438
-     * @param        boolean $REG_group_size Group Registration
439
-     * @throws EE_Error
440
-     * @throws RuntimeException
441
-     */
442
-    public function set_group_size($REG_group_size = false)
443
-    {
444
-        $this->set('REG_group_size', $REG_group_size);
445
-    }
446
-
447
-
448
-    /**
449
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
450
-     *    EEM_Registration::status_id_not_approved
451
-     *
452
-     * @return        boolean
453
-     */
454
-    public function is_not_approved()
455
-    {
456
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
457
-    }
458
-
459
-
460
-    /**
461
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
462
-     *    EEM_Registration::status_id_pending_payment
463
-     *
464
-     * @return        boolean
465
-     */
466
-    public function is_pending_payment()
467
-    {
468
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
469
-    }
470
-
471
-
472
-    /**
473
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
474
-     *
475
-     * @return        boolean
476
-     */
477
-    public function is_approved()
478
-    {
479
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
480
-    }
481
-
482
-
483
-    /**
484
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
485
-     *
486
-     * @return        boolean
487
-     */
488
-    public function is_cancelled()
489
-    {
490
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
491
-    }
492
-
493
-
494
-    /**
495
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
496
-     *
497
-     * @return        boolean
498
-     */
499
-    public function is_declined()
500
-    {
501
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
502
-    }
503
-
504
-
505
-    /**
506
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
507
-     *    EEM_Registration::status_id_incomplete
508
-     *
509
-     * @return        boolean
510
-     */
511
-    public function is_incomplete()
512
-    {
513
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
514
-    }
515
-
516
-
517
-    /**
518
-     *        Set Registration Date
519
-     *
520
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
521
-     *                                                 Date
522
-     * @throws EE_Error
523
-     * @throws RuntimeException
524
-     */
525
-    public function set_reg_date($REG_date = false)
526
-    {
527
-        $this->set('REG_date', $REG_date);
528
-    }
529
-
530
-
531
-    /**
532
-     *    Set final price owing for this registration after all ticket/price modifications
533
-     *
534
-     * @access    public
535
-     * @param    float $REG_final_price
536
-     * @throws EE_Error
537
-     * @throws RuntimeException
538
-     */
539
-    public function set_final_price($REG_final_price = 0.00)
540
-    {
541
-        $this->set('REG_final_price', $REG_final_price);
542
-    }
543
-
544
-
545
-    /**
546
-     *    Set amount paid towards this registration's final price
547
-     *
548
-     * @access    public
549
-     * @param    float $REG_paid
550
-     * @throws EE_Error
551
-     * @throws RuntimeException
552
-     */
553
-    public function set_paid($REG_paid = 0.00)
554
-    {
555
-        $this->set('REG_paid', $REG_paid);
556
-    }
557
-
558
-
559
-    /**
560
-     *        Attendee Is Going
561
-     *
562
-     * @param        boolean $REG_att_is_going Attendee Is Going
563
-     * @throws EE_Error
564
-     * @throws RuntimeException
565
-     */
566
-    public function set_att_is_going($REG_att_is_going = false)
567
-    {
568
-        $this->set('REG_att_is_going', $REG_att_is_going);
569
-    }
570
-
571
-
572
-    /**
573
-     * Gets the related attendee
574
-     *
575
-     * @return EE_Attendee
576
-     * @throws EE_Error
577
-     */
578
-    public function attendee()
579
-    {
580
-        return $this->get_first_related('Attendee');
581
-    }
582
-
583
-
584
-    /**
585
-     *        get Event ID
586
-     */
587
-    public function event_ID()
588
-    {
589
-        return $this->get('EVT_ID');
590
-    }
591
-
592
-
593
-    /**
594
-     *        get Event ID
595
-     */
596
-    public function event_name()
597
-    {
598
-        $event = $this->event_obj();
599
-        if ($event) {
600
-            return $event->name();
601
-        } else {
602
-            return null;
603
-        }
604
-    }
605
-
606
-
607
-    /**
608
-     * Fetches the event this registration is for
609
-     *
610
-     * @return EE_Event
611
-     * @throws EE_Error
612
-     */
613
-    public function event_obj()
614
-    {
615
-        return $this->get_first_related('Event');
616
-    }
617
-
618
-
619
-    /**
620
-     *        get Attendee ID
621
-     */
622
-    public function attendee_ID()
623
-    {
624
-        return $this->get('ATT_ID');
625
-    }
626
-
627
-
628
-    /**
629
-     *        get PHP Session ID
630
-     */
631
-    public function session_ID()
632
-    {
633
-        return $this->get('REG_session');
634
-    }
635
-
636
-
637
-    /**
638
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
639
-     *
640
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
641
-     * @return string
642
-     */
643
-    public function receipt_url($messenger = 'html')
644
-    {
645
-
646
-        /**
647
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
648
-         * already in use on old system.  If there is then we just return the standard url for it.
649
-         *
650
-         * @since 4.5.0
651
-         */
652
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
653
-        $has_custom             = EEH_Template::locate_template(
654
-            $template_relative_path,
655
-            array(),
656
-            true,
657
-            true,
658
-            true
659
-        );
660
-
661
-        if ($has_custom) {
662
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
663
-        }
664
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
665
-    }
666
-
667
-
668
-    /**
669
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
670
-     *
671
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
672
-     * @return string
673
-     * @throws EE_Error
674
-     */
675
-    public function invoice_url($messenger = 'html')
676
-    {
677
-        /**
678
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
679
-         * already in use on old system.  If there is then we just return the standard url for it.
680
-         *
681
-         * @since 4.5.0
682
-         */
683
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
684
-        $has_custom             = EEH_Template::locate_template(
685
-            $template_relative_path,
686
-            array(),
687
-            true,
688
-            true,
689
-            true
690
-        );
691
-
692
-        if ($has_custom) {
693
-            if ($messenger == 'html') {
694
-                return $this->invoice_url('launch');
695
-            }
696
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
697
-
698
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
699
-            if ($messenger == 'html') {
700
-                $query_args['html'] = true;
701
-            }
702
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
703
-        }
704
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
705
-    }
706
-
707
-
708
-    /**
709
-     * get Registration URL Link
710
-     *
711
-     * @access public
712
-     * @return string
713
-     * @throws \EE_Error
714
-     */
715
-    public function reg_url_link()
716
-    {
717
-        return (string) $this->get('REG_url_link');
718
-    }
719
-
720
-
721
-    /**
722
-     * Echoes out invoice_url()
723
-     *
724
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
725
-     * @return void
726
-     * @throws EE_Error
727
-     */
728
-    public function e_invoice_url($type = 'launch')
729
-    {
730
-        echo $this->invoice_url($type);
731
-    }
732
-
733
-
734
-    /**
735
-     * Echoes out payment_overview_url
736
-     */
737
-    public function e_payment_overview_url()
738
-    {
739
-        echo $this->payment_overview_url();
740
-    }
741
-
742
-
743
-    /**
744
-     * Gets the URL of the thank you page with this registration REG_url_link added as
745
-     * a query parameter
746
-     *
747
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
748
-     *                            payment overview url.
749
-     * @return string
750
-     * @throws EE_Error
751
-     */
752
-    public function payment_overview_url($clear_session = false)
753
-    {
754
-        return add_query_arg(array(
755
-            'e_reg_url_link' => $this->reg_url_link(),
756
-            'step'           => 'payment_options',
757
-            'revisit'        => true,
758
-            'clear_session' => (bool) $clear_session
759
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
760
-    }
761
-
762
-
763
-    /**
764
-     * Gets the URL of the thank you page with this registration REG_url_link added as
765
-     * a query parameter
766
-     *
767
-     * @return string
768
-     * @throws EE_Error
769
-     */
770
-    public function edit_attendee_information_url()
771
-    {
772
-        return add_query_arg(array(
773
-            'e_reg_url_link' => $this->reg_url_link(),
774
-            'step'           => 'attendee_information',
775
-            'revisit'        => true,
776
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
777
-    }
778
-
779
-
780
-    /**
781
-     * Simply generates and returns the appropriate admin_url link to edit this registration
782
-     *
783
-     * @return string
784
-     * @throws EE_Error
785
-     */
786
-    public function get_admin_edit_url()
787
-    {
788
-        return EEH_URL::add_query_args_and_nonce(array(
789
-            'page'    => 'espresso_registrations',
790
-            'action'  => 'view_registration',
791
-            '_REG_ID' => $this->ID(),
792
-        ), admin_url('admin.php'));
793
-    }
794
-
795
-
796
-    /**
797
-     *    is_primary_registrant?
798
-     */
799
-    public function is_primary_registrant()
800
-    {
801
-        return $this->get('REG_count') == 1 ? true : false;
802
-    }
803
-
804
-
805
-    /**
806
-     * This returns the primary registration object for this registration group (which may be this object).
807
-     *
808
-     * @return EE_Registration
809
-     * @throws EE_Error
810
-     */
811
-    public function get_primary_registration()
812
-    {
813
-        if ($this->is_primary_registrant()) {
814
-            return $this;
815
-        }
816
-
817
-        //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
818
-        /** @var EE_Registration $primary_registrant */
819
-        $primary_registrant = EEM_Registration::instance()->get_one(array(
820
-            array(
821
-                'TXN_ID'    => $this->transaction_ID(),
822
-                'REG_count' => 1,
823
-            ),
824
-        ));
825
-        return $primary_registrant;
826
-    }
827
-
828
-
829
-    /**
830
-     *        get  Attendee Number
831
-     *
832
-     * @access        public
833
-     */
834
-    public function count()
835
-    {
836
-        return $this->get('REG_count');
837
-    }
838
-
839
-
840
-    /**
841
-     *        get Group Size
842
-     */
843
-    public function group_size()
844
-    {
845
-        return $this->get('REG_group_size');
846
-    }
847
-
848
-
849
-    /**
850
-     *        get Registration Date
851
-     */
852
-    public function date()
853
-    {
854
-        return $this->get('REG_date');
855
-    }
856
-
857
-
858
-    /**
859
-     * gets a pretty date
860
-     *
861
-     * @param string $date_format
862
-     * @param string $time_format
863
-     * @return string
864
-     * @throws EE_Error
865
-     */
866
-    public function pretty_date($date_format = null, $time_format = null)
867
-    {
868
-        return $this->get_datetime('REG_date', $date_format, $time_format);
869
-    }
870
-
871
-
872
-    /**
873
-     * final_price
874
-     * the registration's share of the transaction total, so that the
875
-     * sum of all the transaction's REG_final_prices equal the transaction's total
876
-     *
877
-     * @return float
878
-     * @throws EE_Error
879
-     */
880
-    public function final_price()
881
-    {
882
-        return $this->get('REG_final_price');
883
-    }
884
-
885
-
886
-    /**
887
-     * pretty_final_price
888
-     *  final price as formatted string, with correct decimal places and currency symbol
889
-     *
890
-     * @return string
891
-     * @throws EE_Error
892
-     */
893
-    public function pretty_final_price()
894
-    {
895
-        return $this->get_pretty('REG_final_price');
896
-    }
897
-
898
-
899
-    /**
900
-     * get paid (yeah)
901
-     *
902
-     * @return float
903
-     * @throws EE_Error
904
-     */
905
-    public function paid()
906
-    {
907
-        return $this->get('REG_paid');
908
-    }
909
-
910
-
911
-    /**
912
-     * pretty_paid
913
-     *
914
-     * @return float
915
-     * @throws EE_Error
916
-     */
917
-    public function pretty_paid()
918
-    {
919
-        return $this->get_pretty('REG_paid');
920
-    }
921
-
922
-
923
-    /**
924
-     * owes_monies_and_can_pay
925
-     * whether or not this registration has monies owing and it's' status allows payment
926
-     *
927
-     * @param array $requires_payment
928
-     * @return bool
929
-     * @throws EE_Error
930
-     */
931
-    public function owes_monies_and_can_pay($requires_payment = array())
932
-    {
933
-        // these reg statuses require payment (if event is not free)
934
-        $requires_payment = ! empty($requires_payment)
935
-            ? $requires_payment
936
-            : EEM_Registration::reg_statuses_that_allow_payment();
937
-        if (in_array($this->status_ID(), $requires_payment) &&
938
-            $this->final_price() != 0 &&
939
-            $this->final_price() != $this->paid()
940
-        ) {
941
-            return true;
942
-        } else {
943
-            return false;
944
-        }
945
-    }
946
-
947
-
948
-    /**
949
-     * Prints out the return value of $this->pretty_status()
950
-     *
951
-     * @param bool $show_icons
952
-     * @return void
953
-     * @throws EE_Error
954
-     */
955
-    public function e_pretty_status($show_icons = false)
956
-    {
957
-        echo $this->pretty_status($show_icons);
958
-    }
959
-
960
-
961
-    /**
962
-     * Returns a nice version of the status for displaying to customers
963
-     *
964
-     * @param bool $show_icons
965
-     * @return string
966
-     * @throws EE_Error
967
-     */
968
-    public function pretty_status($show_icons = false)
969
-    {
970
-        $status = EEM_Status::instance()->localized_status(
971
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
972
-            false,
973
-            'sentence'
974
-        );
975
-        $icon   = '';
976
-        switch ($this->status_ID()) {
977
-            case EEM_Registration::status_id_approved:
978
-                $icon = $show_icons
979
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
980
-                    : '';
981
-                break;
982
-            case EEM_Registration::status_id_pending_payment:
983
-                $icon = $show_icons
984
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
985
-                    : '';
986
-                break;
987
-            case EEM_Registration::status_id_not_approved:
988
-                $icon = $show_icons
989
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
990
-                    : '';
991
-                break;
992
-            case EEM_Registration::status_id_cancelled:
993
-                $icon = $show_icons
994
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
995
-                    : '';
996
-                break;
997
-            case EEM_Registration::status_id_incomplete:
998
-                $icon = $show_icons
999
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1000
-                    : '';
1001
-                break;
1002
-            case EEM_Registration::status_id_declined:
1003
-                $icon = $show_icons
1004
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1005
-                    : '';
1006
-                break;
1007
-            case EEM_Registration::status_id_wait_list:
1008
-                $icon = $show_icons
1009
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1010
-                    : '';
1011
-                break;
1012
-        }
1013
-        return $icon . $status[$this->status_ID()];
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     *        get Attendee Is Going
1019
-     */
1020
-    public function att_is_going()
1021
-    {
1022
-        return $this->get('REG_att_is_going');
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * Gets related answers
1028
-     *
1029
-     * @param array $query_params like EEM_Base::get_all
1030
-     * @return EE_Answer[]
1031
-     * @throws EE_Error
1032
-     */
1033
-    public function answers($query_params = null)
1034
-    {
1035
-        return $this->get_many_related('Answer', $query_params);
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * Gets the registration's answer value to the specified question
1041
-     * (either the question's ID or a question object)
1042
-     *
1043
-     * @param EE_Question|int $question
1044
-     * @param bool            $pretty_value
1045
-     * @return array|string if pretty_value= true, the result will always be a string
1046
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1047
-     * will convert it into some kind of string)
1048
-     * @throws EE_Error
1049
-     */
1050
-    public function answer_value_to_question($question, $pretty_value = true)
1051
-    {
1052
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1053
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1054
-    }
1055
-
1056
-
1057
-    /**
1058
-     * question_groups
1059
-     * returns an array of EE_Question_Group objects for this registration
1060
-     *
1061
-     * @return EE_Question_Group[]
1062
-     * @throws EE_Error
1063
-     * @throws EntityNotFoundException
1064
-     */
1065
-    public function question_groups()
1066
-    {
1067
-        $question_groups = array();
1068
-        if ($this->event() instanceof EE_Event) {
1069
-            $question_groups = $this->event()->question_groups(
1070
-                array(
1071
-                    array(
1072
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1073
-                    ),
1074
-                    'order_by' => array('QSG_order' => 'ASC'),
1075
-                )
1076
-            );
1077
-        }
1078
-        return $question_groups;
1079
-    }
1080
-
1081
-
1082
-    /**
1083
-     * count_question_groups
1084
-     * returns a count of the number of EE_Question_Group objects for this registration
1085
-     *
1086
-     * @return int
1087
-     * @throws EE_Error
1088
-     * @throws EntityNotFoundException
1089
-     */
1090
-    public function count_question_groups()
1091
-    {
1092
-        $qg_count = 0;
1093
-        if ($this->event() instanceof EE_Event) {
1094
-            $qg_count = $this->event()->count_related(
1095
-                'Question_Group',
1096
-                array(
1097
-                    array(
1098
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1099
-                    ),
1100
-                )
1101
-            );
1102
-        }
1103
-        return $qg_count;
1104
-    }
1105
-
1106
-
1107
-    /**
1108
-     * Returns the registration date in the 'standard' string format
1109
-     * (function may be improved in the future to allow for different formats and timezones)
1110
-     *
1111
-     * @return string
1112
-     * @throws EE_Error
1113
-     */
1114
-    public function reg_date()
1115
-    {
1116
-        return $this->get_datetime('REG_date');
1117
-    }
1118
-
1119
-
1120
-    /**
1121
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1122
-     * the ticket this registration purchased, or the datetime they have registered
1123
-     * to attend)
1124
-     *
1125
-     * @return EE_Datetime_Ticket
1126
-     * @throws EE_Error
1127
-     */
1128
-    public function datetime_ticket()
1129
-    {
1130
-        return $this->get_first_related('Datetime_Ticket');
1131
-    }
1132
-
1133
-
1134
-    /**
1135
-     * Sets the registration's datetime_ticket.
1136
-     *
1137
-     * @param EE_Datetime_Ticket $datetime_ticket
1138
-     * @return EE_Datetime_Ticket
1139
-     * @throws EE_Error
1140
-     */
1141
-    public function set_datetime_ticket($datetime_ticket)
1142
-    {
1143
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1144
-    }
1145
-
1146
-    /**
1147
-     * Gets deleted
1148
-     *
1149
-     * @return bool
1150
-     * @throws EE_Error
1151
-     */
1152
-    public function deleted()
1153
-    {
1154
-        return $this->get('REG_deleted');
1155
-    }
1156
-
1157
-    /**
1158
-     * Sets deleted
1159
-     *
1160
-     * @param boolean $deleted
1161
-     * @return bool
1162
-     * @throws EE_Error
1163
-     * @throws RuntimeException
1164
-     */
1165
-    public function set_deleted($deleted)
1166
-    {
1167
-        if ($deleted) {
1168
-            $this->delete();
1169
-        } else {
1170
-            $this->restore();
1171
-        }
1172
-    }
1173
-
1174
-
1175
-    /**
1176
-     * Get the status object of this object
1177
-     *
1178
-     * @return EE_Status
1179
-     * @throws EE_Error
1180
-     */
1181
-    public function status_obj()
1182
-    {
1183
-        return $this->get_first_related('Status');
1184
-    }
1185
-
1186
-
1187
-    /**
1188
-     * Returns the number of times this registration has checked into any of the datetimes
1189
-     * its available for
1190
-     *
1191
-     * @return int
1192
-     * @throws EE_Error
1193
-     */
1194
-    public function count_checkins()
1195
-    {
1196
-        return $this->get_model()->count_related($this, 'Checkin');
1197
-    }
1198
-
1199
-
1200
-    /**
1201
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1202
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1203
-     *
1204
-     * @return int
1205
-     * @throws EE_Error
1206
-     */
1207
-    public function count_checkins_not_checkedout()
1208
-    {
1209
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1215
-     *
1216
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1217
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1218
-     *                                          consider registration status as well as datetime access.
1219
-     * @return bool
1220
-     * @throws EE_Error
1221
-     */
1222
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1223
-    {
1224
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1225
-
1226
-        //first check registration status
1227
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1228
-            return false;
1229
-        }
1230
-        //is there a datetime ticket that matches this dtt_ID?
1231
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1232
-            array(
1233
-                'TKT_ID' => $this->get('TKT_ID'),
1234
-                'DTT_ID' => $DTT_ID,
1235
-            ),
1236
-        )))
1237
-        ) {
1238
-            return false;
1239
-        }
1240
-
1241
-        //final check is against TKT_uses
1242
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1243
-    }
1244
-
1245
-
1246
-    /**
1247
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1248
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1249
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1250
-     * then return false.  Otherwise return true.
1251
-     *
1252
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1253
-     * @return bool true means can checkin.  false means cannot checkin.
1254
-     * @throws EE_Error
1255
-     */
1256
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1257
-    {
1258
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1259
-
1260
-        if (! $DTT_ID) {
1261
-            return false;
1262
-        }
1263
-
1264
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1265
-
1266
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1267
-        // check-in or not.
1268
-        if (! $max_uses || $max_uses === EE_INF) {
1269
-            return true;
1270
-        }
1271
-
1272
-        //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1273
-        //go ahead and toggle.
1274
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1275
-            return true;
1276
-        }
1277
-
1278
-        //made it here so the last check is whether the number of checkins per unique datetime on this registration
1279
-        //disallows further check-ins.
1280
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1281
-            array(
1282
-                'REG_ID' => $this->ID(),
1283
-                'CHK_in' => true,
1284
-            ),
1285
-        ), 'DTT_ID', true);
1286
-        // checkins have already reached their max number of uses
1287
-        // so registrant can NOT checkin
1288
-        if ($count_unique_dtt_checkins >= $max_uses) {
1289
-            EE_Error::add_error(
1290
-                esc_html__(
1291
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1292
-                    'event_espresso'
1293
-                ),
1294
-                __FILE__,
1295
-                __FUNCTION__,
1296
-                __LINE__
1297
-            );
1298
-            return false;
1299
-        }
1300
-        return true;
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     * toggle Check-in status for this registration
1306
-     * Check-ins are toggled in the following order:
1307
-     * never checked in -> checked in
1308
-     * checked in -> checked out
1309
-     * checked out -> checked in
1310
-     *
1311
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1312
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1313
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1314
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1315
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1316
-     * @throws EE_Error
1317
-     */
1318
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1319
-    {
1320
-        if (empty($DTT_ID)) {
1321
-            $datetime = $this->get_latest_related_datetime();
1322
-            $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1323
-            // verify the registration can checkin for the given DTT_ID
1324
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1325
-            EE_Error::add_error(
1326
-                sprintf(
1327
-                    esc_html__(
1328
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1329
-                        'event_espresso'
1330
-                    ),
1331
-                    $this->ID(),
1332
-                    $DTT_ID
1333
-                ),
1334
-                __FILE__,
1335
-                __FUNCTION__,
1336
-                __LINE__
1337
-            );
1338
-            return false;
1339
-        }
1340
-        $status_paths = array(
1341
-            EE_Registration::checkin_status_never => EE_Registration::checkin_status_in,
1342
-            EE_Registration::checkin_status_in    => EE_Registration::checkin_status_out,
1343
-            EE_Registration::checkin_status_out   => EE_Registration::checkin_status_in,
1344
-        );
1345
-        //start by getting the current status so we know what status we'll be changing to.
1346
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1347
-        $status_to  = $status_paths[$cur_status];
1348
-        // database only records true for checked IN or false for checked OUT
1349
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1350
-        $new_status = $status_to === EE_Registration::checkin_status_in ? true : false;
1351
-        // add relation - note Check-ins are always creating new rows
1352
-        // because we are keeping track of Check-ins over time.
1353
-        // Eventually we'll probably want to show a list table
1354
-        // for the individual Check-ins so that they can be managed.
1355
-        $checkin = EE_Checkin::new_instance(array(
1356
-            'REG_ID' => $this->ID(),
1357
-            'DTT_ID' => $DTT_ID,
1358
-            'CHK_in' => $new_status,
1359
-        ));
1360
-        // if the record could not be saved then return false
1361
-        if ($checkin->save() === 0) {
1362
-            if (WP_DEBUG) {
1363
-                global $wpdb;
1364
-                $error = sprintf(
1365
-                    esc_html__(
1366
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1367
-                        'event_espresso'
1368
-                    ),
1369
-                    '<br />',
1370
-                    $wpdb->last_error
1371
-                );
1372
-            } else {
1373
-                $error = esc_html__(
1374
-                    'Registration check in update failed because of an unknown database error',
1375
-                    'event_espresso'
1376
-                );
1377
-            }
1378
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1379
-            return false;
1380
-        }
1381
-        return $status_to;
1382
-    }
1383
-
1384
-
1385
-    /**
1386
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1387
-     * "Latest" is defined by the `DTT_EVT_start` column.
1388
-     *
1389
-     * @return EE_Datetime|null
1390
-     * @throws \EE_Error
1391
-     */
1392
-    public function get_latest_related_datetime()
1393
-    {
1394
-        return EEM_Datetime::instance()->get_one(
1395
-            array(
1396
-                array(
1397
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1398
-                ),
1399
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1400
-            )
1401
-        );
1402
-    }
1403
-
1404
-
1405
-    /**
1406
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1407
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1408
-     *
1409
-     * @throws \EE_Error
1410
-     */
1411
-    public function get_earliest_related_datetime()
1412
-    {
1413
-        return EEM_Datetime::instance()->get_one(
1414
-            array(
1415
-                array(
1416
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1417
-                ),
1418
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1419
-            )
1420
-        );
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * This method simply returns the check-in status for this registration and the given datetime.
1426
-     * If neither the datetime nor the checkin values are provided as arguments,
1427
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1428
-     *
1429
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1430
-     *                            (if empty we'll get the primary datetime for
1431
-     *                            this registration (via event) and use it's ID);
1432
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1433
-     * @return int                Integer representing Check-in status.
1434
-     * @throws \EE_Error
1435
-     */
1436
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1437
-    {
1438
-        $checkin_query_params = array(
1439
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1440
-        );
1441
-
1442
-        if ($DTT_ID > 0) {
1443
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1444
-        }
1445
-
1446
-        //get checkin object (if exists)
1447
-        $checkin = $checkin instanceof EE_Checkin
1448
-            ? $checkin
1449
-            : $this->get_first_related('Checkin', $checkin_query_params);
1450
-        if ($checkin instanceof EE_Checkin) {
1451
-            if ($checkin->get('CHK_in')) {
1452
-                return EE_Registration::checkin_status_in; //checked in
1453
-            }
1454
-            return EE_Registration::checkin_status_out; //had checked in but is now checked out.
1455
-        }
1456
-        return EE_Registration::checkin_status_never; //never been checked in
1457
-    }
1458
-
1459
-
1460
-    /**
1461
-     * This method returns a localized message for the toggled Check-in message.
1462
-     *
1463
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1464
-     *                     then it is assumed Check-in for primary datetime was toggled.
1465
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1466
-     *                     message can be customized with the attendee name.
1467
-     * @return string internationalized message
1468
-     * @throws EE_Error
1469
-     */
1470
-    public function get_checkin_msg($DTT_ID, $error = false)
1471
-    {
1472
-        //let's get the attendee first so we can include the name of the attendee
1473
-        $attendee = $this->get_first_related('Attendee');
1474
-        if ($attendee instanceof EE_Attendee) {
1475
-            if ($error) {
1476
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1477
-            }
1478
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1479
-            //what is the status message going to be?
1480
-            switch ($cur_status) {
1481
-                case EE_Registration::checkin_status_never:
1482
-                    return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1483
-                        $attendee->full_name());
1484
-                    break;
1485
-                case EE_Registration::checkin_status_in:
1486
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1487
-                    break;
1488
-                case EE_Registration::checkin_status_out:
1489
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1490
-                    break;
1491
-            }
1492
-        }
1493
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1494
-    }
1495
-
1496
-
1497
-    /**
1498
-     * Returns the related EE_Transaction to this registration
1499
-     *
1500
-     * @return EE_Transaction
1501
-     * @throws EE_Error
1502
-     * @throws EntityNotFoundException
1503
-     */
1504
-    public function transaction()
1505
-    {
1506
-        $transaction = $this->get_first_related('Transaction');
1507
-        if (! $transaction instanceof \EE_Transaction) {
1508
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1509
-        }
1510
-        return $transaction;
1511
-    }
1512
-
1513
-
1514
-    /**
1515
-     *        get Registration Code
1516
-     */
1517
-    public function reg_code()
1518
-    {
1519
-        return $this->get('REG_code');
1520
-    }
1521
-
1522
-
1523
-    /**
1524
-     *        get Transaction ID
1525
-     */
1526
-    public function transaction_ID()
1527
-    {
1528
-        return $this->get('TXN_ID');
1529
-    }
1530
-
1531
-
1532
-    /**
1533
-     * @return int
1534
-     * @throws EE_Error
1535
-     */
1536
-    public function ticket_ID()
1537
-    {
1538
-        return $this->get('TKT_ID');
1539
-    }
1540
-
1541
-
1542
-    /**
1543
-     *        Set Registration Code
1544
-     *
1545
-     * @access    public
1546
-     * @param    string  $REG_code Registration Code
1547
-     * @param    boolean $use_default
1548
-     * @throws EE_Error
1549
-     */
1550
-    public function set_reg_code($REG_code, $use_default = false)
1551
-    {
1552
-        if (empty($REG_code)) {
1553
-            EE_Error::add_error(
1554
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1555
-                __FILE__,
1556
-                __FUNCTION__,
1557
-                __LINE__
1558
-            );
1559
-            return;
1560
-        }
1561
-        if (! $this->reg_code()) {
1562
-            parent::set('REG_code', $REG_code, $use_default);
1563
-        } else {
1564
-            EE_Error::doing_it_wrong(
1565
-                __CLASS__ . '::' . __FUNCTION__,
1566
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1567
-                '4.6.0'
1568
-            );
1569
-        }
1570
-    }
1571
-
1572
-
1573
-    /**
1574
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1575
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1576
-     *    $registration->transaction()->registrations();
1577
-     *
1578
-     * @since 4.5.0
1579
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1580
-     * @throws EE_Error
1581
-     */
1582
-    public function get_all_other_registrations_in_group()
1583
-    {
1584
-        if ($this->group_size() < 2) {
1585
-            return array();
1586
-        }
1587
-
1588
-        $query[0] = array(
1589
-            'TXN_ID' => $this->transaction_ID(),
1590
-            'REG_ID' => array('!=', $this->ID()),
1591
-            'TKT_ID' => $this->ticket_ID(),
1592
-        );
1593
-        /** @var EE_Registration[] $registrations */
1594
-        $registrations = $this->get_model()->get_all($query);
1595
-        return $registrations;
1596
-    }
1597
-
1598
-    /**
1599
-     * Return the link to the admin details for the object.
1600
-     *
1601
-     * @return string
1602
-     * @throws EE_Error
1603
-     */
1604
-    public function get_admin_details_link()
1605
-    {
1606
-        EE_Registry::instance()->load_helper('URL');
1607
-        return EEH_URL::add_query_args_and_nonce(
1608
-            array(
1609
-                'page'    => 'espresso_registrations',
1610
-                'action'  => 'view_registration',
1611
-                '_REG_ID' => $this->ID(),
1612
-            ),
1613
-            admin_url('admin.php')
1614
-        );
1615
-    }
1616
-
1617
-    /**
1618
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1619
-     *
1620
-     * @return string
1621
-     * @throws EE_Error
1622
-     */
1623
-    public function get_admin_edit_link()
1624
-    {
1625
-        return $this->get_admin_details_link();
1626
-    }
1627
-
1628
-    /**
1629
-     * Returns the link to a settings page for the object.
1630
-     *
1631
-     * @return string
1632
-     * @throws EE_Error
1633
-     */
1634
-    public function get_admin_settings_link()
1635
-    {
1636
-        return $this->get_admin_details_link();
1637
-    }
1638
-
1639
-    /**
1640
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1641
-     *
1642
-     * @return string
1643
-     */
1644
-    public function get_admin_overview_link()
1645
-    {
1646
-        EE_Registry::instance()->load_helper('URL');
1647
-        return EEH_URL::add_query_args_and_nonce(
1648
-            array(
1649
-                'page' => 'espresso_registrations',
1650
-            ),
1651
-            admin_url('admin.php')
1652
-        );
1653
-    }
1654
-
1655
-
1656
-    /**
1657
-     * @param array $query_params
1658
-     * @return \EE_Registration[]
1659
-     * @throws \EE_Error
1660
-     */
1661
-    public function payments($query_params = array())
1662
-    {
1663
-        return $this->get_many_related('Payment', $query_params);
1664
-    }
1665
-
1666
-
1667
-    /**
1668
-     * @param array $query_params
1669
-     * @return \EE_Registration_Payment[]
1670
-     * @throws \EE_Error
1671
-     */
1672
-    public function registration_payments($query_params = array())
1673
-    {
1674
-        return $this->get_many_related('Registration_Payment', $query_params);
1675
-    }
1676
-
1677
-
1678
-    /**
1679
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1680
-     * Note: if there are no payments on the registration there will be no payment method returned.
1681
-     *
1682
-     * @return EE_Payment_Method|null
1683
-     */
1684
-    public function payment_method()
1685
-    {
1686
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1687
-    }
1688
-
1689
-
1690
-    /**
1691
-     * @return \EE_Line_Item
1692
-     * @throws EntityNotFoundException
1693
-     * @throws \EE_Error
1694
-     */
1695
-    public function ticket_line_item()
1696
-    {
1697
-        $ticket            = $this->ticket();
1698
-        $transaction       = $this->transaction();
1699
-        $line_item         = null;
1700
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1701
-            $transaction->total_line_item(),
1702
-            'Ticket',
1703
-            array($ticket->ID())
1704
-        );
1705
-        foreach ($ticket_line_items as $ticket_line_item) {
1706
-            if (
1707
-                $ticket_line_item instanceof \EE_Line_Item
1708
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1709
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1710
-            ) {
1711
-                $line_item = $ticket_line_item;
1712
-                break;
1713
-            }
1714
-        }
1715
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1716
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1717
-        }
1718
-        return $line_item;
1719
-    }
1720
-
1721
-
1722
-    /**
1723
-     * Soft Deletes this model object.
1724
-     *
1725
-     * @return boolean | int
1726
-     * @throws \RuntimeException
1727
-     * @throws \EE_Error
1728
-     */
1729
-    public function delete()
1730
-    {
1731
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1732
-            $this->set_status(EEM_Registration::status_id_cancelled);
1733
-        }
1734
-        return parent::delete();
1735
-    }
1736
-
1737
-
1738
-    /**
1739
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1740
-     *
1741
-     * @throws \EE_Error
1742
-     * @throws \RuntimeException
1743
-     */
1744
-    public function restore()
1745
-    {
1746
-        $previous_status = $this->get_extra_meta(
1747
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1748
-            true,
1749
-            EEM_Registration::status_id_cancelled
1750
-        );
1751
-        if ($previous_status) {
1752
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1753
-            $this->set_status($previous_status);
1754
-        }
1755
-        return parent::restore();
1756
-    }
1757
-
1758
-
1759
-
1760
-    /*************************** DEPRECATED ***************************/
1761
-
1762
-
1763
-    /**
1764
-     * @deprecated
1765
-     * @since     4.7.0
1766
-     * @access    public
1767
-     */
1768
-    public function price_paid()
1769
-    {
1770
-        EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1771
-            esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1772
-            '4.7.0');
1773
-        return $this->final_price();
1774
-    }
1775
-
1776
-
1777
-    /**
1778
-     * @deprecated
1779
-     * @since     4.7.0
1780
-     * @access    public
1781
-     * @param    float $REG_final_price
1782
-     * @throws EE_Error
1783
-     * @throws RuntimeException
1784
-     */
1785
-    public function set_price_paid($REG_final_price = 0.00)
1786
-    {
1787
-        EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1788
-            esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1789
-            '4.7.0');
1790
-        $this->set_final_price($REG_final_price);
1791
-    }
1792
-
1793
-
1794
-    /**
1795
-     * @deprecated
1796
-     * @since 4.7.0
1797
-     * @return string
1798
-     * @throws EE_Error
1799
-     */
1800
-    public function pretty_price_paid()
1801
-    {
1802
-        EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1803
-            esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1804
-                'event_espresso'), '4.7.0');
1805
-        return $this->pretty_final_price();
1806
-    }
1807
-
1808
-
1809
-    /**
1810
-     * Gets the primary datetime related to this registration via the related Event to this registration
1811
-     *
1812
-     * @deprecated 4.9.17
1813
-     * @return EE_Datetime
1814
-     * @throws EE_Error
1815
-     * @throws EntityNotFoundException
1816
-     */
1817
-    public function get_related_primary_datetime()
1818
-    {
1819
-        EE_Error::doing_it_wrong(
1820
-            __METHOD__,
1821
-            esc_html__(
1822
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1823
-                'event_espresso'
1824
-            ),
1825
-            '4.9.17',
1826
-            '5.0.0'
1827
-        );
1828
-        return $this->event()->primary_datetime();
1829
-    }
18
+	/**
19
+	 * Used to reference when a registration has never been checked in.
20
+	 *
21
+	 * @type int
22
+	 */
23
+	const checkin_status_never = 2;
24
+
25
+	/**
26
+	 * Used to reference when a registration has been checked in.
27
+	 *
28
+	 * @type int
29
+	 */
30
+	const checkin_status_in = 1;
31
+
32
+
33
+	/**
34
+	 * Used to reference when a registration has been checked out.
35
+	 *
36
+	 * @type int
37
+	 */
38
+	const checkin_status_out = 0;
39
+
40
+
41
+	/**
42
+	 * extra meta key for tracking reg status os trashed registrations
43
+	 *
44
+	 * @type string
45
+	 */
46
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
47
+
48
+
49
+	/**
50
+	 * extra meta key for tracking if registration has reserved ticket
51
+	 *
52
+	 * @type string
53
+	 */
54
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
55
+
56
+
57
+	/**
58
+	 * @param array  $props_n_values          incoming values
59
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
60
+	 *                                        used.)
61
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
62
+	 *                                        date_format and the second value is the time format
63
+	 * @return EE_Registration
64
+	 * @throws EE_Error
65
+	 */
66
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
67
+	{
68
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
69
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
70
+	}
71
+
72
+
73
+	/**
74
+	 * @param array  $props_n_values  incoming values from the database
75
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
76
+	 *                                the website will be used.
77
+	 * @return EE_Registration
78
+	 */
79
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
80
+	{
81
+		return new self($props_n_values, true, $timezone);
82
+	}
83
+
84
+
85
+	/**
86
+	 *        Set Event ID
87
+	 *
88
+	 * @param        int $EVT_ID Event ID
89
+	 * @throws EE_Error
90
+	 * @throws RuntimeException
91
+	 */
92
+	public function set_event($EVT_ID = 0)
93
+	{
94
+		$this->set('EVT_ID', $EVT_ID);
95
+	}
96
+
97
+
98
+	/**
99
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
100
+	 * be routed to internal methods
101
+	 *
102
+	 * @param string $field_name
103
+	 * @param mixed  $field_value
104
+	 * @param bool   $use_default
105
+	 * @throws \EE_Error
106
+	 * @throws \RuntimeException
107
+	 */
108
+	public function set($field_name, $field_value, $use_default = false)
109
+	{
110
+		switch ($field_name) {
111
+			case 'REG_code':
112
+				if (! empty($field_value) && $this->reg_code() === null) {
113
+					$this->set_reg_code($field_value, $use_default);
114
+				}
115
+				break;
116
+			case 'STS_ID':
117
+				$this->set_status($field_value, $use_default);
118
+				break;
119
+			default:
120
+				parent::set($field_name, $field_value, $use_default);
121
+		}
122
+	}
123
+
124
+
125
+	/**
126
+	 * Set Status ID
127
+	 * updates the registration status and ALSO...
128
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
129
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
130
+	 *
131
+	 * @param string  $new_STS_ID
132
+	 * @param boolean $use_default
133
+	 * @return bool
134
+	 * @throws \RuntimeException
135
+	 * @throws \EE_Error
136
+	 */
137
+	public function set_status($new_STS_ID = null, $use_default = false)
138
+	{
139
+		// get current REG_Status
140
+		$old_STS_ID = $this->status_ID();
141
+		// if status has changed
142
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
143
+			&& ! empty($old_STS_ID) // and that old status is actually set
144
+			&& ! empty($new_STS_ID) // as well as the new status
145
+			&& $this->ID() // ensure registration is in the db
146
+		) {
147
+			// TO approved
148
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
149
+				// reserve a space by incrementing ticket and datetime sold values
150
+				$this->_reserve_registration_space();
151
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID);
152
+				// OR FROM  approved
153
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
154
+				// release a space by decrementing ticket and datetime sold values
155
+				$this->_release_registration_space();
156
+				do_action('AHEE__EE_Registration__set_status__from_approved', $this, $old_STS_ID, $new_STS_ID);
157
+			}
158
+			// update status
159
+			parent::set('STS_ID', $new_STS_ID, $use_default);
160
+			$this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID);
161
+			/** @type EE_Transaction_Payments $transaction_payments */
162
+			$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
163
+			$transaction_payments->recalculate_transaction_total($this->transaction(), false);
164
+			$this->transaction()->update_status_based_on_total_paid(true);
165
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID);
166
+			return true;
167
+		}
168
+		//even though the old value matches the new value, it's still good to
169
+		//allow the parent set method to have a say
170
+		parent::set('STS_ID', $new_STS_ID, $use_default);
171
+		return true;
172
+	}
173
+
174
+
175
+	/**
176
+	 * update REGs and TXN when cancelled or declined registrations involved
177
+	 *
178
+	 * @param string $new_STS_ID
179
+	 * @param string $old_STS_ID
180
+	 * @throws \EE_Error
181
+	 */
182
+	private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID)
183
+	{
184
+		// these reg statuses should not be considered in any calculations involving monies owing
185
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
186
+		// true if registration has been cancelled or declined
187
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
188
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
189
+		) {
190
+			/** @type EE_Registration_Processor $registration_processor */
191
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
192
+			/** @type EE_Transaction_Processor $transaction_processor */
193
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
194
+			// cancelled or declined registration
195
+			$registration_processor->update_registration_after_being_canceled_or_declined(
196
+				$this,
197
+				$closed_reg_statuses
198
+			);
199
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
200
+				$this,
201
+				$closed_reg_statuses,
202
+				false
203
+			);
204
+			do_action('AHEE__EE_Registration__set_status__canceled_or_declined', $this, $old_STS_ID, $new_STS_ID);
205
+			return;
206
+		}
207
+		// true if reinstating cancelled or declined registration
208
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
209
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
210
+		) {
211
+			/** @type EE_Registration_Processor $registration_processor */
212
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
213
+			/** @type EE_Transaction_Processor $transaction_processor */
214
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
215
+			// reinstating cancelled or declined registration
216
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
217
+				$this,
218
+				$closed_reg_statuses
219
+			);
220
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
221
+				$this,
222
+				$closed_reg_statuses,
223
+				false
224
+			);
225
+			do_action('AHEE__EE_Registration__set_status__after_reinstated', $this, $old_STS_ID, $new_STS_ID);
226
+		}
227
+	}
228
+
229
+
230
+	/**
231
+	 *        get Status ID
232
+	 */
233
+	public function status_ID()
234
+	{
235
+		return $this->get('STS_ID');
236
+	}
237
+
238
+
239
+	/**
240
+	 * increments this registration's related ticket sold and corresponding datetime sold values
241
+	 *
242
+	 * @return void
243
+	 * @throws EE_Error
244
+	 * @throws EntityNotFoundException
245
+	 */
246
+	private function _reserve_registration_space()
247
+	{
248
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
249
+		// so stop tracking that this reg has a ticket reserved
250
+		$this->release_reserved_ticket();
251
+		$ticket = $this->ticket();
252
+		$ticket->increase_sold();
253
+		$ticket->save();
254
+		// possibly set event status to sold out
255
+		$this->event()->perform_sold_out_status_check();
256
+	}
257
+
258
+
259
+	/**
260
+	 * Gets the ticket this registration is for
261
+	 *
262
+	 * @param boolean $include_archived whether to include archived tickets or not.
263
+	 * @return EE_Ticket|EE_Base_Class
264
+	 * @throws \EE_Error
265
+	 */
266
+	public function ticket($include_archived = true)
267
+	{
268
+		$query_params = array();
269
+		if ($include_archived) {
270
+			$query_params['default_where_conditions'] = 'none';
271
+		}
272
+		return $this->get_first_related('Ticket', $query_params);
273
+	}
274
+
275
+
276
+	/**
277
+	 * Gets the event this registration is for
278
+	 *
279
+	 * @return EE_Event
280
+	 * @throws EE_Error
281
+	 * @throws EntityNotFoundException
282
+	 */
283
+	public function event()
284
+	{
285
+		$event = $this->get_first_related('Event');
286
+		if (! $event instanceof \EE_Event) {
287
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
288
+		}
289
+		return $event;
290
+	}
291
+
292
+
293
+	/**
294
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
295
+	 * with the author of the event this registration is for.
296
+	 *
297
+	 * @since 4.5.0
298
+	 * @return int
299
+	 * @throws EE_Error
300
+	 * @throws EntityNotFoundException
301
+	 */
302
+	public function wp_user()
303
+	{
304
+		$event = $this->event();
305
+		if ($event instanceof EE_Event) {
306
+			return $event->wp_user();
307
+		}
308
+		return 0;
309
+	}
310
+
311
+
312
+	/**
313
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
314
+	 *
315
+	 * @return void
316
+	 * @throws \EE_Error
317
+	 */
318
+	private function _release_registration_space()
319
+	{
320
+		$ticket = $this->ticket();
321
+		$ticket->decrease_sold();
322
+		$ticket->save();
323
+	}
324
+
325
+
326
+	/**
327
+	 * tracks this registration's ticket reservation in extra meta
328
+	 * and can increment related ticket reserved and corresponding datetime reserved values
329
+	 *
330
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
331
+	 * @return void
332
+	 * @throws \EE_Error
333
+	 */
334
+	public function reserve_ticket($update_ticket = false)
335
+	{
336
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
337
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
338
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
339
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
340
+				$ticket = $this->ticket();
341
+				$ticket->increase_reserved();
342
+				$ticket->save();
343
+			}
344
+		}
345
+	}
346
+
347
+
348
+	/**
349
+	 * stops tracking this registration's ticket reservation in extra meta
350
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
351
+	 *
352
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
353
+	 * @return void
354
+	 * @throws \EE_Error
355
+	 */
356
+	public function release_reserved_ticket($update_ticket = false)
357
+	{
358
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
359
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
360
+			// we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
361
+			if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
362
+				$ticket = $this->ticket();
363
+				$ticket->decrease_reserved();
364
+				$ticket->save();
365
+			}
366
+		}
367
+	}
368
+
369
+
370
+	/**
371
+	 * Set Attendee ID
372
+	 *
373
+	 * @param        int $ATT_ID Attendee ID
374
+	 * @throws EE_Error
375
+	 * @throws RuntimeException
376
+	 */
377
+	public function set_attendee_id($ATT_ID = 0)
378
+	{
379
+		$this->set('ATT_ID', $ATT_ID);
380
+	}
381
+
382
+
383
+	/**
384
+	 *        Set Transaction ID
385
+	 *
386
+	 * @param        int $TXN_ID Transaction ID
387
+	 * @throws EE_Error
388
+	 * @throws RuntimeException
389
+	 */
390
+	public function set_transaction_id($TXN_ID = 0)
391
+	{
392
+		$this->set('TXN_ID', $TXN_ID);
393
+	}
394
+
395
+
396
+	/**
397
+	 *        Set Session
398
+	 *
399
+	 * @param    string $REG_session PHP Session ID
400
+	 * @throws EE_Error
401
+	 * @throws RuntimeException
402
+	 */
403
+	public function set_session($REG_session = '')
404
+	{
405
+		$this->set('REG_session', $REG_session);
406
+	}
407
+
408
+
409
+	/**
410
+	 *        Set Registration URL Link
411
+	 *
412
+	 * @param    string $REG_url_link Registration URL Link
413
+	 * @throws EE_Error
414
+	 * @throws RuntimeException
415
+	 */
416
+	public function set_reg_url_link($REG_url_link = '')
417
+	{
418
+		$this->set('REG_url_link', $REG_url_link);
419
+	}
420
+
421
+
422
+	/**
423
+	 *        Set Attendee Counter
424
+	 *
425
+	 * @param        int $REG_count Primary Attendee
426
+	 * @throws EE_Error
427
+	 * @throws RuntimeException
428
+	 */
429
+	public function set_count($REG_count = 1)
430
+	{
431
+		$this->set('REG_count', $REG_count);
432
+	}
433
+
434
+
435
+	/**
436
+	 *        Set Group Size
437
+	 *
438
+	 * @param        boolean $REG_group_size Group Registration
439
+	 * @throws EE_Error
440
+	 * @throws RuntimeException
441
+	 */
442
+	public function set_group_size($REG_group_size = false)
443
+	{
444
+		$this->set('REG_group_size', $REG_group_size);
445
+	}
446
+
447
+
448
+	/**
449
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
450
+	 *    EEM_Registration::status_id_not_approved
451
+	 *
452
+	 * @return        boolean
453
+	 */
454
+	public function is_not_approved()
455
+	{
456
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
457
+	}
458
+
459
+
460
+	/**
461
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
462
+	 *    EEM_Registration::status_id_pending_payment
463
+	 *
464
+	 * @return        boolean
465
+	 */
466
+	public function is_pending_payment()
467
+	{
468
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
469
+	}
470
+
471
+
472
+	/**
473
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
474
+	 *
475
+	 * @return        boolean
476
+	 */
477
+	public function is_approved()
478
+	{
479
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
480
+	}
481
+
482
+
483
+	/**
484
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
485
+	 *
486
+	 * @return        boolean
487
+	 */
488
+	public function is_cancelled()
489
+	{
490
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
491
+	}
492
+
493
+
494
+	/**
495
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
496
+	 *
497
+	 * @return        boolean
498
+	 */
499
+	public function is_declined()
500
+	{
501
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
502
+	}
503
+
504
+
505
+	/**
506
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
507
+	 *    EEM_Registration::status_id_incomplete
508
+	 *
509
+	 * @return        boolean
510
+	 */
511
+	public function is_incomplete()
512
+	{
513
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
514
+	}
515
+
516
+
517
+	/**
518
+	 *        Set Registration Date
519
+	 *
520
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
521
+	 *                                                 Date
522
+	 * @throws EE_Error
523
+	 * @throws RuntimeException
524
+	 */
525
+	public function set_reg_date($REG_date = false)
526
+	{
527
+		$this->set('REG_date', $REG_date);
528
+	}
529
+
530
+
531
+	/**
532
+	 *    Set final price owing for this registration after all ticket/price modifications
533
+	 *
534
+	 * @access    public
535
+	 * @param    float $REG_final_price
536
+	 * @throws EE_Error
537
+	 * @throws RuntimeException
538
+	 */
539
+	public function set_final_price($REG_final_price = 0.00)
540
+	{
541
+		$this->set('REG_final_price', $REG_final_price);
542
+	}
543
+
544
+
545
+	/**
546
+	 *    Set amount paid towards this registration's final price
547
+	 *
548
+	 * @access    public
549
+	 * @param    float $REG_paid
550
+	 * @throws EE_Error
551
+	 * @throws RuntimeException
552
+	 */
553
+	public function set_paid($REG_paid = 0.00)
554
+	{
555
+		$this->set('REG_paid', $REG_paid);
556
+	}
557
+
558
+
559
+	/**
560
+	 *        Attendee Is Going
561
+	 *
562
+	 * @param        boolean $REG_att_is_going Attendee Is Going
563
+	 * @throws EE_Error
564
+	 * @throws RuntimeException
565
+	 */
566
+	public function set_att_is_going($REG_att_is_going = false)
567
+	{
568
+		$this->set('REG_att_is_going', $REG_att_is_going);
569
+	}
570
+
571
+
572
+	/**
573
+	 * Gets the related attendee
574
+	 *
575
+	 * @return EE_Attendee
576
+	 * @throws EE_Error
577
+	 */
578
+	public function attendee()
579
+	{
580
+		return $this->get_first_related('Attendee');
581
+	}
582
+
583
+
584
+	/**
585
+	 *        get Event ID
586
+	 */
587
+	public function event_ID()
588
+	{
589
+		return $this->get('EVT_ID');
590
+	}
591
+
592
+
593
+	/**
594
+	 *        get Event ID
595
+	 */
596
+	public function event_name()
597
+	{
598
+		$event = $this->event_obj();
599
+		if ($event) {
600
+			return $event->name();
601
+		} else {
602
+			return null;
603
+		}
604
+	}
605
+
606
+
607
+	/**
608
+	 * Fetches the event this registration is for
609
+	 *
610
+	 * @return EE_Event
611
+	 * @throws EE_Error
612
+	 */
613
+	public function event_obj()
614
+	{
615
+		return $this->get_first_related('Event');
616
+	}
617
+
618
+
619
+	/**
620
+	 *        get Attendee ID
621
+	 */
622
+	public function attendee_ID()
623
+	{
624
+		return $this->get('ATT_ID');
625
+	}
626
+
627
+
628
+	/**
629
+	 *        get PHP Session ID
630
+	 */
631
+	public function session_ID()
632
+	{
633
+		return $this->get('REG_session');
634
+	}
635
+
636
+
637
+	/**
638
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
639
+	 *
640
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
641
+	 * @return string
642
+	 */
643
+	public function receipt_url($messenger = 'html')
644
+	{
645
+
646
+		/**
647
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
648
+		 * already in use on old system.  If there is then we just return the standard url for it.
649
+		 *
650
+		 * @since 4.5.0
651
+		 */
652
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
653
+		$has_custom             = EEH_Template::locate_template(
654
+			$template_relative_path,
655
+			array(),
656
+			true,
657
+			true,
658
+			true
659
+		);
660
+
661
+		if ($has_custom) {
662
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
663
+		}
664
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
665
+	}
666
+
667
+
668
+	/**
669
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
670
+	 *
671
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
672
+	 * @return string
673
+	 * @throws EE_Error
674
+	 */
675
+	public function invoice_url($messenger = 'html')
676
+	{
677
+		/**
678
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
679
+		 * already in use on old system.  If there is then we just return the standard url for it.
680
+		 *
681
+		 * @since 4.5.0
682
+		 */
683
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
684
+		$has_custom             = EEH_Template::locate_template(
685
+			$template_relative_path,
686
+			array(),
687
+			true,
688
+			true,
689
+			true
690
+		);
691
+
692
+		if ($has_custom) {
693
+			if ($messenger == 'html') {
694
+				return $this->invoice_url('launch');
695
+			}
696
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
697
+
698
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
699
+			if ($messenger == 'html') {
700
+				$query_args['html'] = true;
701
+			}
702
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
703
+		}
704
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
705
+	}
706
+
707
+
708
+	/**
709
+	 * get Registration URL Link
710
+	 *
711
+	 * @access public
712
+	 * @return string
713
+	 * @throws \EE_Error
714
+	 */
715
+	public function reg_url_link()
716
+	{
717
+		return (string) $this->get('REG_url_link');
718
+	}
719
+
720
+
721
+	/**
722
+	 * Echoes out invoice_url()
723
+	 *
724
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
725
+	 * @return void
726
+	 * @throws EE_Error
727
+	 */
728
+	public function e_invoice_url($type = 'launch')
729
+	{
730
+		echo $this->invoice_url($type);
731
+	}
732
+
733
+
734
+	/**
735
+	 * Echoes out payment_overview_url
736
+	 */
737
+	public function e_payment_overview_url()
738
+	{
739
+		echo $this->payment_overview_url();
740
+	}
741
+
742
+
743
+	/**
744
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
745
+	 * a query parameter
746
+	 *
747
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
748
+	 *                            payment overview url.
749
+	 * @return string
750
+	 * @throws EE_Error
751
+	 */
752
+	public function payment_overview_url($clear_session = false)
753
+	{
754
+		return add_query_arg(array(
755
+			'e_reg_url_link' => $this->reg_url_link(),
756
+			'step'           => 'payment_options',
757
+			'revisit'        => true,
758
+			'clear_session' => (bool) $clear_session
759
+		), EE_Registry::instance()->CFG->core->reg_page_url());
760
+	}
761
+
762
+
763
+	/**
764
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
765
+	 * a query parameter
766
+	 *
767
+	 * @return string
768
+	 * @throws EE_Error
769
+	 */
770
+	public function edit_attendee_information_url()
771
+	{
772
+		return add_query_arg(array(
773
+			'e_reg_url_link' => $this->reg_url_link(),
774
+			'step'           => 'attendee_information',
775
+			'revisit'        => true,
776
+		), EE_Registry::instance()->CFG->core->reg_page_url());
777
+	}
778
+
779
+
780
+	/**
781
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
782
+	 *
783
+	 * @return string
784
+	 * @throws EE_Error
785
+	 */
786
+	public function get_admin_edit_url()
787
+	{
788
+		return EEH_URL::add_query_args_and_nonce(array(
789
+			'page'    => 'espresso_registrations',
790
+			'action'  => 'view_registration',
791
+			'_REG_ID' => $this->ID(),
792
+		), admin_url('admin.php'));
793
+	}
794
+
795
+
796
+	/**
797
+	 *    is_primary_registrant?
798
+	 */
799
+	public function is_primary_registrant()
800
+	{
801
+		return $this->get('REG_count') == 1 ? true : false;
802
+	}
803
+
804
+
805
+	/**
806
+	 * This returns the primary registration object for this registration group (which may be this object).
807
+	 *
808
+	 * @return EE_Registration
809
+	 * @throws EE_Error
810
+	 */
811
+	public function get_primary_registration()
812
+	{
813
+		if ($this->is_primary_registrant()) {
814
+			return $this;
815
+		}
816
+
817
+		//k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
818
+		/** @var EE_Registration $primary_registrant */
819
+		$primary_registrant = EEM_Registration::instance()->get_one(array(
820
+			array(
821
+				'TXN_ID'    => $this->transaction_ID(),
822
+				'REG_count' => 1,
823
+			),
824
+		));
825
+		return $primary_registrant;
826
+	}
827
+
828
+
829
+	/**
830
+	 *        get  Attendee Number
831
+	 *
832
+	 * @access        public
833
+	 */
834
+	public function count()
835
+	{
836
+		return $this->get('REG_count');
837
+	}
838
+
839
+
840
+	/**
841
+	 *        get Group Size
842
+	 */
843
+	public function group_size()
844
+	{
845
+		return $this->get('REG_group_size');
846
+	}
847
+
848
+
849
+	/**
850
+	 *        get Registration Date
851
+	 */
852
+	public function date()
853
+	{
854
+		return $this->get('REG_date');
855
+	}
856
+
857
+
858
+	/**
859
+	 * gets a pretty date
860
+	 *
861
+	 * @param string $date_format
862
+	 * @param string $time_format
863
+	 * @return string
864
+	 * @throws EE_Error
865
+	 */
866
+	public function pretty_date($date_format = null, $time_format = null)
867
+	{
868
+		return $this->get_datetime('REG_date', $date_format, $time_format);
869
+	}
870
+
871
+
872
+	/**
873
+	 * final_price
874
+	 * the registration's share of the transaction total, so that the
875
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
876
+	 *
877
+	 * @return float
878
+	 * @throws EE_Error
879
+	 */
880
+	public function final_price()
881
+	{
882
+		return $this->get('REG_final_price');
883
+	}
884
+
885
+
886
+	/**
887
+	 * pretty_final_price
888
+	 *  final price as formatted string, with correct decimal places and currency symbol
889
+	 *
890
+	 * @return string
891
+	 * @throws EE_Error
892
+	 */
893
+	public function pretty_final_price()
894
+	{
895
+		return $this->get_pretty('REG_final_price');
896
+	}
897
+
898
+
899
+	/**
900
+	 * get paid (yeah)
901
+	 *
902
+	 * @return float
903
+	 * @throws EE_Error
904
+	 */
905
+	public function paid()
906
+	{
907
+		return $this->get('REG_paid');
908
+	}
909
+
910
+
911
+	/**
912
+	 * pretty_paid
913
+	 *
914
+	 * @return float
915
+	 * @throws EE_Error
916
+	 */
917
+	public function pretty_paid()
918
+	{
919
+		return $this->get_pretty('REG_paid');
920
+	}
921
+
922
+
923
+	/**
924
+	 * owes_monies_and_can_pay
925
+	 * whether or not this registration has monies owing and it's' status allows payment
926
+	 *
927
+	 * @param array $requires_payment
928
+	 * @return bool
929
+	 * @throws EE_Error
930
+	 */
931
+	public function owes_monies_and_can_pay($requires_payment = array())
932
+	{
933
+		// these reg statuses require payment (if event is not free)
934
+		$requires_payment = ! empty($requires_payment)
935
+			? $requires_payment
936
+			: EEM_Registration::reg_statuses_that_allow_payment();
937
+		if (in_array($this->status_ID(), $requires_payment) &&
938
+			$this->final_price() != 0 &&
939
+			$this->final_price() != $this->paid()
940
+		) {
941
+			return true;
942
+		} else {
943
+			return false;
944
+		}
945
+	}
946
+
947
+
948
+	/**
949
+	 * Prints out the return value of $this->pretty_status()
950
+	 *
951
+	 * @param bool $show_icons
952
+	 * @return void
953
+	 * @throws EE_Error
954
+	 */
955
+	public function e_pretty_status($show_icons = false)
956
+	{
957
+		echo $this->pretty_status($show_icons);
958
+	}
959
+
960
+
961
+	/**
962
+	 * Returns a nice version of the status for displaying to customers
963
+	 *
964
+	 * @param bool $show_icons
965
+	 * @return string
966
+	 * @throws EE_Error
967
+	 */
968
+	public function pretty_status($show_icons = false)
969
+	{
970
+		$status = EEM_Status::instance()->localized_status(
971
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
972
+			false,
973
+			'sentence'
974
+		);
975
+		$icon   = '';
976
+		switch ($this->status_ID()) {
977
+			case EEM_Registration::status_id_approved:
978
+				$icon = $show_icons
979
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
980
+					: '';
981
+				break;
982
+			case EEM_Registration::status_id_pending_payment:
983
+				$icon = $show_icons
984
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
985
+					: '';
986
+				break;
987
+			case EEM_Registration::status_id_not_approved:
988
+				$icon = $show_icons
989
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
990
+					: '';
991
+				break;
992
+			case EEM_Registration::status_id_cancelled:
993
+				$icon = $show_icons
994
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
995
+					: '';
996
+				break;
997
+			case EEM_Registration::status_id_incomplete:
998
+				$icon = $show_icons
999
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1000
+					: '';
1001
+				break;
1002
+			case EEM_Registration::status_id_declined:
1003
+				$icon = $show_icons
1004
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1005
+					: '';
1006
+				break;
1007
+			case EEM_Registration::status_id_wait_list:
1008
+				$icon = $show_icons
1009
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1010
+					: '';
1011
+				break;
1012
+		}
1013
+		return $icon . $status[$this->status_ID()];
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 *        get Attendee Is Going
1019
+	 */
1020
+	public function att_is_going()
1021
+	{
1022
+		return $this->get('REG_att_is_going');
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * Gets related answers
1028
+	 *
1029
+	 * @param array $query_params like EEM_Base::get_all
1030
+	 * @return EE_Answer[]
1031
+	 * @throws EE_Error
1032
+	 */
1033
+	public function answers($query_params = null)
1034
+	{
1035
+		return $this->get_many_related('Answer', $query_params);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * Gets the registration's answer value to the specified question
1041
+	 * (either the question's ID or a question object)
1042
+	 *
1043
+	 * @param EE_Question|int $question
1044
+	 * @param bool            $pretty_value
1045
+	 * @return array|string if pretty_value= true, the result will always be a string
1046
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1047
+	 * will convert it into some kind of string)
1048
+	 * @throws EE_Error
1049
+	 */
1050
+	public function answer_value_to_question($question, $pretty_value = true)
1051
+	{
1052
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1053
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1054
+	}
1055
+
1056
+
1057
+	/**
1058
+	 * question_groups
1059
+	 * returns an array of EE_Question_Group objects for this registration
1060
+	 *
1061
+	 * @return EE_Question_Group[]
1062
+	 * @throws EE_Error
1063
+	 * @throws EntityNotFoundException
1064
+	 */
1065
+	public function question_groups()
1066
+	{
1067
+		$question_groups = array();
1068
+		if ($this->event() instanceof EE_Event) {
1069
+			$question_groups = $this->event()->question_groups(
1070
+				array(
1071
+					array(
1072
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1073
+					),
1074
+					'order_by' => array('QSG_order' => 'ASC'),
1075
+				)
1076
+			);
1077
+		}
1078
+		return $question_groups;
1079
+	}
1080
+
1081
+
1082
+	/**
1083
+	 * count_question_groups
1084
+	 * returns a count of the number of EE_Question_Group objects for this registration
1085
+	 *
1086
+	 * @return int
1087
+	 * @throws EE_Error
1088
+	 * @throws EntityNotFoundException
1089
+	 */
1090
+	public function count_question_groups()
1091
+	{
1092
+		$qg_count = 0;
1093
+		if ($this->event() instanceof EE_Event) {
1094
+			$qg_count = $this->event()->count_related(
1095
+				'Question_Group',
1096
+				array(
1097
+					array(
1098
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1099
+					),
1100
+				)
1101
+			);
1102
+		}
1103
+		return $qg_count;
1104
+	}
1105
+
1106
+
1107
+	/**
1108
+	 * Returns the registration date in the 'standard' string format
1109
+	 * (function may be improved in the future to allow for different formats and timezones)
1110
+	 *
1111
+	 * @return string
1112
+	 * @throws EE_Error
1113
+	 */
1114
+	public function reg_date()
1115
+	{
1116
+		return $this->get_datetime('REG_date');
1117
+	}
1118
+
1119
+
1120
+	/**
1121
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1122
+	 * the ticket this registration purchased, or the datetime they have registered
1123
+	 * to attend)
1124
+	 *
1125
+	 * @return EE_Datetime_Ticket
1126
+	 * @throws EE_Error
1127
+	 */
1128
+	public function datetime_ticket()
1129
+	{
1130
+		return $this->get_first_related('Datetime_Ticket');
1131
+	}
1132
+
1133
+
1134
+	/**
1135
+	 * Sets the registration's datetime_ticket.
1136
+	 *
1137
+	 * @param EE_Datetime_Ticket $datetime_ticket
1138
+	 * @return EE_Datetime_Ticket
1139
+	 * @throws EE_Error
1140
+	 */
1141
+	public function set_datetime_ticket($datetime_ticket)
1142
+	{
1143
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1144
+	}
1145
+
1146
+	/**
1147
+	 * Gets deleted
1148
+	 *
1149
+	 * @return bool
1150
+	 * @throws EE_Error
1151
+	 */
1152
+	public function deleted()
1153
+	{
1154
+		return $this->get('REG_deleted');
1155
+	}
1156
+
1157
+	/**
1158
+	 * Sets deleted
1159
+	 *
1160
+	 * @param boolean $deleted
1161
+	 * @return bool
1162
+	 * @throws EE_Error
1163
+	 * @throws RuntimeException
1164
+	 */
1165
+	public function set_deleted($deleted)
1166
+	{
1167
+		if ($deleted) {
1168
+			$this->delete();
1169
+		} else {
1170
+			$this->restore();
1171
+		}
1172
+	}
1173
+
1174
+
1175
+	/**
1176
+	 * Get the status object of this object
1177
+	 *
1178
+	 * @return EE_Status
1179
+	 * @throws EE_Error
1180
+	 */
1181
+	public function status_obj()
1182
+	{
1183
+		return $this->get_first_related('Status');
1184
+	}
1185
+
1186
+
1187
+	/**
1188
+	 * Returns the number of times this registration has checked into any of the datetimes
1189
+	 * its available for
1190
+	 *
1191
+	 * @return int
1192
+	 * @throws EE_Error
1193
+	 */
1194
+	public function count_checkins()
1195
+	{
1196
+		return $this->get_model()->count_related($this, 'Checkin');
1197
+	}
1198
+
1199
+
1200
+	/**
1201
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1202
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1203
+	 *
1204
+	 * @return int
1205
+	 * @throws EE_Error
1206
+	 */
1207
+	public function count_checkins_not_checkedout()
1208
+	{
1209
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1215
+	 *
1216
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1217
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1218
+	 *                                          consider registration status as well as datetime access.
1219
+	 * @return bool
1220
+	 * @throws EE_Error
1221
+	 */
1222
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1223
+	{
1224
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1225
+
1226
+		//first check registration status
1227
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1228
+			return false;
1229
+		}
1230
+		//is there a datetime ticket that matches this dtt_ID?
1231
+		if (! (EEM_Datetime_Ticket::instance()->exists(array(
1232
+			array(
1233
+				'TKT_ID' => $this->get('TKT_ID'),
1234
+				'DTT_ID' => $DTT_ID,
1235
+			),
1236
+		)))
1237
+		) {
1238
+			return false;
1239
+		}
1240
+
1241
+		//final check is against TKT_uses
1242
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1243
+	}
1244
+
1245
+
1246
+	/**
1247
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1248
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1249
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1250
+	 * then return false.  Otherwise return true.
1251
+	 *
1252
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1253
+	 * @return bool true means can checkin.  false means cannot checkin.
1254
+	 * @throws EE_Error
1255
+	 */
1256
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1257
+	{
1258
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1259
+
1260
+		if (! $DTT_ID) {
1261
+			return false;
1262
+		}
1263
+
1264
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1265
+
1266
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1267
+		// check-in or not.
1268
+		if (! $max_uses || $max_uses === EE_INF) {
1269
+			return true;
1270
+		}
1271
+
1272
+		//does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1273
+		//go ahead and toggle.
1274
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1275
+			return true;
1276
+		}
1277
+
1278
+		//made it here so the last check is whether the number of checkins per unique datetime on this registration
1279
+		//disallows further check-ins.
1280
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1281
+			array(
1282
+				'REG_ID' => $this->ID(),
1283
+				'CHK_in' => true,
1284
+			),
1285
+		), 'DTT_ID', true);
1286
+		// checkins have already reached their max number of uses
1287
+		// so registrant can NOT checkin
1288
+		if ($count_unique_dtt_checkins >= $max_uses) {
1289
+			EE_Error::add_error(
1290
+				esc_html__(
1291
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1292
+					'event_espresso'
1293
+				),
1294
+				__FILE__,
1295
+				__FUNCTION__,
1296
+				__LINE__
1297
+			);
1298
+			return false;
1299
+		}
1300
+		return true;
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 * toggle Check-in status for this registration
1306
+	 * Check-ins are toggled in the following order:
1307
+	 * never checked in -> checked in
1308
+	 * checked in -> checked out
1309
+	 * checked out -> checked in
1310
+	 *
1311
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1312
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1313
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1314
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1315
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1316
+	 * @throws EE_Error
1317
+	 */
1318
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1319
+	{
1320
+		if (empty($DTT_ID)) {
1321
+			$datetime = $this->get_latest_related_datetime();
1322
+			$DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1323
+			// verify the registration can checkin for the given DTT_ID
1324
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1325
+			EE_Error::add_error(
1326
+				sprintf(
1327
+					esc_html__(
1328
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1329
+						'event_espresso'
1330
+					),
1331
+					$this->ID(),
1332
+					$DTT_ID
1333
+				),
1334
+				__FILE__,
1335
+				__FUNCTION__,
1336
+				__LINE__
1337
+			);
1338
+			return false;
1339
+		}
1340
+		$status_paths = array(
1341
+			EE_Registration::checkin_status_never => EE_Registration::checkin_status_in,
1342
+			EE_Registration::checkin_status_in    => EE_Registration::checkin_status_out,
1343
+			EE_Registration::checkin_status_out   => EE_Registration::checkin_status_in,
1344
+		);
1345
+		//start by getting the current status so we know what status we'll be changing to.
1346
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1347
+		$status_to  = $status_paths[$cur_status];
1348
+		// database only records true for checked IN or false for checked OUT
1349
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1350
+		$new_status = $status_to === EE_Registration::checkin_status_in ? true : false;
1351
+		// add relation - note Check-ins are always creating new rows
1352
+		// because we are keeping track of Check-ins over time.
1353
+		// Eventually we'll probably want to show a list table
1354
+		// for the individual Check-ins so that they can be managed.
1355
+		$checkin = EE_Checkin::new_instance(array(
1356
+			'REG_ID' => $this->ID(),
1357
+			'DTT_ID' => $DTT_ID,
1358
+			'CHK_in' => $new_status,
1359
+		));
1360
+		// if the record could not be saved then return false
1361
+		if ($checkin->save() === 0) {
1362
+			if (WP_DEBUG) {
1363
+				global $wpdb;
1364
+				$error = sprintf(
1365
+					esc_html__(
1366
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1367
+						'event_espresso'
1368
+					),
1369
+					'<br />',
1370
+					$wpdb->last_error
1371
+				);
1372
+			} else {
1373
+				$error = esc_html__(
1374
+					'Registration check in update failed because of an unknown database error',
1375
+					'event_espresso'
1376
+				);
1377
+			}
1378
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1379
+			return false;
1380
+		}
1381
+		return $status_to;
1382
+	}
1383
+
1384
+
1385
+	/**
1386
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1387
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1388
+	 *
1389
+	 * @return EE_Datetime|null
1390
+	 * @throws \EE_Error
1391
+	 */
1392
+	public function get_latest_related_datetime()
1393
+	{
1394
+		return EEM_Datetime::instance()->get_one(
1395
+			array(
1396
+				array(
1397
+					'Ticket.Registration.REG_ID' => $this->ID(),
1398
+				),
1399
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1400
+			)
1401
+		);
1402
+	}
1403
+
1404
+
1405
+	/**
1406
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1407
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1408
+	 *
1409
+	 * @throws \EE_Error
1410
+	 */
1411
+	public function get_earliest_related_datetime()
1412
+	{
1413
+		return EEM_Datetime::instance()->get_one(
1414
+			array(
1415
+				array(
1416
+					'Ticket.Registration.REG_ID' => $this->ID(),
1417
+				),
1418
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1419
+			)
1420
+		);
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * This method simply returns the check-in status for this registration and the given datetime.
1426
+	 * If neither the datetime nor the checkin values are provided as arguments,
1427
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1428
+	 *
1429
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1430
+	 *                            (if empty we'll get the primary datetime for
1431
+	 *                            this registration (via event) and use it's ID);
1432
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1433
+	 * @return int                Integer representing Check-in status.
1434
+	 * @throws \EE_Error
1435
+	 */
1436
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1437
+	{
1438
+		$checkin_query_params = array(
1439
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1440
+		);
1441
+
1442
+		if ($DTT_ID > 0) {
1443
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1444
+		}
1445
+
1446
+		//get checkin object (if exists)
1447
+		$checkin = $checkin instanceof EE_Checkin
1448
+			? $checkin
1449
+			: $this->get_first_related('Checkin', $checkin_query_params);
1450
+		if ($checkin instanceof EE_Checkin) {
1451
+			if ($checkin->get('CHK_in')) {
1452
+				return EE_Registration::checkin_status_in; //checked in
1453
+			}
1454
+			return EE_Registration::checkin_status_out; //had checked in but is now checked out.
1455
+		}
1456
+		return EE_Registration::checkin_status_never; //never been checked in
1457
+	}
1458
+
1459
+
1460
+	/**
1461
+	 * This method returns a localized message for the toggled Check-in message.
1462
+	 *
1463
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1464
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1465
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1466
+	 *                     message can be customized with the attendee name.
1467
+	 * @return string internationalized message
1468
+	 * @throws EE_Error
1469
+	 */
1470
+	public function get_checkin_msg($DTT_ID, $error = false)
1471
+	{
1472
+		//let's get the attendee first so we can include the name of the attendee
1473
+		$attendee = $this->get_first_related('Attendee');
1474
+		if ($attendee instanceof EE_Attendee) {
1475
+			if ($error) {
1476
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1477
+			}
1478
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1479
+			//what is the status message going to be?
1480
+			switch ($cur_status) {
1481
+				case EE_Registration::checkin_status_never:
1482
+					return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1483
+						$attendee->full_name());
1484
+					break;
1485
+				case EE_Registration::checkin_status_in:
1486
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1487
+					break;
1488
+				case EE_Registration::checkin_status_out:
1489
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1490
+					break;
1491
+			}
1492
+		}
1493
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1494
+	}
1495
+
1496
+
1497
+	/**
1498
+	 * Returns the related EE_Transaction to this registration
1499
+	 *
1500
+	 * @return EE_Transaction
1501
+	 * @throws EE_Error
1502
+	 * @throws EntityNotFoundException
1503
+	 */
1504
+	public function transaction()
1505
+	{
1506
+		$transaction = $this->get_first_related('Transaction');
1507
+		if (! $transaction instanceof \EE_Transaction) {
1508
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1509
+		}
1510
+		return $transaction;
1511
+	}
1512
+
1513
+
1514
+	/**
1515
+	 *        get Registration Code
1516
+	 */
1517
+	public function reg_code()
1518
+	{
1519
+		return $this->get('REG_code');
1520
+	}
1521
+
1522
+
1523
+	/**
1524
+	 *        get Transaction ID
1525
+	 */
1526
+	public function transaction_ID()
1527
+	{
1528
+		return $this->get('TXN_ID');
1529
+	}
1530
+
1531
+
1532
+	/**
1533
+	 * @return int
1534
+	 * @throws EE_Error
1535
+	 */
1536
+	public function ticket_ID()
1537
+	{
1538
+		return $this->get('TKT_ID');
1539
+	}
1540
+
1541
+
1542
+	/**
1543
+	 *        Set Registration Code
1544
+	 *
1545
+	 * @access    public
1546
+	 * @param    string  $REG_code Registration Code
1547
+	 * @param    boolean $use_default
1548
+	 * @throws EE_Error
1549
+	 */
1550
+	public function set_reg_code($REG_code, $use_default = false)
1551
+	{
1552
+		if (empty($REG_code)) {
1553
+			EE_Error::add_error(
1554
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1555
+				__FILE__,
1556
+				__FUNCTION__,
1557
+				__LINE__
1558
+			);
1559
+			return;
1560
+		}
1561
+		if (! $this->reg_code()) {
1562
+			parent::set('REG_code', $REG_code, $use_default);
1563
+		} else {
1564
+			EE_Error::doing_it_wrong(
1565
+				__CLASS__ . '::' . __FUNCTION__,
1566
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1567
+				'4.6.0'
1568
+			);
1569
+		}
1570
+	}
1571
+
1572
+
1573
+	/**
1574
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1575
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1576
+	 *    $registration->transaction()->registrations();
1577
+	 *
1578
+	 * @since 4.5.0
1579
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1580
+	 * @throws EE_Error
1581
+	 */
1582
+	public function get_all_other_registrations_in_group()
1583
+	{
1584
+		if ($this->group_size() < 2) {
1585
+			return array();
1586
+		}
1587
+
1588
+		$query[0] = array(
1589
+			'TXN_ID' => $this->transaction_ID(),
1590
+			'REG_ID' => array('!=', $this->ID()),
1591
+			'TKT_ID' => $this->ticket_ID(),
1592
+		);
1593
+		/** @var EE_Registration[] $registrations */
1594
+		$registrations = $this->get_model()->get_all($query);
1595
+		return $registrations;
1596
+	}
1597
+
1598
+	/**
1599
+	 * Return the link to the admin details for the object.
1600
+	 *
1601
+	 * @return string
1602
+	 * @throws EE_Error
1603
+	 */
1604
+	public function get_admin_details_link()
1605
+	{
1606
+		EE_Registry::instance()->load_helper('URL');
1607
+		return EEH_URL::add_query_args_and_nonce(
1608
+			array(
1609
+				'page'    => 'espresso_registrations',
1610
+				'action'  => 'view_registration',
1611
+				'_REG_ID' => $this->ID(),
1612
+			),
1613
+			admin_url('admin.php')
1614
+		);
1615
+	}
1616
+
1617
+	/**
1618
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1619
+	 *
1620
+	 * @return string
1621
+	 * @throws EE_Error
1622
+	 */
1623
+	public function get_admin_edit_link()
1624
+	{
1625
+		return $this->get_admin_details_link();
1626
+	}
1627
+
1628
+	/**
1629
+	 * Returns the link to a settings page for the object.
1630
+	 *
1631
+	 * @return string
1632
+	 * @throws EE_Error
1633
+	 */
1634
+	public function get_admin_settings_link()
1635
+	{
1636
+		return $this->get_admin_details_link();
1637
+	}
1638
+
1639
+	/**
1640
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1641
+	 *
1642
+	 * @return string
1643
+	 */
1644
+	public function get_admin_overview_link()
1645
+	{
1646
+		EE_Registry::instance()->load_helper('URL');
1647
+		return EEH_URL::add_query_args_and_nonce(
1648
+			array(
1649
+				'page' => 'espresso_registrations',
1650
+			),
1651
+			admin_url('admin.php')
1652
+		);
1653
+	}
1654
+
1655
+
1656
+	/**
1657
+	 * @param array $query_params
1658
+	 * @return \EE_Registration[]
1659
+	 * @throws \EE_Error
1660
+	 */
1661
+	public function payments($query_params = array())
1662
+	{
1663
+		return $this->get_many_related('Payment', $query_params);
1664
+	}
1665
+
1666
+
1667
+	/**
1668
+	 * @param array $query_params
1669
+	 * @return \EE_Registration_Payment[]
1670
+	 * @throws \EE_Error
1671
+	 */
1672
+	public function registration_payments($query_params = array())
1673
+	{
1674
+		return $this->get_many_related('Registration_Payment', $query_params);
1675
+	}
1676
+
1677
+
1678
+	/**
1679
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1680
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1681
+	 *
1682
+	 * @return EE_Payment_Method|null
1683
+	 */
1684
+	public function payment_method()
1685
+	{
1686
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1687
+	}
1688
+
1689
+
1690
+	/**
1691
+	 * @return \EE_Line_Item
1692
+	 * @throws EntityNotFoundException
1693
+	 * @throws \EE_Error
1694
+	 */
1695
+	public function ticket_line_item()
1696
+	{
1697
+		$ticket            = $this->ticket();
1698
+		$transaction       = $this->transaction();
1699
+		$line_item         = null;
1700
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1701
+			$transaction->total_line_item(),
1702
+			'Ticket',
1703
+			array($ticket->ID())
1704
+		);
1705
+		foreach ($ticket_line_items as $ticket_line_item) {
1706
+			if (
1707
+				$ticket_line_item instanceof \EE_Line_Item
1708
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1709
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1710
+			) {
1711
+				$line_item = $ticket_line_item;
1712
+				break;
1713
+			}
1714
+		}
1715
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1716
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1717
+		}
1718
+		return $line_item;
1719
+	}
1720
+
1721
+
1722
+	/**
1723
+	 * Soft Deletes this model object.
1724
+	 *
1725
+	 * @return boolean | int
1726
+	 * @throws \RuntimeException
1727
+	 * @throws \EE_Error
1728
+	 */
1729
+	public function delete()
1730
+	{
1731
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1732
+			$this->set_status(EEM_Registration::status_id_cancelled);
1733
+		}
1734
+		return parent::delete();
1735
+	}
1736
+
1737
+
1738
+	/**
1739
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1740
+	 *
1741
+	 * @throws \EE_Error
1742
+	 * @throws \RuntimeException
1743
+	 */
1744
+	public function restore()
1745
+	{
1746
+		$previous_status = $this->get_extra_meta(
1747
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1748
+			true,
1749
+			EEM_Registration::status_id_cancelled
1750
+		);
1751
+		if ($previous_status) {
1752
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1753
+			$this->set_status($previous_status);
1754
+		}
1755
+		return parent::restore();
1756
+	}
1757
+
1758
+
1759
+
1760
+	/*************************** DEPRECATED ***************************/
1761
+
1762
+
1763
+	/**
1764
+	 * @deprecated
1765
+	 * @since     4.7.0
1766
+	 * @access    public
1767
+	 */
1768
+	public function price_paid()
1769
+	{
1770
+		EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1771
+			esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1772
+			'4.7.0');
1773
+		return $this->final_price();
1774
+	}
1775
+
1776
+
1777
+	/**
1778
+	 * @deprecated
1779
+	 * @since     4.7.0
1780
+	 * @access    public
1781
+	 * @param    float $REG_final_price
1782
+	 * @throws EE_Error
1783
+	 * @throws RuntimeException
1784
+	 */
1785
+	public function set_price_paid($REG_final_price = 0.00)
1786
+	{
1787
+		EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1788
+			esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1789
+			'4.7.0');
1790
+		$this->set_final_price($REG_final_price);
1791
+	}
1792
+
1793
+
1794
+	/**
1795
+	 * @deprecated
1796
+	 * @since 4.7.0
1797
+	 * @return string
1798
+	 * @throws EE_Error
1799
+	 */
1800
+	public function pretty_price_paid()
1801
+	{
1802
+		EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1803
+			esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1804
+				'event_espresso'), '4.7.0');
1805
+		return $this->pretty_final_price();
1806
+	}
1807
+
1808
+
1809
+	/**
1810
+	 * Gets the primary datetime related to this registration via the related Event to this registration
1811
+	 *
1812
+	 * @deprecated 4.9.17
1813
+	 * @return EE_Datetime
1814
+	 * @throws EE_Error
1815
+	 * @throws EntityNotFoundException
1816
+	 */
1817
+	public function get_related_primary_datetime()
1818
+	{
1819
+		EE_Error::doing_it_wrong(
1820
+			__METHOD__,
1821
+			esc_html__(
1822
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1823
+				'event_espresso'
1824
+			),
1825
+			'4.9.17',
1826
+			'5.0.0'
1827
+		);
1828
+		return $this->event()->primary_datetime();
1829
+	}
1830 1830
 
1831 1831
 
1832 1832
 }
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 2 patches
Indentation   +1856 added lines, -1856 removed lines patch added patch discarded remove patch
@@ -5,7 +5,7 @@  discard block
 block discarded – undo
5 5
 use EventEspresso\core\exceptions\InvalidEntityException;
6 6
 
7 7
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
8
-    exit('No direct script access allowed');
8
+	exit('No direct script access allowed');
9 9
 }
10 10
 
11 11
 
@@ -20,1861 +20,1861 @@  discard block
 block discarded – undo
20 20
 class EED_Single_Page_Checkout extends EED_Module
21 21
 {
22 22
 
23
-    /**
24
-     * $_initialized - has the SPCO controller already been initialized ?
25
-     *
26
-     * @access private
27
-     * @var bool $_initialized
28
-     */
29
-    private static $_initialized = false;
30
-
31
-
32
-    /**
33
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
34
-     *
35
-     * @access private
36
-     * @var bool $_valid_checkout
37
-     */
38
-    private static $_checkout_verified = true;
39
-
40
-    /**
41
-     *    $_reg_steps_array - holds initial array of reg steps
42
-     *
43
-     * @access private
44
-     * @var array $_reg_steps_array
45
-     */
46
-    private static $_reg_steps_array = array();
47
-
48
-    /**
49
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
50
-     *
51
-     * @access public
52
-     * @var EE_Checkout $checkout
53
-     */
54
-    public $checkout;
55
-
56
-
57
-
58
-    /**
59
-     * @return EED_Module|EED_Single_Page_Checkout
60
-     */
61
-    public static function instance()
62
-    {
63
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
64
-        return parent::get_instance(__CLASS__);
65
-    }
66
-
67
-
68
-
69
-    /**
70
-     * @return EE_CART
71
-     */
72
-    public function cart()
73
-    {
74
-        return $this->checkout->cart;
75
-    }
76
-
77
-
78
-
79
-    /**
80
-     * @return EE_Transaction
81
-     */
82
-    public function transaction()
83
-    {
84
-        return $this->checkout->transaction;
85
-    }
86
-
87
-
88
-
89
-    /**
90
-     *    set_hooks - for hooking into EE Core, other modules, etc
91
-     *
92
-     * @access    public
93
-     * @return    void
94
-     * @throws EE_Error
95
-     */
96
-    public static function set_hooks()
97
-    {
98
-        EED_Single_Page_Checkout::set_definitions();
99
-    }
100
-
101
-
102
-
103
-    /**
104
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
-     *
106
-     * @access    public
107
-     * @return    void
108
-     * @throws EE_Error
109
-     */
110
-    public static function set_hooks_admin()
111
-    {
112
-        EED_Single_Page_Checkout::set_definitions();
113
-        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
114
-            return;
115
-        }
116
-        // going to start an output buffer in case anything gets accidentally output
117
-        // that might disrupt our JSON response
118
-        ob_start();
119
-        EED_Single_Page_Checkout::load_request_handler();
120
-        EED_Single_Page_Checkout::load_reg_steps();
121
-        // set ajax hooks
122
-        add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
123
-        add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
124
-        add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
125
-        add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
126
-        add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
127
-        add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     *    process ajax request
134
-     *
135
-     * @param string $ajax_action
136
-     * @throws EE_Error
137
-     */
138
-    public static function process_ajax_request($ajax_action)
139
-    {
140
-        EE_Registry::instance()->REQ->set('action', $ajax_action);
141
-        EED_Single_Page_Checkout::instance()->_initialize();
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     *    ajax display registration step
148
-     *
149
-     * @throws EE_Error
150
-     */
151
-    public static function display_reg_step()
152
-    {
153
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
154
-    }
155
-
156
-
157
-
158
-    /**
159
-     *    ajax process registration step
160
-     *
161
-     * @throws EE_Error
162
-     */
163
-    public static function process_reg_step()
164
-    {
165
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
166
-    }
167
-
168
-
169
-
170
-    /**
171
-     *    ajax process registration step
172
-     *
173
-     * @throws EE_Error
174
-     */
175
-    public static function update_reg_step()
176
-    {
177
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
178
-    }
179
-
180
-
181
-
182
-    /**
183
-     *   update_checkout
184
-     *
185
-     * @access public
186
-     * @return void
187
-     * @throws EE_Error
188
-     */
189
-    public static function update_checkout()
190
-    {
191
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
192
-    }
193
-
194
-
195
-
196
-    /**
197
-     *    load_request_handler
198
-     *
199
-     * @access    public
200
-     * @return    void
201
-     */
202
-    public static function load_request_handler()
203
-    {
204
-        // load core Request_Handler class
205
-        if (EE_Registry::instance()->REQ !== null) {
206
-            EE_Registry::instance()->load_core('Request_Handler');
207
-        }
208
-    }
209
-
210
-
211
-
212
-    /**
213
-     *    set_definitions
214
-     *
215
-     * @access    public
216
-     * @return    void
217
-     * @throws EE_Error
218
-     */
219
-    public static function set_definitions()
220
-    {
221
-        if(defined('SPCO_BASE_PATH')) {
222
-            return;
223
-        }
224
-        define(
225
-            'SPCO_BASE_PATH',
226
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
227
-        );
228
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
234
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
236
-            __('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
237
-                'event_espresso'),
238
-            '<h4 class="important-notice">',
239
-            '</h4>',
240
-            '<br />',
241
-            '<p>',
242
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
243
-            '">',
244
-            '</a>',
245
-            '</p>'
246
-        );
247
-    }
248
-
249
-
250
-
251
-    /**
252
-     * load_reg_steps
253
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
254
-     *
255
-     * @access    private
256
-     * @throws EE_Error
257
-     */
258
-    public static function load_reg_steps()
259
-    {
260
-        static $reg_steps_loaded = false;
261
-        if ($reg_steps_loaded) {
262
-            return;
263
-        }
264
-        // filter list of reg_steps
265
-        $reg_steps_to_load = (array)apply_filters(
266
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
267
-            EED_Single_Page_Checkout::get_reg_steps()
268
-        );
269
-        // sort by key (order)
270
-        ksort($reg_steps_to_load);
271
-        // loop through folders
272
-        foreach ($reg_steps_to_load as $order => $reg_step) {
273
-            // we need a
274
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
275
-                // copy over to the reg_steps_array
276
-                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
277
-                // register custom key route for each reg step
278
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
279
-                EE_Config::register_route(
280
-                    $reg_step['slug'],
281
-                    'EED_Single_Page_Checkout',
282
-                    'run',
283
-                    'step'
284
-                );
285
-                // add AJAX or other hooks
286
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
287
-                    // setup autoloaders if necessary
288
-                    if ( ! class_exists($reg_step['class_name'])) {
289
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
290
-                            $reg_step['file_path'],
291
-                            true
292
-                        );
293
-                    }
294
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
295
-                        call_user_func(array($reg_step['class_name'], 'set_hooks'));
296
-                    }
297
-                }
298
-            }
299
-        }
300
-        $reg_steps_loaded = true;
301
-    }
302
-
303
-
304
-
305
-    /**
306
-     *    get_reg_steps
307
-     *
308
-     * @access    public
309
-     * @return    array
310
-     */
311
-    public static function get_reg_steps()
312
-    {
313
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
314
-        if (empty($reg_steps)) {
315
-            $reg_steps = array(
316
-                10  => array(
317
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
318
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
319
-                    'slug'       => 'attendee_information',
320
-                    'has_hooks'  => false,
321
-                ),
322
-                20  => array(
323
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
324
-                    'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
325
-                    'slug'       => 'registration_confirmation',
326
-                    'has_hooks'  => false,
327
-                ),
328
-                30  => array(
329
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
330
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
331
-                    'slug'       => 'payment_options',
332
-                    'has_hooks'  => true,
333
-                ),
334
-                999 => array(
335
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
336
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
337
-                    'slug'       => 'finalize_registration',
338
-                    'has_hooks'  => false,
339
-                ),
340
-            );
341
-        }
342
-        return $reg_steps;
343
-    }
344
-
345
-
346
-
347
-    /**
348
-     *    registration_checkout_for_admin
349
-     *
350
-     * @access    public
351
-     * @return    string
352
-     * @throws EE_Error
353
-     */
354
-    public static function registration_checkout_for_admin()
355
-    {
356
-        EED_Single_Page_Checkout::load_request_handler();
357
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
358
-        EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
359
-        EE_Registry::instance()->REQ->set('process_form_submission', false);
360
-        EED_Single_Page_Checkout::instance()->_initialize();
361
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
362
-        return EE_Registry::instance()->REQ->get_output();
363
-    }
364
-
365
-
366
-
367
-    /**
368
-     * process_registration_from_admin
369
-     *
370
-     * @access public
371
-     * @return \EE_Transaction
372
-     * @throws EE_Error
373
-     */
374
-    public static function process_registration_from_admin()
375
-    {
376
-        EED_Single_Page_Checkout::load_request_handler();
377
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
378
-        EE_Registry::instance()->REQ->set('action', 'process_reg_step');
379
-        EE_Registry::instance()->REQ->set('process_form_submission', true);
380
-        EED_Single_Page_Checkout::instance()->_initialize();
381
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
382
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
383
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
384
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
385
-                if ($final_reg_step->process_reg_step()) {
386
-                    $final_reg_step->set_completed();
387
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
388
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
389
-                }
390
-            }
391
-        }
392
-        return null;
393
-    }
394
-
395
-
396
-
397
-    /**
398
-     *    run
399
-     *
400
-     * @access    public
401
-     * @param WP_Query $WP_Query
402
-     * @return    void
403
-     * @throws EE_Error
404
-     */
405
-    public function run($WP_Query)
406
-    {
407
-        if (
408
-            $WP_Query instanceof WP_Query
409
-            && $WP_Query->is_main_query()
410
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
411
-            && $this->_is_reg_checkout()
412
-        ) {
413
-            $this->_initialize();
414
-        }
415
-    }
416
-
417
-
418
-
419
-    /**
420
-     * determines whether current url matches reg page url
421
-     *
422
-     * @return bool
423
-     */
424
-    protected function _is_reg_checkout()
425
-    {
426
-        // get current permalink for reg page without any extra query args
427
-        $reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
428
-        // get request URI for current request, but without the scheme or host
429
-        $current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
430
-        $current_request_uri = html_entity_decode($current_request_uri);
431
-        // get array of query args from the current request URI
432
-        $query_args = \EEH_URL::get_query_string($current_request_uri);
433
-        // grab page id if it is set
434
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
435
-        // and remove the page id from the query args (we will re-add it later)
436
-        unset($query_args['page_id']);
437
-        // now strip all query args from current request URI
438
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
439
-        // and re-add the page id if it was set
440
-        if ($page_id) {
441
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
442
-        }
443
-        // remove slashes and ?
444
-        $current_request_uri = trim($current_request_uri, '?/');
445
-        // is current request URI part of the known full reg page URL ?
446
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
447
-    }
448
-
449
-
450
-
451
-    /**
452
-     * @param WP_Query $wp_query
453
-     * @return    void
454
-     * @throws EE_Error
455
-     */
456
-    public static function init($wp_query)
457
-    {
458
-        EED_Single_Page_Checkout::instance()->run($wp_query);
459
-    }
460
-
461
-
462
-
463
-    /**
464
-     *    _initialize - initial module setup
465
-     *
466
-     * @access    private
467
-     * @throws EE_Error
468
-     * @return    void
469
-     */
470
-    private function _initialize()
471
-    {
472
-        // ensure SPCO doesn't run twice
473
-        if (EED_Single_Page_Checkout::$_initialized) {
474
-            return;
475
-        }
476
-        try {
477
-            EED_Single_Page_Checkout::load_reg_steps();
478
-            $this->_verify_session();
479
-            // setup the EE_Checkout object
480
-            $this->checkout = $this->_initialize_checkout();
481
-            // filter checkout
482
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
483
-            // get the $_GET
484
-            $this->_get_request_vars();
485
-            if ($this->_block_bots()) {
486
-                return;
487
-            }
488
-            // filter continue_reg
489
-            $this->checkout->continue_reg = apply_filters(
490
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
491
-                true,
492
-                $this->checkout
493
-            );
494
-            // load the reg steps array
495
-            if ( ! $this->_load_and_instantiate_reg_steps()) {
496
-                EED_Single_Page_Checkout::$_initialized = true;
497
-                return;
498
-            }
499
-            // set the current step
500
-            $this->checkout->set_current_step($this->checkout->step);
501
-            // and the next step
502
-            $this->checkout->set_next_step();
503
-            // verify that everything has been setup correctly
504
-            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
505
-                EED_Single_Page_Checkout::$_initialized = true;
506
-                return;
507
-            }
508
-            // lock the transaction
509
-            $this->checkout->transaction->lock();
510
-            // make sure all of our cached objects are added to their respective model entity mappers
511
-            $this->checkout->refresh_all_entities();
512
-            // set amount owing
513
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
514
-            // initialize each reg step, which gives them the chance to potentially alter the process
515
-            $this->_initialize_reg_steps();
516
-            // DEBUG LOG
517
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
518
-            // get reg form
519
-            if( ! $this->_check_form_submission()) {
520
-                EED_Single_Page_Checkout::$_initialized = true;
521
-                return;
522
-            }
523
-            // checkout the action!!!
524
-            $this->_process_form_action();
525
-            // add some style and make it dance
526
-            $this->add_styles_and_scripts();
527
-            // kk... SPCO has successfully run
528
-            EED_Single_Page_Checkout::$_initialized = true;
529
-            // set no cache headers and constants
530
-            EE_System::do_not_cache();
531
-            // add anchor
532
-            add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
533
-            // remove transaction lock
534
-            add_action('shutdown', array($this, 'unlock_transaction'), 1);
535
-        } catch (Exception $e) {
536
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
537
-        }
538
-    }
539
-
540
-
541
-
542
-    /**
543
-     *    _verify_session
544
-     * checks that the session is valid and not expired
545
-     *
546
-     * @access    private
547
-     * @throws EE_Error
548
-     */
549
-    private function _verify_session()
550
-    {
551
-        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
552
-            throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
553
-        }
554
-        $clear_session_requested = filter_var(
555
-            EE_Registry::instance()->REQ->get('clear_session', false),
556
-            FILTER_VALIDATE_BOOLEAN
557
-        );
558
-        // is session still valid ?
559
-        if ($clear_session_requested
560
-            || ( EE_Registry::instance()->SSN->expired()
561
-              && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
562
-            )
563
-        ) {
564
-            $this->checkout = new EE_Checkout();
565
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
566
-            // EE_Registry::instance()->SSN->reset_cart();
567
-            // EE_Registry::instance()->SSN->reset_checkout();
568
-            // EE_Registry::instance()->SSN->reset_transaction();
569
-            if (! $clear_session_requested) {
570
-                EE_Error::add_attention(
571
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
572
-                    __FILE__, __FUNCTION__, __LINE__
573
-                );
574
-            }
575
-            // EE_Registry::instance()->SSN->reset_expired();
576
-        }
577
-    }
578
-
579
-
580
-
581
-    /**
582
-     *    _initialize_checkout
583
-     * loads and instantiates EE_Checkout
584
-     *
585
-     * @access    private
586
-     * @throws EE_Error
587
-     * @return EE_Checkout
588
-     */
589
-    private function _initialize_checkout()
590
-    {
591
-        // look in session for existing checkout
592
-        /** @type EE_Checkout $checkout */
593
-        $checkout = EE_Registry::instance()->SSN->checkout();
594
-        // verify
595
-        if ( ! $checkout instanceof EE_Checkout) {
596
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
597
-            $checkout = EE_Registry::instance()->load_file(
598
-                SPCO_INC_PATH,
599
-                'EE_Checkout',
600
-                'class', array(),
601
-                false
602
-            );
603
-        } else {
604
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
605
-                $this->unlock_transaction();
606
-                wp_safe_redirect($checkout->redirect_url);
607
-                exit();
608
-            }
609
-        }
610
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
611
-        // verify again
612
-        if ( ! $checkout instanceof EE_Checkout) {
613
-            throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
614
-        }
615
-        // reset anything that needs a clean slate for each request
616
-        $checkout->reset_for_current_request();
617
-        return $checkout;
618
-    }
619
-
620
-
621
-
622
-    /**
623
-     *    _get_request_vars
624
-     *
625
-     * @access    private
626
-     * @return    void
627
-     * @throws EE_Error
628
-     */
629
-    private function _get_request_vars()
630
-    {
631
-        // load classes
632
-        EED_Single_Page_Checkout::load_request_handler();
633
-        //make sure this request is marked as belonging to EE
634
-        EE_Registry::instance()->REQ->set_espresso_page(true);
635
-        // which step is being requested ?
636
-        $this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
637
-        // which step is being edited ?
638
-        $this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
639
-        // and what we're doing on the current step
640
-        $this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
641
-        // timestamp
642
-        $this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
643
-        // returning to edit ?
644
-        $this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
645
-        // or some other kind of revisit ?
646
-        $this->checkout->revisit = filter_var(
647
-            EE_Registry::instance()->REQ->get('revisit', false),
648
-            FILTER_VALIDATE_BOOLEAN
649
-        );
650
-        // and whether or not to generate a reg form for this request
651
-        $this->checkout->generate_reg_form = filter_var(
652
-            EE_Registry::instance()->REQ->get('generate_reg_form', true),
653
-            FILTER_VALIDATE_BOOLEAN
654
-        );
655
-        // and whether or not to process a reg form submission for this request
656
-        $this->checkout->process_form_submission = filter_var(
657
-            EE_Registry::instance()->REQ->get(
658
-                'process_form_submission',
659
-                $this->checkout->action === 'process_reg_step'
660
-            ),
661
-            FILTER_VALIDATE_BOOLEAN
662
-        );
663
-        $this->checkout->process_form_submission = filter_var(
664
-            $this->checkout->action !== 'display_spco_reg_step'
665
-                ? $this->checkout->process_form_submission
666
-                : false,
667
-            FILTER_VALIDATE_BOOLEAN
668
-        );
669
-        // $this->_display_request_vars();
670
-    }
671
-
672
-
673
-
674
-    /**
675
-     *  _display_request_vars
676
-     *
677
-     * @access    protected
678
-     * @return    void
679
-     */
680
-    protected function _display_request_vars()
681
-    {
682
-        if ( ! WP_DEBUG) {
683
-            return;
684
-        }
685
-        EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
686
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
687
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
688
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
689
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
690
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
691
-        EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
692
-        EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
693
-    }
694
-
695
-
696
-
697
-    /**
698
-     * _block_bots
699
-     * checks that the incoming request has either of the following set:
700
-     *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
701
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
702
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
703
-     * then where you coming from man?
704
-     *
705
-     * @return boolean
706
-     */
707
-    private function _block_bots()
708
-    {
709
-        $invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
710
-        if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
711
-            return true;
712
-        }
713
-        return false;
714
-    }
715
-
716
-
717
-
718
-    /**
719
-     *    _get_first_step
720
-     *  gets slug for first step in $_reg_steps_array
721
-     *
722
-     * @access    private
723
-     * @throws EE_Error
724
-     * @return    string
725
-     */
726
-    private function _get_first_step()
727
-    {
728
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
729
-        return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
730
-    }
731
-
732
-
733
-
734
-    /**
735
-     *    _load_and_instantiate_reg_steps
736
-     *  instantiates each reg step based on the loaded reg_steps array
737
-     *
738
-     * @access    private
739
-     * @throws EE_Error
740
-     * @return    bool
741
-     */
742
-    private function _load_and_instantiate_reg_steps()
743
-    {
744
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
745
-        // have reg_steps already been instantiated ?
746
-        if (
747
-            empty($this->checkout->reg_steps)
748
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
749
-        ) {
750
-            // if not, then loop through raw reg steps array
751
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
752
-                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
753
-                    return false;
754
-                }
755
-            }
756
-            EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
757
-            EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
758
-            // skip the registration_confirmation page ?
759
-            if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
760
-                // just remove it from the reg steps array
761
-                $this->checkout->remove_reg_step('registration_confirmation', false);
762
-            } else if (
763
-                isset($this->checkout->reg_steps['registration_confirmation'])
764
-                && EE_Registry::instance()->CFG->registration->reg_confirmation_last
765
-            ) {
766
-                // set the order to something big like 100
767
-                $this->checkout->set_reg_step_order('registration_confirmation', 100);
768
-            }
769
-            // filter the array for good luck
770
-            $this->checkout->reg_steps = apply_filters(
771
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
772
-                $this->checkout->reg_steps
773
-            );
774
-            // finally re-sort based on the reg step class order properties
775
-            $this->checkout->sort_reg_steps();
776
-        } else {
777
-            foreach ($this->checkout->reg_steps as $reg_step) {
778
-                // set all current step stati to FALSE
779
-                $reg_step->set_is_current_step(false);
780
-            }
781
-        }
782
-        if (empty($this->checkout->reg_steps)) {
783
-            EE_Error::add_error(
784
-                __('No Reg Steps were loaded..', 'event_espresso'),
785
-                __FILE__, __FUNCTION__, __LINE__
786
-            );
787
-            return false;
788
-        }
789
-        // make reg step details available to JS
790
-        $this->checkout->set_reg_step_JSON_info();
791
-        return true;
792
-    }
793
-
794
-
795
-
796
-    /**
797
-     *     _load_and_instantiate_reg_step
798
-     *
799
-     * @access    private
800
-     * @param array $reg_step
801
-     * @param int   $order
802
-     * @return bool
803
-     */
804
-    private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
805
-    {
806
-        // we need a file_path, class_name, and slug to add a reg step
807
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
808
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
809
-            if (
810
-                $this->checkout->reg_url_link
811
-                && $this->checkout->step !== $reg_step['slug']
812
-                && $reg_step['slug'] !== 'finalize_registration'
813
-                // normally at this point we would NOT load the reg step, but this filter can change that
814
-                && apply_filters(
815
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
816
-                    true,
817
-                    $reg_step,
818
-                    $this->checkout
819
-                )
820
-            ) {
821
-                return true;
822
-            }
823
-            // instantiate step class using file path and class name
824
-            $reg_step_obj = EE_Registry::instance()->load_file(
825
-                $reg_step['file_path'],
826
-                $reg_step['class_name'],
827
-                'class',
828
-                $this->checkout,
829
-                false
830
-            );
831
-            // did we gets the goods ?
832
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
833
-                // set reg step order based on config
834
-                $reg_step_obj->set_order($order);
835
-                // add instantiated reg step object to the master reg steps array
836
-                $this->checkout->add_reg_step($reg_step_obj);
837
-            } else {
838
-                EE_Error::add_error(
839
-                    __('The current step could not be set.', 'event_espresso'),
840
-                    __FILE__, __FUNCTION__, __LINE__
841
-                );
842
-                return false;
843
-            }
844
-        } else {
845
-            if (WP_DEBUG) {
846
-                EE_Error::add_error(
847
-                    sprintf(
848
-                        __(
849
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
850
-                            'event_espresso'
851
-                        ),
852
-                        isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
853
-                        isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
854
-                        isset($reg_step['slug']) ? $reg_step['slug'] : '',
855
-                        '<ul>',
856
-                        '<li>',
857
-                        '</li>',
858
-                        '</ul>'
859
-                    ),
860
-                    __FILE__, __FUNCTION__, __LINE__
861
-                );
862
-            }
863
-            return false;
864
-        }
865
-        return true;
866
-    }
867
-
868
-
869
-    /**
870
-     * _verify_transaction_and_get_registrations
871
-     *
872
-     * @access private
873
-     * @return bool
874
-     * @throws InvalidDataTypeException
875
-     * @throws InvalidEntityException
876
-     * @throws EE_Error
877
-     */
878
-    private function _verify_transaction_and_get_registrations()
879
-    {
880
-        // was there already a valid transaction in the checkout from the session ?
881
-        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
882
-            // get transaction from db or session
883
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
884
-                ? $this->_get_transaction_and_cart_for_previous_visit()
885
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
886
-            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
887
-                EE_Error::add_error(
888
-                    __('Your Registration and Transaction information could not be retrieved from the db.',
889
-                        'event_espresso'),
890
-                    __FILE__, __FUNCTION__, __LINE__
891
-                );
892
-                $this->checkout->transaction = EE_Transaction::new_instance();
893
-                // add some style and make it dance
894
-                $this->add_styles_and_scripts();
895
-                EED_Single_Page_Checkout::$_initialized = true;
896
-                return false;
897
-            }
898
-            // and the registrations for the transaction
899
-            $this->_get_registrations($this->checkout->transaction);
900
-        }
901
-        return true;
902
-    }
903
-
904
-
905
-
906
-    /**
907
-     * _get_transaction_and_cart_for_previous_visit
908
-     *
909
-     * @access private
910
-     * @return mixed EE_Transaction|NULL
911
-     */
912
-    private function _get_transaction_and_cart_for_previous_visit()
913
-    {
914
-        /** @var $TXN_model EEM_Transaction */
915
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
916
-        // because the reg_url_link is present in the request,
917
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
918
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
919
-        // verify transaction
920
-        if ($transaction instanceof EE_Transaction) {
921
-            // and get the cart that was used for that transaction
922
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
923
-            return $transaction;
924
-        }
925
-        EE_Error::add_error(
926
-            __('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
927
-            __FILE__, __FUNCTION__, __LINE__
928
-        );
929
-        return null;
930
-
931
-    }
932
-
933
-
934
-
935
-    /**
936
-     * _get_cart_for_transaction
937
-     *
938
-     * @access private
939
-     * @param EE_Transaction $transaction
940
-     * @return EE_Cart
941
-     */
942
-    private function _get_cart_for_transaction($transaction)
943
-    {
944
-        return $this->checkout->get_cart_for_transaction($transaction);
945
-    }
946
-
947
-
948
-
949
-    /**
950
-     * get_cart_for_transaction
951
-     *
952
-     * @access public
953
-     * @param EE_Transaction $transaction
954
-     * @return EE_Cart
955
-     */
956
-    public function get_cart_for_transaction(EE_Transaction $transaction)
957
-    {
958
-        return $this->checkout->get_cart_for_transaction($transaction);
959
-    }
960
-
961
-
962
-
963
-    /**
964
-     * _get_transaction_and_cart_for_current_session
965
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
966
-     *
967
-     * @access private
968
-     * @return EE_Transaction
969
-     * @throws EE_Error
970
-     */
971
-    private function _get_cart_for_current_session_and_setup_new_transaction()
972
-    {
973
-        //  if there's no transaction, then this is the FIRST visit to SPCO
974
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
975
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
976
-        // and then create a new transaction
977
-        $transaction = $this->_initialize_transaction();
978
-        // verify transaction
979
-        if ($transaction instanceof EE_Transaction) {
980
-            // save it so that we have an ID for other objects to use
981
-            $transaction->save();
982
-            // and save TXN data to the cart
983
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
984
-        } else {
985
-            EE_Error::add_error(
986
-                __('A Valid Transaction could not be initialized.', 'event_espresso'),
987
-                __FILE__, __FUNCTION__, __LINE__
988
-            );
989
-        }
990
-        return $transaction;
991
-    }
992
-
993
-
994
-
995
-    /**
996
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
997
-     *
998
-     * @access private
999
-     * @return mixed EE_Transaction|NULL
1000
-     */
1001
-    private function _initialize_transaction()
1002
-    {
1003
-        try {
1004
-            // ensure cart totals have been calculated
1005
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
1006
-            // grab the cart grand total
1007
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
1008
-            // create new TXN
1009
-            $transaction = EE_Transaction::new_instance(
1010
-                array(
1011
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
1012
-                    'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
1013
-                    'TXN_paid'      => 0,
1014
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
1015
-                )
1016
-            );
1017
-            // save it so that we have an ID for other objects to use
1018
-            $transaction->save();
1019
-            // set cron job for following up on TXNs after their session has expired
1020
-            EE_Cron_Tasks::schedule_expired_transaction_check(
1021
-                EE_Registry::instance()->SSN->expiration() + 1,
1022
-                $transaction->ID()
1023
-            );
1024
-            return $transaction;
1025
-        } catch (Exception $e) {
1026
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1027
-        }
1028
-        return null;
1029
-    }
1030
-
1031
-
1032
-    /**
1033
-     * _get_registrations
1034
-     *
1035
-     * @access private
1036
-     * @param EE_Transaction $transaction
1037
-     * @return void
1038
-     * @throws InvalidDataTypeException
1039
-     * @throws InvalidEntityException
1040
-     * @throws EE_Error
1041
-     */
1042
-    private function _get_registrations(EE_Transaction $transaction)
1043
-    {
1044
-        // first step: grab the registrants  { : o
1045
-        $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
1046
-        // verify registrations have been set
1047
-        if (empty($registrations)) {
1048
-            // if no cached registrations, then check the db
1049
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1050
-            // still nothing ? well as long as this isn't a revisit
1051
-            if (empty($registrations) && ! $this->checkout->revisit) {
1052
-                // generate new registrations from scratch
1053
-                $registrations = $this->_initialize_registrations($transaction);
1054
-            }
1055
-        }
1056
-        // sort by their original registration order
1057
-        usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1058
-        // then loop thru the array
1059
-        foreach ($registrations as $registration) {
1060
-            // verify each registration
1061
-            if ($registration instanceof EE_Registration) {
1062
-                // we display all attendee info for the primary registrant
1063
-                if ($this->checkout->reg_url_link === $registration->reg_url_link()
1064
-                    && $registration->is_primary_registrant()
1065
-                ) {
1066
-                    $this->checkout->primary_revisit = true;
1067
-                    break;
1068
-                }
1069
-                if ($this->checkout->revisit
1070
-                           && $this->checkout->reg_url_link !== $registration->reg_url_link()
1071
-                ) {
1072
-                    // but hide info if it doesn't belong to you
1073
-                    $transaction->clear_cache('Registration', $registration->ID());
1074
-                }
1075
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1076
-            }
1077
-        }
1078
-    }
1079
-
1080
-
1081
-    /**
1082
-     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1083
-     *
1084
-     * @access private
1085
-     * @param EE_Transaction $transaction
1086
-     * @return    array
1087
-     * @throws InvalidDataTypeException
1088
-     * @throws InvalidEntityException
1089
-     * @throws EE_Error
1090
-     */
1091
-    private function _initialize_registrations(EE_Transaction $transaction)
1092
-    {
1093
-        $att_nmbr = 0;
1094
-        $registrations = array();
1095
-        if ($transaction instanceof EE_Transaction) {
1096
-            /** @type EE_Registration_Processor $registration_processor */
1097
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1098
-            $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1099
-            // now let's add the cart items to the $transaction
1100
-            foreach ($this->checkout->cart->get_tickets() as $line_item) {
1101
-                //do the following for each ticket of this type they selected
1102
-                for ($x = 1; $x <= $line_item->quantity(); $x++) {
1103
-                    $att_nmbr++;
1104
-                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1105
-                    $CreateRegistrationCommand = EE_Registry::instance()->create(
1106
-                        'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1107
-                        array(
1108
-                            $transaction,
1109
-                            $line_item,
1110
-                            $att_nmbr,
1111
-                            $this->checkout->total_ticket_count,
1112
-                        )
1113
-                    );
1114
-                    // override capabilities for frontend registrations
1115
-                    if ( ! is_admin()) {
1116
-                        $CreateRegistrationCommand->setCapCheck(
1117
-                            new PublicCapabilities('', 'create_new_registration')
1118
-                        );
1119
-                    }
1120
-                    $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1121
-                    if ( ! $registration instanceof EE_Registration) {
1122
-                        throw new InvalidEntityException($registration, 'EE_Registration');
1123
-                    }
1124
-                    $registrations[ $registration->ID() ] = $registration;
1125
-                }
1126
-            }
1127
-            $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1128
-        }
1129
-        return $registrations;
1130
-    }
1131
-
1132
-
1133
-
1134
-    /**
1135
-     * sorts registrations by REG_count
1136
-     *
1137
-     * @access public
1138
-     * @param EE_Registration $reg_A
1139
-     * @param EE_Registration $reg_B
1140
-     * @return int
1141
-     */
1142
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1143
-    {
1144
-        // this shouldn't ever happen within the same TXN, but oh well
1145
-        if ($reg_A->count() === $reg_B->count()) {
1146
-            return 0;
1147
-        }
1148
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1149
-    }
1150
-
1151
-
1152
-
1153
-    /**
1154
-     *    _final_verifications
1155
-     * just makes sure that everything is set up correctly before proceeding
1156
-     *
1157
-     * @access    private
1158
-     * @return    bool
1159
-     * @throws EE_Error
1160
-     */
1161
-    private function _final_verifications()
1162
-    {
1163
-        // filter checkout
1164
-        $this->checkout = apply_filters(
1165
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1166
-            $this->checkout
1167
-        );
1168
-        //verify that current step is still set correctly
1169
-        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1170
-            EE_Error::add_error(
1171
-                __('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1172
-                __FILE__,
1173
-                __FUNCTION__,
1174
-                __LINE__
1175
-            );
1176
-            return false;
1177
-        }
1178
-        // if returning to SPCO, then verify that primary registrant is set
1179
-        if ( ! empty($this->checkout->reg_url_link)) {
1180
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1181
-            if ( ! $valid_registrant instanceof EE_Registration) {
1182
-                EE_Error::add_error(
1183
-                    __('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1184
-                    __FILE__,
1185
-                    __FUNCTION__,
1186
-                    __LINE__
1187
-                );
1188
-                return false;
1189
-            }
1190
-            $valid_registrant = null;
1191
-            foreach (
1192
-                $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration
1193
-            ) {
1194
-                if (
1195
-                    $registration instanceof EE_Registration
1196
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1197
-                ) {
1198
-                    $valid_registrant = $registration;
1199
-                }
1200
-            }
1201
-            if ( ! $valid_registrant instanceof EE_Registration) {
1202
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1203
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1204
-                    // clear the session, mark the checkout as unverified, and try again
1205
-                    EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1206
-                    EED_Single_Page_Checkout::$_initialized = false;
1207
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1208
-                    $this->_initialize();
1209
-                    EE_Error::reset_notices();
1210
-                    return false;
1211
-                }
1212
-                EE_Error::add_error(
1213
-                    __(
1214
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1215
-                        'event_espresso'
1216
-                    ),
1217
-                    __FILE__,
1218
-                    __FUNCTION__,
1219
-                    __LINE__
1220
-                );
1221
-                return false;
1222
-            }
1223
-        }
1224
-        // now that things have been kinda sufficiently verified,
1225
-        // let's add the checkout to the session so that it's available to other systems
1226
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1227
-        return true;
1228
-    }
1229
-
1230
-
1231
-
1232
-    /**
1233
-     *    _initialize_reg_steps
1234
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1235
-     * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1236
-     *
1237
-     * @access    private
1238
-     * @param bool $reinitializing
1239
-     * @throws EE_Error
1240
-     */
1241
-    private function _initialize_reg_steps($reinitializing = false)
1242
-    {
1243
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1244
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1245
-        foreach ($this->checkout->reg_steps as $reg_step) {
1246
-            if ( ! $reg_step->initialize_reg_step()) {
1247
-                // if not initialized then maybe this step is being removed...
1248
-                if ( ! $reinitializing && $reg_step->is_current_step()) {
1249
-                    // if it was the current step, then we need to start over here
1250
-                    $this->_initialize_reg_steps(true);
1251
-                    return;
1252
-                }
1253
-                continue;
1254
-            }
1255
-            // add css and JS for current step
1256
-            $reg_step->enqueue_styles_and_scripts();
1257
-            // i18n
1258
-            $reg_step->translate_js_strings();
1259
-            if ($reg_step->is_current_step()) {
1260
-                // the text that appears on the reg step form submit button
1261
-                $reg_step->set_submit_button_text();
1262
-            }
1263
-        }
1264
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1265
-        do_action(
1266
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1267
-            $this->checkout->current_step
1268
-        );
1269
-    }
1270
-
1271
-
1272
-
1273
-    /**
1274
-     * _check_form_submission
1275
-     *
1276
-     * @access private
1277
-     * @return boolean
1278
-     */
1279
-    private function _check_form_submission()
1280
-    {
1281
-        //does this request require the reg form to be generated ?
1282
-        if ($this->checkout->generate_reg_form) {
1283
-            // ever heard that song by Blue Rodeo ?
1284
-            try {
1285
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1286
-                // if not displaying a form, then check for form submission
1287
-                if (
1288
-                    $this->checkout->process_form_submission
1289
-                    && $this->checkout->current_step->reg_form->was_submitted()
1290
-                ) {
1291
-                    // clear out any old data in case this step is being run again
1292
-                    $this->checkout->current_step->set_valid_data(array());
1293
-                    // capture submitted form data
1294
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1295
-                        apply_filters(
1296
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1297
-                            EE_Registry::instance()->REQ->params(),
1298
-                            $this->checkout
1299
-                        )
1300
-                    );
1301
-                    // validate submitted form data
1302
-                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1303
-                        // thou shall not pass !!!
1304
-                        $this->checkout->continue_reg = false;
1305
-                        // any form validation errors?
1306
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1307
-                            $submission_error_messages = array();
1308
-                            // bad, bad, bad registrant
1309
-                            foreach (
1310
-                                $this->checkout->current_step->reg_form->get_validation_errors_accumulated()
1311
-                                as $validation_error
1312
-                            ) {
1313
-                                if ($validation_error instanceof EE_Validation_Error) {
1314
-                                    $submission_error_messages[] = sprintf(
1315
-                                        __('%s : %s', 'event_espresso'),
1316
-                                        $validation_error->get_form_section()->html_label_text(),
1317
-                                        $validation_error->getMessage()
1318
-                                    );
1319
-                                }
1320
-                            }
1321
-                            EE_Error::add_error(
1322
-                                implode('<br />', $submission_error_messages),
1323
-                                __FILE__, __FUNCTION__, __LINE__
1324
-                            );
1325
-                        }
1326
-                        // well not really... what will happen is
1327
-                        // we'll just get redirected back to redo the current step
1328
-                        $this->go_to_next_step();
1329
-                        return false;
1330
-                    }
1331
-                }
1332
-            } catch (EE_Error $e) {
1333
-                $e->get_error();
1334
-            }
1335
-        }
1336
-        return true;
1337
-    }
1338
-
1339
-
1340
-
1341
-    /**
1342
-     * _process_action
1343
-     *
1344
-     * @access private
1345
-     * @return void
1346
-     * @throws EE_Error
1347
-     */
1348
-    private function _process_form_action()
1349
-    {
1350
-        // what cha wanna do?
1351
-        switch ($this->checkout->action) {
1352
-            // AJAX next step reg form
1353
-            case 'display_spco_reg_step' :
1354
-                $this->checkout->redirect = false;
1355
-                if (EE_Registry::instance()->REQ->ajax) {
1356
-                    $this->checkout->json_response->set_reg_step_html(
1357
-                        $this->checkout->current_step->display_reg_form()
1358
-                    );
1359
-                }
1360
-                break;
1361
-            default :
1362
-                // meh... do one of those other steps first
1363
-                if (
1364
-                    ! empty($this->checkout->action)
1365
-                    && is_callable(array($this->checkout->current_step, $this->checkout->action))
1366
-                ) {
1367
-                    // dynamically creates hook point like:
1368
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1369
-                    do_action(
1370
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1371
-                        $this->checkout->current_step
1372
-                    );
1373
-                    // call action on current step
1374
-                    if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1375
-                        // good registrant, you get to proceed
1376
-                        if (
1377
-                            $this->checkout->current_step->success_message() !== ''
1378
-                            && apply_filters(
1379
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1380
-                                false
1381
-                            )
1382
-                        ) {
1383
-                            EE_Error::add_success(
1384
-                                $this->checkout->current_step->success_message()
1385
-                                . '<br />' . $this->checkout->next_step->_instructions()
1386
-                            );
1387
-                        }
1388
-                        // pack it up, pack it in...
1389
-                        $this->_setup_redirect();
1390
-                    }
1391
-                    // dynamically creates hook point like:
1392
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1393
-                    do_action(
1394
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1395
-                        $this->checkout->current_step
1396
-                    );
1397
-                } else {
1398
-                    EE_Error::add_error(
1399
-                        sprintf(
1400
-                            __(
1401
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1402
-                                'event_espresso'
1403
-                            ),
1404
-                            $this->checkout->action,
1405
-                            $this->checkout->current_step->name()
1406
-                        ),
1407
-                        __FILE__,
1408
-                        __FUNCTION__,
1409
-                        __LINE__
1410
-                    );
1411
-                }
1412
-            // end default
1413
-        }
1414
-        // store our progress so far
1415
-        $this->checkout->stash_transaction_and_checkout();
1416
-        // advance to the next step! If you pass GO, collect $200
1417
-        $this->go_to_next_step();
1418
-    }
1419
-
1420
-
1421
-
1422
-    /**
1423
-     *        add_styles_and_scripts
1424
-     *
1425
-     * @access        public
1426
-     * @return        void
1427
-     */
1428
-    public function add_styles_and_scripts()
1429
-    {
1430
-        // i18n
1431
-        $this->translate_js_strings();
1432
-        if ($this->checkout->admin_request) {
1433
-            add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1434
-        } else {
1435
-            add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1436
-        }
1437
-    }
1438
-
1439
-
1440
-
1441
-    /**
1442
-     *        translate_js_strings
1443
-     *
1444
-     * @access        public
1445
-     * @return        void
1446
-     */
1447
-    public function translate_js_strings()
1448
-    {
1449
-        EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1450
-        EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1451
-        EE_Registry::$i18n_js_strings['server_error'] = __(
1452
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1453
-            'event_espresso'
1454
-        );
1455
-        EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1456
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1457
-            'event_espresso'
1458
-        );
1459
-        EE_Registry::$i18n_js_strings['validation_error'] = __(
1460
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1461
-            'event_espresso'
1462
-        );
1463
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1464
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1465
-            'event_espresso'
1466
-        );
1467
-        EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1468
-            'This registration step could not be completed. Please refresh the page and try again.',
1469
-            'event_espresso'
1470
-        );
1471
-        EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1472
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1473
-            'event_espresso'
1474
-        );
1475
-        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1476
-            __(
1477
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1478
-                'event_espresso'
1479
-            ),
1480
-            '<br/>',
1481
-            '<br/>'
1482
-        );
1483
-        EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1484
-        EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1485
-        EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1486
-        EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1487
-        EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1488
-        EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1489
-        EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1490
-        EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1491
-        EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1492
-        EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1493
-        EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1494
-        EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1495
-        EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1496
-        EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1497
-        EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1498
-        EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1499
-        EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1500
-        EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1501
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1502
-            __(
1503
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
1504
-                'event_espresso'
1505
-            ),
1506
-            '<h4 class="important-notice">',
1507
-            '</h4>',
1508
-            '<br />',
1509
-            '<p>',
1510
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1511
-            '">',
1512
-            '</a>',
1513
-            '</p>'
1514
-        );
1515
-        EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1516
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1517
-            true
1518
-        );
1519
-        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1520
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1521
-        );
1522
-        EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1523
-            'M d, Y H:i:s',
1524
-            EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1525
-        );
1526
-    }
1527
-
1528
-
1529
-
1530
-    /**
1531
-     *    enqueue_styles_and_scripts
1532
-     *
1533
-     * @access        public
1534
-     * @return        void
1535
-     * @throws EE_Error
1536
-     */
1537
-    public function enqueue_styles_and_scripts()
1538
-    {
1539
-        // load css
1540
-        wp_register_style(
1541
-            'single_page_checkout',
1542
-            SPCO_CSS_URL . 'single_page_checkout.css',
1543
-            array('espresso_default'),
1544
-            EVENT_ESPRESSO_VERSION
1545
-        );
1546
-        wp_enqueue_style('single_page_checkout');
1547
-        // load JS
1548
-        wp_register_script(
1549
-            'jquery_plugin',
1550
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1551
-            array('jquery'),
1552
-            '1.0.1',
1553
-            true
1554
-        );
1555
-        wp_register_script(
1556
-            'jquery_countdown',
1557
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1558
-            array('jquery_plugin'),
1559
-            '2.0.2',
1560
-            true
1561
-        );
1562
-        wp_register_script(
1563
-            'single_page_checkout',
1564
-            SPCO_JS_URL . 'single_page_checkout.js',
1565
-            array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1566
-            EVENT_ESPRESSO_VERSION,
1567
-            true
1568
-        );
1569
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1570
-            $this->checkout->registration_form->enqueue_js();
1571
-        }
1572
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1573
-            $this->checkout->current_step->reg_form->enqueue_js();
1574
-        }
1575
-        wp_enqueue_script('single_page_checkout');
1576
-        /**
1577
-         * global action hook for enqueueing styles and scripts with
1578
-         * spco calls.
1579
-         */
1580
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1581
-        /**
1582
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1583
-         * The hook will end up being something like:
1584
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1585
-         */
1586
-        do_action(
1587
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1588
-            $this
1589
-        );
1590
-    }
1591
-
1592
-
1593
-
1594
-    /**
1595
-     *    display the Registration Single Page Checkout Form
1596
-     *
1597
-     * @access    private
1598
-     * @return    void
1599
-     * @throws EE_Error
1600
-     */
1601
-    private function _display_spco_reg_form()
1602
-    {
1603
-        // if registering via the admin, just display the reg form for the current step
1604
-        if ($this->checkout->admin_request) {
1605
-            EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1606
-        } else {
1607
-            // add powered by EE msg
1608
-            add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1609
-            $empty_cart = count(
1610
-                $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1611
-            ) < 1;
1612
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1613
-            $cookies_not_set_msg = '';
1614
-            if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1615
-                $cookies_not_set_msg = apply_filters(
1616
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1617
-                    sprintf(
1618
-                        __(
1619
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1620
-                            'event_espresso'
1621
-                        ),
1622
-                        '<div class="ee-attention">',
1623
-                        '</div>',
1624
-                        '<h6 class="important-notice">',
1625
-                        '</h6>',
1626
-                        '<p>',
1627
-                        '</p>',
1628
-                        '<br />',
1629
-                        '<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1630
-                        '</a>'
1631
-                    )
1632
-                );
1633
-            }
1634
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1635
-                array(
1636
-                    'name'            => 'single-page-checkout',
1637
-                    'html_id'         => 'ee-single-page-checkout-dv',
1638
-                    'layout_strategy' =>
1639
-                        new EE_Template_Layout(
1640
-                            array(
1641
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1642
-                                'template_args'        => array(
1643
-                                    'empty_cart'              => $empty_cart,
1644
-                                    'revisit'                 => $this->checkout->revisit,
1645
-                                    'reg_steps'               => $this->checkout->reg_steps,
1646
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1647
-                                        ? $this->checkout->next_step->slug()
1648
-                                        : '',
1649
-                                    'cancel_page_url'         => $this->checkout->cancel_page_url,
1650
-                                    'empty_msg'               => apply_filters(
1651
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1652
-                                        sprintf(
1653
-                                            __(
1654
-                                                'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1655
-                                                'event_espresso'
1656
-                                            ),
1657
-                                            '<a href="'
1658
-                                            . get_post_type_archive_link('espresso_events')
1659
-                                            . '" title="',
1660
-                                            '">',
1661
-                                            '</a>'
1662
-                                        )
1663
-                                    ),
1664
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1665
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1666
-                                    'session_expiration'      => gmdate(
1667
-                                        'M d, Y H:i:s',
1668
-                                        EE_Registry::instance()->SSN->expiration()
1669
-                                        + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1670
-                                    ),
1671
-                                ),
1672
-                            )
1673
-                        ),
1674
-                )
1675
-            );
1676
-            // load template and add to output sent that gets filtered into the_content()
1677
-            EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1678
-        }
1679
-    }
1680
-
1681
-
1682
-
1683
-    /**
1684
-     *    add_extra_finalize_registration_inputs
1685
-     *
1686
-     * @access    public
1687
-     * @param $next_step
1688
-     * @internal  param string $label
1689
-     * @return void
1690
-     */
1691
-    public function add_extra_finalize_registration_inputs($next_step)
1692
-    {
1693
-        if ($next_step === 'finalize_registration') {
1694
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1695
-        }
1696
-    }
1697
-
1698
-
1699
-
1700
-    /**
1701
-     *    display_registration_footer
1702
-     *
1703
-     * @access    public
1704
-     * @return    string
1705
-     */
1706
-    public static function display_registration_footer()
1707
-    {
1708
-        if (
1709
-        apply_filters(
1710
-            'FHEE__EE_Front__Controller__show_reg_footer',
1711
-            EE_Registry::instance()->CFG->admin->show_reg_footer
1712
-        )
1713
-        ) {
1714
-            add_filter(
1715
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1716
-                function ($url) {
1717
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1718
-                }
1719
-            );
1720
-            echo apply_filters(
1721
-                'FHEE__EE_Front_Controller__display_registration_footer',
1722
-                \EEH_Template::powered_by_event_espresso(
1723
-                    '',
1724
-                    'espresso-registration-footer-dv',
1725
-                    array('utm_content' => 'registration_checkout')
1726
-                )
1727
-            );
1728
-        }
1729
-        return '';
1730
-    }
1731
-
1732
-
1733
-
1734
-    /**
1735
-     *    unlock_transaction
1736
-     *
1737
-     * @access    public
1738
-     * @return    void
1739
-     * @throws EE_Error
1740
-     */
1741
-    public function unlock_transaction()
1742
-    {
1743
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1744
-            $this->checkout->transaction->unlock();
1745
-        }
1746
-    }
1747
-
1748
-
1749
-
1750
-    /**
1751
-     *        _setup_redirect
1752
-     *
1753
-     * @access    private
1754
-     * @return void
1755
-     */
1756
-    private function _setup_redirect()
1757
-    {
1758
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1759
-            $this->checkout->redirect = true;
1760
-            if (empty($this->checkout->redirect_url)) {
1761
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1762
-            }
1763
-            $this->checkout->redirect_url = apply_filters(
1764
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1765
-                $this->checkout->redirect_url,
1766
-                $this->checkout
1767
-            );
1768
-        }
1769
-    }
1770
-
1771
-
1772
-
1773
-    /**
1774
-     *   handle ajax message responses and redirects
1775
-     *
1776
-     * @access public
1777
-     * @return void
1778
-     * @throws EE_Error
1779
-     */
1780
-    public function go_to_next_step()
1781
-    {
1782
-        if (EE_Registry::instance()->REQ->ajax) {
1783
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1784
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1785
-        }
1786
-        $this->unlock_transaction();
1787
-        // just return for these conditions
1788
-        if (
1789
-            $this->checkout->admin_request
1790
-            || $this->checkout->action === 'redirect_form'
1791
-            || $this->checkout->action === 'update_checkout'
1792
-        ) {
1793
-            return;
1794
-        }
1795
-        // AJAX response
1796
-        $this->_handle_json_response();
1797
-        // redirect to next step or the Thank You page
1798
-        $this->_handle_html_redirects();
1799
-        // hmmm... must be something wrong, so let's just display the form again !
1800
-        $this->_display_spco_reg_form();
1801
-    }
1802
-
1803
-
1804
-
1805
-    /**
1806
-     *   _handle_json_response
1807
-     *
1808
-     * @access protected
1809
-     * @return void
1810
-     */
1811
-    protected function _handle_json_response()
1812
-    {
1813
-        // if this is an ajax request
1814
-        if (EE_Registry::instance()->REQ->ajax) {
1815
-            // DEBUG LOG
1816
-            //$this->checkout->log(
1817
-            //	__CLASS__, __FUNCTION__, __LINE__,
1818
-            //	array(
1819
-            //		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1820
-            //		'redirect'                   => $this->checkout->redirect,
1821
-            //		'continue_reg'               => $this->checkout->continue_reg,
1822
-            //	)
1823
-            //);
1824
-            $this->checkout->json_response->set_registration_time_limit(
1825
-                $this->checkout->get_registration_time_limit()
1826
-            );
1827
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1828
-            // just send the ajax (
1829
-            $json_response = apply_filters(
1830
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1831
-                $this->checkout->json_response
1832
-            );
1833
-            echo $json_response;
1834
-            exit();
1835
-        }
1836
-    }
1837
-
1838
-
1839
-
1840
-    /**
1841
-     *   _handle_redirects
1842
-     *
1843
-     * @access protected
1844
-     * @return void
1845
-     */
1846
-    protected function _handle_html_redirects()
1847
-    {
1848
-        // going somewhere ?
1849
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1850
-            // store notices in a transient
1851
-            EE_Error::get_notices(false, true, true);
1852
-            // DEBUG LOG
1853
-            //$this->checkout->log(
1854
-            //	__CLASS__, __FUNCTION__, __LINE__,
1855
-            //	array(
1856
-            //		'headers_sent' => headers_sent(),
1857
-            //		'redirect_url'     => $this->checkout->redirect_url,
1858
-            //		'headers_list'    => headers_list(),
1859
-            //	)
1860
-            //);
1861
-            wp_safe_redirect($this->checkout->redirect_url);
1862
-            exit();
1863
-        }
1864
-    }
1865
-
1866
-
1867
-
1868
-    /**
1869
-     *   set_checkout_anchor
1870
-     *
1871
-     * @access public
1872
-     * @return void
1873
-     */
1874
-    public function set_checkout_anchor()
1875
-    {
1876
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1877
-    }
23
+	/**
24
+	 * $_initialized - has the SPCO controller already been initialized ?
25
+	 *
26
+	 * @access private
27
+	 * @var bool $_initialized
28
+	 */
29
+	private static $_initialized = false;
30
+
31
+
32
+	/**
33
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
34
+	 *
35
+	 * @access private
36
+	 * @var bool $_valid_checkout
37
+	 */
38
+	private static $_checkout_verified = true;
39
+
40
+	/**
41
+	 *    $_reg_steps_array - holds initial array of reg steps
42
+	 *
43
+	 * @access private
44
+	 * @var array $_reg_steps_array
45
+	 */
46
+	private static $_reg_steps_array = array();
47
+
48
+	/**
49
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
50
+	 *
51
+	 * @access public
52
+	 * @var EE_Checkout $checkout
53
+	 */
54
+	public $checkout;
55
+
56
+
57
+
58
+	/**
59
+	 * @return EED_Module|EED_Single_Page_Checkout
60
+	 */
61
+	public static function instance()
62
+	{
63
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
64
+		return parent::get_instance(__CLASS__);
65
+	}
66
+
67
+
68
+
69
+	/**
70
+	 * @return EE_CART
71
+	 */
72
+	public function cart()
73
+	{
74
+		return $this->checkout->cart;
75
+	}
76
+
77
+
78
+
79
+	/**
80
+	 * @return EE_Transaction
81
+	 */
82
+	public function transaction()
83
+	{
84
+		return $this->checkout->transaction;
85
+	}
86
+
87
+
88
+
89
+	/**
90
+	 *    set_hooks - for hooking into EE Core, other modules, etc
91
+	 *
92
+	 * @access    public
93
+	 * @return    void
94
+	 * @throws EE_Error
95
+	 */
96
+	public static function set_hooks()
97
+	{
98
+		EED_Single_Page_Checkout::set_definitions();
99
+	}
100
+
101
+
102
+
103
+	/**
104
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
+	 *
106
+	 * @access    public
107
+	 * @return    void
108
+	 * @throws EE_Error
109
+	 */
110
+	public static function set_hooks_admin()
111
+	{
112
+		EED_Single_Page_Checkout::set_definitions();
113
+		if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
114
+			return;
115
+		}
116
+		// going to start an output buffer in case anything gets accidentally output
117
+		// that might disrupt our JSON response
118
+		ob_start();
119
+		EED_Single_Page_Checkout::load_request_handler();
120
+		EED_Single_Page_Checkout::load_reg_steps();
121
+		// set ajax hooks
122
+		add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
123
+		add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
124
+		add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
125
+		add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
126
+		add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
127
+		add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 *    process ajax request
134
+	 *
135
+	 * @param string $ajax_action
136
+	 * @throws EE_Error
137
+	 */
138
+	public static function process_ajax_request($ajax_action)
139
+	{
140
+		EE_Registry::instance()->REQ->set('action', $ajax_action);
141
+		EED_Single_Page_Checkout::instance()->_initialize();
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 *    ajax display registration step
148
+	 *
149
+	 * @throws EE_Error
150
+	 */
151
+	public static function display_reg_step()
152
+	{
153
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
154
+	}
155
+
156
+
157
+
158
+	/**
159
+	 *    ajax process registration step
160
+	 *
161
+	 * @throws EE_Error
162
+	 */
163
+	public static function process_reg_step()
164
+	{
165
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
166
+	}
167
+
168
+
169
+
170
+	/**
171
+	 *    ajax process registration step
172
+	 *
173
+	 * @throws EE_Error
174
+	 */
175
+	public static function update_reg_step()
176
+	{
177
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
178
+	}
179
+
180
+
181
+
182
+	/**
183
+	 *   update_checkout
184
+	 *
185
+	 * @access public
186
+	 * @return void
187
+	 * @throws EE_Error
188
+	 */
189
+	public static function update_checkout()
190
+	{
191
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
192
+	}
193
+
194
+
195
+
196
+	/**
197
+	 *    load_request_handler
198
+	 *
199
+	 * @access    public
200
+	 * @return    void
201
+	 */
202
+	public static function load_request_handler()
203
+	{
204
+		// load core Request_Handler class
205
+		if (EE_Registry::instance()->REQ !== null) {
206
+			EE_Registry::instance()->load_core('Request_Handler');
207
+		}
208
+	}
209
+
210
+
211
+
212
+	/**
213
+	 *    set_definitions
214
+	 *
215
+	 * @access    public
216
+	 * @return    void
217
+	 * @throws EE_Error
218
+	 */
219
+	public static function set_definitions()
220
+	{
221
+		if(defined('SPCO_BASE_PATH')) {
222
+			return;
223
+		}
224
+		define(
225
+			'SPCO_BASE_PATH',
226
+			rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
227
+		);
228
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
234
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
236
+			__('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
237
+				'event_espresso'),
238
+			'<h4 class="important-notice">',
239
+			'</h4>',
240
+			'<br />',
241
+			'<p>',
242
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
243
+			'">',
244
+			'</a>',
245
+			'</p>'
246
+		);
247
+	}
248
+
249
+
250
+
251
+	/**
252
+	 * load_reg_steps
253
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
254
+	 *
255
+	 * @access    private
256
+	 * @throws EE_Error
257
+	 */
258
+	public static function load_reg_steps()
259
+	{
260
+		static $reg_steps_loaded = false;
261
+		if ($reg_steps_loaded) {
262
+			return;
263
+		}
264
+		// filter list of reg_steps
265
+		$reg_steps_to_load = (array)apply_filters(
266
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
267
+			EED_Single_Page_Checkout::get_reg_steps()
268
+		);
269
+		// sort by key (order)
270
+		ksort($reg_steps_to_load);
271
+		// loop through folders
272
+		foreach ($reg_steps_to_load as $order => $reg_step) {
273
+			// we need a
274
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
275
+				// copy over to the reg_steps_array
276
+				EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
277
+				// register custom key route for each reg step
278
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
279
+				EE_Config::register_route(
280
+					$reg_step['slug'],
281
+					'EED_Single_Page_Checkout',
282
+					'run',
283
+					'step'
284
+				);
285
+				// add AJAX or other hooks
286
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
287
+					// setup autoloaders if necessary
288
+					if ( ! class_exists($reg_step['class_name'])) {
289
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
290
+							$reg_step['file_path'],
291
+							true
292
+						);
293
+					}
294
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
295
+						call_user_func(array($reg_step['class_name'], 'set_hooks'));
296
+					}
297
+				}
298
+			}
299
+		}
300
+		$reg_steps_loaded = true;
301
+	}
302
+
303
+
304
+
305
+	/**
306
+	 *    get_reg_steps
307
+	 *
308
+	 * @access    public
309
+	 * @return    array
310
+	 */
311
+	public static function get_reg_steps()
312
+	{
313
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
314
+		if (empty($reg_steps)) {
315
+			$reg_steps = array(
316
+				10  => array(
317
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
318
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
319
+					'slug'       => 'attendee_information',
320
+					'has_hooks'  => false,
321
+				),
322
+				20  => array(
323
+					'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
324
+					'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
325
+					'slug'       => 'registration_confirmation',
326
+					'has_hooks'  => false,
327
+				),
328
+				30  => array(
329
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
330
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
331
+					'slug'       => 'payment_options',
332
+					'has_hooks'  => true,
333
+				),
334
+				999 => array(
335
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
336
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
337
+					'slug'       => 'finalize_registration',
338
+					'has_hooks'  => false,
339
+				),
340
+			);
341
+		}
342
+		return $reg_steps;
343
+	}
344
+
345
+
346
+
347
+	/**
348
+	 *    registration_checkout_for_admin
349
+	 *
350
+	 * @access    public
351
+	 * @return    string
352
+	 * @throws EE_Error
353
+	 */
354
+	public static function registration_checkout_for_admin()
355
+	{
356
+		EED_Single_Page_Checkout::load_request_handler();
357
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
358
+		EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
359
+		EE_Registry::instance()->REQ->set('process_form_submission', false);
360
+		EED_Single_Page_Checkout::instance()->_initialize();
361
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
362
+		return EE_Registry::instance()->REQ->get_output();
363
+	}
364
+
365
+
366
+
367
+	/**
368
+	 * process_registration_from_admin
369
+	 *
370
+	 * @access public
371
+	 * @return \EE_Transaction
372
+	 * @throws EE_Error
373
+	 */
374
+	public static function process_registration_from_admin()
375
+	{
376
+		EED_Single_Page_Checkout::load_request_handler();
377
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
378
+		EE_Registry::instance()->REQ->set('action', 'process_reg_step');
379
+		EE_Registry::instance()->REQ->set('process_form_submission', true);
380
+		EED_Single_Page_Checkout::instance()->_initialize();
381
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
382
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
383
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
384
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
385
+				if ($final_reg_step->process_reg_step()) {
386
+					$final_reg_step->set_completed();
387
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
388
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
389
+				}
390
+			}
391
+		}
392
+		return null;
393
+	}
394
+
395
+
396
+
397
+	/**
398
+	 *    run
399
+	 *
400
+	 * @access    public
401
+	 * @param WP_Query $WP_Query
402
+	 * @return    void
403
+	 * @throws EE_Error
404
+	 */
405
+	public function run($WP_Query)
406
+	{
407
+		if (
408
+			$WP_Query instanceof WP_Query
409
+			&& $WP_Query->is_main_query()
410
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
411
+			&& $this->_is_reg_checkout()
412
+		) {
413
+			$this->_initialize();
414
+		}
415
+	}
416
+
417
+
418
+
419
+	/**
420
+	 * determines whether current url matches reg page url
421
+	 *
422
+	 * @return bool
423
+	 */
424
+	protected function _is_reg_checkout()
425
+	{
426
+		// get current permalink for reg page without any extra query args
427
+		$reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
428
+		// get request URI for current request, but without the scheme or host
429
+		$current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
430
+		$current_request_uri = html_entity_decode($current_request_uri);
431
+		// get array of query args from the current request URI
432
+		$query_args = \EEH_URL::get_query_string($current_request_uri);
433
+		// grab page id if it is set
434
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
435
+		// and remove the page id from the query args (we will re-add it later)
436
+		unset($query_args['page_id']);
437
+		// now strip all query args from current request URI
438
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
439
+		// and re-add the page id if it was set
440
+		if ($page_id) {
441
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
442
+		}
443
+		// remove slashes and ?
444
+		$current_request_uri = trim($current_request_uri, '?/');
445
+		// is current request URI part of the known full reg page URL ?
446
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
447
+	}
448
+
449
+
450
+
451
+	/**
452
+	 * @param WP_Query $wp_query
453
+	 * @return    void
454
+	 * @throws EE_Error
455
+	 */
456
+	public static function init($wp_query)
457
+	{
458
+		EED_Single_Page_Checkout::instance()->run($wp_query);
459
+	}
460
+
461
+
462
+
463
+	/**
464
+	 *    _initialize - initial module setup
465
+	 *
466
+	 * @access    private
467
+	 * @throws EE_Error
468
+	 * @return    void
469
+	 */
470
+	private function _initialize()
471
+	{
472
+		// ensure SPCO doesn't run twice
473
+		if (EED_Single_Page_Checkout::$_initialized) {
474
+			return;
475
+		}
476
+		try {
477
+			EED_Single_Page_Checkout::load_reg_steps();
478
+			$this->_verify_session();
479
+			// setup the EE_Checkout object
480
+			$this->checkout = $this->_initialize_checkout();
481
+			// filter checkout
482
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
483
+			// get the $_GET
484
+			$this->_get_request_vars();
485
+			if ($this->_block_bots()) {
486
+				return;
487
+			}
488
+			// filter continue_reg
489
+			$this->checkout->continue_reg = apply_filters(
490
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
491
+				true,
492
+				$this->checkout
493
+			);
494
+			// load the reg steps array
495
+			if ( ! $this->_load_and_instantiate_reg_steps()) {
496
+				EED_Single_Page_Checkout::$_initialized = true;
497
+				return;
498
+			}
499
+			// set the current step
500
+			$this->checkout->set_current_step($this->checkout->step);
501
+			// and the next step
502
+			$this->checkout->set_next_step();
503
+			// verify that everything has been setup correctly
504
+			if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
505
+				EED_Single_Page_Checkout::$_initialized = true;
506
+				return;
507
+			}
508
+			// lock the transaction
509
+			$this->checkout->transaction->lock();
510
+			// make sure all of our cached objects are added to their respective model entity mappers
511
+			$this->checkout->refresh_all_entities();
512
+			// set amount owing
513
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
514
+			// initialize each reg step, which gives them the chance to potentially alter the process
515
+			$this->_initialize_reg_steps();
516
+			// DEBUG LOG
517
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
518
+			// get reg form
519
+			if( ! $this->_check_form_submission()) {
520
+				EED_Single_Page_Checkout::$_initialized = true;
521
+				return;
522
+			}
523
+			// checkout the action!!!
524
+			$this->_process_form_action();
525
+			// add some style and make it dance
526
+			$this->add_styles_and_scripts();
527
+			// kk... SPCO has successfully run
528
+			EED_Single_Page_Checkout::$_initialized = true;
529
+			// set no cache headers and constants
530
+			EE_System::do_not_cache();
531
+			// add anchor
532
+			add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
533
+			// remove transaction lock
534
+			add_action('shutdown', array($this, 'unlock_transaction'), 1);
535
+		} catch (Exception $e) {
536
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
537
+		}
538
+	}
539
+
540
+
541
+
542
+	/**
543
+	 *    _verify_session
544
+	 * checks that the session is valid and not expired
545
+	 *
546
+	 * @access    private
547
+	 * @throws EE_Error
548
+	 */
549
+	private function _verify_session()
550
+	{
551
+		if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
552
+			throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
553
+		}
554
+		$clear_session_requested = filter_var(
555
+			EE_Registry::instance()->REQ->get('clear_session', false),
556
+			FILTER_VALIDATE_BOOLEAN
557
+		);
558
+		// is session still valid ?
559
+		if ($clear_session_requested
560
+			|| ( EE_Registry::instance()->SSN->expired()
561
+			  && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
562
+			)
563
+		) {
564
+			$this->checkout = new EE_Checkout();
565
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
566
+			// EE_Registry::instance()->SSN->reset_cart();
567
+			// EE_Registry::instance()->SSN->reset_checkout();
568
+			// EE_Registry::instance()->SSN->reset_transaction();
569
+			if (! $clear_session_requested) {
570
+				EE_Error::add_attention(
571
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
572
+					__FILE__, __FUNCTION__, __LINE__
573
+				);
574
+			}
575
+			// EE_Registry::instance()->SSN->reset_expired();
576
+		}
577
+	}
578
+
579
+
580
+
581
+	/**
582
+	 *    _initialize_checkout
583
+	 * loads and instantiates EE_Checkout
584
+	 *
585
+	 * @access    private
586
+	 * @throws EE_Error
587
+	 * @return EE_Checkout
588
+	 */
589
+	private function _initialize_checkout()
590
+	{
591
+		// look in session for existing checkout
592
+		/** @type EE_Checkout $checkout */
593
+		$checkout = EE_Registry::instance()->SSN->checkout();
594
+		// verify
595
+		if ( ! $checkout instanceof EE_Checkout) {
596
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
597
+			$checkout = EE_Registry::instance()->load_file(
598
+				SPCO_INC_PATH,
599
+				'EE_Checkout',
600
+				'class', array(),
601
+				false
602
+			);
603
+		} else {
604
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
605
+				$this->unlock_transaction();
606
+				wp_safe_redirect($checkout->redirect_url);
607
+				exit();
608
+			}
609
+		}
610
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
611
+		// verify again
612
+		if ( ! $checkout instanceof EE_Checkout) {
613
+			throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
614
+		}
615
+		// reset anything that needs a clean slate for each request
616
+		$checkout->reset_for_current_request();
617
+		return $checkout;
618
+	}
619
+
620
+
621
+
622
+	/**
623
+	 *    _get_request_vars
624
+	 *
625
+	 * @access    private
626
+	 * @return    void
627
+	 * @throws EE_Error
628
+	 */
629
+	private function _get_request_vars()
630
+	{
631
+		// load classes
632
+		EED_Single_Page_Checkout::load_request_handler();
633
+		//make sure this request is marked as belonging to EE
634
+		EE_Registry::instance()->REQ->set_espresso_page(true);
635
+		// which step is being requested ?
636
+		$this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
637
+		// which step is being edited ?
638
+		$this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
639
+		// and what we're doing on the current step
640
+		$this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
641
+		// timestamp
642
+		$this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
643
+		// returning to edit ?
644
+		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
645
+		// or some other kind of revisit ?
646
+		$this->checkout->revisit = filter_var(
647
+			EE_Registry::instance()->REQ->get('revisit', false),
648
+			FILTER_VALIDATE_BOOLEAN
649
+		);
650
+		// and whether or not to generate a reg form for this request
651
+		$this->checkout->generate_reg_form = filter_var(
652
+			EE_Registry::instance()->REQ->get('generate_reg_form', true),
653
+			FILTER_VALIDATE_BOOLEAN
654
+		);
655
+		// and whether or not to process a reg form submission for this request
656
+		$this->checkout->process_form_submission = filter_var(
657
+			EE_Registry::instance()->REQ->get(
658
+				'process_form_submission',
659
+				$this->checkout->action === 'process_reg_step'
660
+			),
661
+			FILTER_VALIDATE_BOOLEAN
662
+		);
663
+		$this->checkout->process_form_submission = filter_var(
664
+			$this->checkout->action !== 'display_spco_reg_step'
665
+				? $this->checkout->process_form_submission
666
+				: false,
667
+			FILTER_VALIDATE_BOOLEAN
668
+		);
669
+		// $this->_display_request_vars();
670
+	}
671
+
672
+
673
+
674
+	/**
675
+	 *  _display_request_vars
676
+	 *
677
+	 * @access    protected
678
+	 * @return    void
679
+	 */
680
+	protected function _display_request_vars()
681
+	{
682
+		if ( ! WP_DEBUG) {
683
+			return;
684
+		}
685
+		EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
686
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
687
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
688
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
689
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
690
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
691
+		EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
692
+		EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
693
+	}
694
+
695
+
696
+
697
+	/**
698
+	 * _block_bots
699
+	 * checks that the incoming request has either of the following set:
700
+	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
701
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
702
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
703
+	 * then where you coming from man?
704
+	 *
705
+	 * @return boolean
706
+	 */
707
+	private function _block_bots()
708
+	{
709
+		$invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
710
+		if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
711
+			return true;
712
+		}
713
+		return false;
714
+	}
715
+
716
+
717
+
718
+	/**
719
+	 *    _get_first_step
720
+	 *  gets slug for first step in $_reg_steps_array
721
+	 *
722
+	 * @access    private
723
+	 * @throws EE_Error
724
+	 * @return    string
725
+	 */
726
+	private function _get_first_step()
727
+	{
728
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
729
+		return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
730
+	}
731
+
732
+
733
+
734
+	/**
735
+	 *    _load_and_instantiate_reg_steps
736
+	 *  instantiates each reg step based on the loaded reg_steps array
737
+	 *
738
+	 * @access    private
739
+	 * @throws EE_Error
740
+	 * @return    bool
741
+	 */
742
+	private function _load_and_instantiate_reg_steps()
743
+	{
744
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
745
+		// have reg_steps already been instantiated ?
746
+		if (
747
+			empty($this->checkout->reg_steps)
748
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
749
+		) {
750
+			// if not, then loop through raw reg steps array
751
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
752
+				if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
753
+					return false;
754
+				}
755
+			}
756
+			EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
757
+			EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
758
+			// skip the registration_confirmation page ?
759
+			if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
760
+				// just remove it from the reg steps array
761
+				$this->checkout->remove_reg_step('registration_confirmation', false);
762
+			} else if (
763
+				isset($this->checkout->reg_steps['registration_confirmation'])
764
+				&& EE_Registry::instance()->CFG->registration->reg_confirmation_last
765
+			) {
766
+				// set the order to something big like 100
767
+				$this->checkout->set_reg_step_order('registration_confirmation', 100);
768
+			}
769
+			// filter the array for good luck
770
+			$this->checkout->reg_steps = apply_filters(
771
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
772
+				$this->checkout->reg_steps
773
+			);
774
+			// finally re-sort based on the reg step class order properties
775
+			$this->checkout->sort_reg_steps();
776
+		} else {
777
+			foreach ($this->checkout->reg_steps as $reg_step) {
778
+				// set all current step stati to FALSE
779
+				$reg_step->set_is_current_step(false);
780
+			}
781
+		}
782
+		if (empty($this->checkout->reg_steps)) {
783
+			EE_Error::add_error(
784
+				__('No Reg Steps were loaded..', 'event_espresso'),
785
+				__FILE__, __FUNCTION__, __LINE__
786
+			);
787
+			return false;
788
+		}
789
+		// make reg step details available to JS
790
+		$this->checkout->set_reg_step_JSON_info();
791
+		return true;
792
+	}
793
+
794
+
795
+
796
+	/**
797
+	 *     _load_and_instantiate_reg_step
798
+	 *
799
+	 * @access    private
800
+	 * @param array $reg_step
801
+	 * @param int   $order
802
+	 * @return bool
803
+	 */
804
+	private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
805
+	{
806
+		// we need a file_path, class_name, and slug to add a reg step
807
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
808
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
809
+			if (
810
+				$this->checkout->reg_url_link
811
+				&& $this->checkout->step !== $reg_step['slug']
812
+				&& $reg_step['slug'] !== 'finalize_registration'
813
+				// normally at this point we would NOT load the reg step, but this filter can change that
814
+				&& apply_filters(
815
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
816
+					true,
817
+					$reg_step,
818
+					$this->checkout
819
+				)
820
+			) {
821
+				return true;
822
+			}
823
+			// instantiate step class using file path and class name
824
+			$reg_step_obj = EE_Registry::instance()->load_file(
825
+				$reg_step['file_path'],
826
+				$reg_step['class_name'],
827
+				'class',
828
+				$this->checkout,
829
+				false
830
+			);
831
+			// did we gets the goods ?
832
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
833
+				// set reg step order based on config
834
+				$reg_step_obj->set_order($order);
835
+				// add instantiated reg step object to the master reg steps array
836
+				$this->checkout->add_reg_step($reg_step_obj);
837
+			} else {
838
+				EE_Error::add_error(
839
+					__('The current step could not be set.', 'event_espresso'),
840
+					__FILE__, __FUNCTION__, __LINE__
841
+				);
842
+				return false;
843
+			}
844
+		} else {
845
+			if (WP_DEBUG) {
846
+				EE_Error::add_error(
847
+					sprintf(
848
+						__(
849
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
850
+							'event_espresso'
851
+						),
852
+						isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
853
+						isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
854
+						isset($reg_step['slug']) ? $reg_step['slug'] : '',
855
+						'<ul>',
856
+						'<li>',
857
+						'</li>',
858
+						'</ul>'
859
+					),
860
+					__FILE__, __FUNCTION__, __LINE__
861
+				);
862
+			}
863
+			return false;
864
+		}
865
+		return true;
866
+	}
867
+
868
+
869
+	/**
870
+	 * _verify_transaction_and_get_registrations
871
+	 *
872
+	 * @access private
873
+	 * @return bool
874
+	 * @throws InvalidDataTypeException
875
+	 * @throws InvalidEntityException
876
+	 * @throws EE_Error
877
+	 */
878
+	private function _verify_transaction_and_get_registrations()
879
+	{
880
+		// was there already a valid transaction in the checkout from the session ?
881
+		if ( ! $this->checkout->transaction instanceof EE_Transaction) {
882
+			// get transaction from db or session
883
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
884
+				? $this->_get_transaction_and_cart_for_previous_visit()
885
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
886
+			if ( ! $this->checkout->transaction instanceof EE_Transaction) {
887
+				EE_Error::add_error(
888
+					__('Your Registration and Transaction information could not be retrieved from the db.',
889
+						'event_espresso'),
890
+					__FILE__, __FUNCTION__, __LINE__
891
+				);
892
+				$this->checkout->transaction = EE_Transaction::new_instance();
893
+				// add some style and make it dance
894
+				$this->add_styles_and_scripts();
895
+				EED_Single_Page_Checkout::$_initialized = true;
896
+				return false;
897
+			}
898
+			// and the registrations for the transaction
899
+			$this->_get_registrations($this->checkout->transaction);
900
+		}
901
+		return true;
902
+	}
903
+
904
+
905
+
906
+	/**
907
+	 * _get_transaction_and_cart_for_previous_visit
908
+	 *
909
+	 * @access private
910
+	 * @return mixed EE_Transaction|NULL
911
+	 */
912
+	private function _get_transaction_and_cart_for_previous_visit()
913
+	{
914
+		/** @var $TXN_model EEM_Transaction */
915
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
916
+		// because the reg_url_link is present in the request,
917
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
918
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
919
+		// verify transaction
920
+		if ($transaction instanceof EE_Transaction) {
921
+			// and get the cart that was used for that transaction
922
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
923
+			return $transaction;
924
+		}
925
+		EE_Error::add_error(
926
+			__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
927
+			__FILE__, __FUNCTION__, __LINE__
928
+		);
929
+		return null;
930
+
931
+	}
932
+
933
+
934
+
935
+	/**
936
+	 * _get_cart_for_transaction
937
+	 *
938
+	 * @access private
939
+	 * @param EE_Transaction $transaction
940
+	 * @return EE_Cart
941
+	 */
942
+	private function _get_cart_for_transaction($transaction)
943
+	{
944
+		return $this->checkout->get_cart_for_transaction($transaction);
945
+	}
946
+
947
+
948
+
949
+	/**
950
+	 * get_cart_for_transaction
951
+	 *
952
+	 * @access public
953
+	 * @param EE_Transaction $transaction
954
+	 * @return EE_Cart
955
+	 */
956
+	public function get_cart_for_transaction(EE_Transaction $transaction)
957
+	{
958
+		return $this->checkout->get_cart_for_transaction($transaction);
959
+	}
960
+
961
+
962
+
963
+	/**
964
+	 * _get_transaction_and_cart_for_current_session
965
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
966
+	 *
967
+	 * @access private
968
+	 * @return EE_Transaction
969
+	 * @throws EE_Error
970
+	 */
971
+	private function _get_cart_for_current_session_and_setup_new_transaction()
972
+	{
973
+		//  if there's no transaction, then this is the FIRST visit to SPCO
974
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
975
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
976
+		// and then create a new transaction
977
+		$transaction = $this->_initialize_transaction();
978
+		// verify transaction
979
+		if ($transaction instanceof EE_Transaction) {
980
+			// save it so that we have an ID for other objects to use
981
+			$transaction->save();
982
+			// and save TXN data to the cart
983
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
984
+		} else {
985
+			EE_Error::add_error(
986
+				__('A Valid Transaction could not be initialized.', 'event_espresso'),
987
+				__FILE__, __FUNCTION__, __LINE__
988
+			);
989
+		}
990
+		return $transaction;
991
+	}
992
+
993
+
994
+
995
+	/**
996
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
997
+	 *
998
+	 * @access private
999
+	 * @return mixed EE_Transaction|NULL
1000
+	 */
1001
+	private function _initialize_transaction()
1002
+	{
1003
+		try {
1004
+			// ensure cart totals have been calculated
1005
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
1006
+			// grab the cart grand total
1007
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
1008
+			// create new TXN
1009
+			$transaction = EE_Transaction::new_instance(
1010
+				array(
1011
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
1012
+					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
1013
+					'TXN_paid'      => 0,
1014
+					'STS_ID'        => EEM_Transaction::failed_status_code,
1015
+				)
1016
+			);
1017
+			// save it so that we have an ID for other objects to use
1018
+			$transaction->save();
1019
+			// set cron job for following up on TXNs after their session has expired
1020
+			EE_Cron_Tasks::schedule_expired_transaction_check(
1021
+				EE_Registry::instance()->SSN->expiration() + 1,
1022
+				$transaction->ID()
1023
+			);
1024
+			return $transaction;
1025
+		} catch (Exception $e) {
1026
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1027
+		}
1028
+		return null;
1029
+	}
1030
+
1031
+
1032
+	/**
1033
+	 * _get_registrations
1034
+	 *
1035
+	 * @access private
1036
+	 * @param EE_Transaction $transaction
1037
+	 * @return void
1038
+	 * @throws InvalidDataTypeException
1039
+	 * @throws InvalidEntityException
1040
+	 * @throws EE_Error
1041
+	 */
1042
+	private function _get_registrations(EE_Transaction $transaction)
1043
+	{
1044
+		// first step: grab the registrants  { : o
1045
+		$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
1046
+		// verify registrations have been set
1047
+		if (empty($registrations)) {
1048
+			// if no cached registrations, then check the db
1049
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1050
+			// still nothing ? well as long as this isn't a revisit
1051
+			if (empty($registrations) && ! $this->checkout->revisit) {
1052
+				// generate new registrations from scratch
1053
+				$registrations = $this->_initialize_registrations($transaction);
1054
+			}
1055
+		}
1056
+		// sort by their original registration order
1057
+		usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1058
+		// then loop thru the array
1059
+		foreach ($registrations as $registration) {
1060
+			// verify each registration
1061
+			if ($registration instanceof EE_Registration) {
1062
+				// we display all attendee info for the primary registrant
1063
+				if ($this->checkout->reg_url_link === $registration->reg_url_link()
1064
+					&& $registration->is_primary_registrant()
1065
+				) {
1066
+					$this->checkout->primary_revisit = true;
1067
+					break;
1068
+				}
1069
+				if ($this->checkout->revisit
1070
+						   && $this->checkout->reg_url_link !== $registration->reg_url_link()
1071
+				) {
1072
+					// but hide info if it doesn't belong to you
1073
+					$transaction->clear_cache('Registration', $registration->ID());
1074
+				}
1075
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1076
+			}
1077
+		}
1078
+	}
1079
+
1080
+
1081
+	/**
1082
+	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1083
+	 *
1084
+	 * @access private
1085
+	 * @param EE_Transaction $transaction
1086
+	 * @return    array
1087
+	 * @throws InvalidDataTypeException
1088
+	 * @throws InvalidEntityException
1089
+	 * @throws EE_Error
1090
+	 */
1091
+	private function _initialize_registrations(EE_Transaction $transaction)
1092
+	{
1093
+		$att_nmbr = 0;
1094
+		$registrations = array();
1095
+		if ($transaction instanceof EE_Transaction) {
1096
+			/** @type EE_Registration_Processor $registration_processor */
1097
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1098
+			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1099
+			// now let's add the cart items to the $transaction
1100
+			foreach ($this->checkout->cart->get_tickets() as $line_item) {
1101
+				//do the following for each ticket of this type they selected
1102
+				for ($x = 1; $x <= $line_item->quantity(); $x++) {
1103
+					$att_nmbr++;
1104
+					/** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1105
+					$CreateRegistrationCommand = EE_Registry::instance()->create(
1106
+						'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1107
+						array(
1108
+							$transaction,
1109
+							$line_item,
1110
+							$att_nmbr,
1111
+							$this->checkout->total_ticket_count,
1112
+						)
1113
+					);
1114
+					// override capabilities for frontend registrations
1115
+					if ( ! is_admin()) {
1116
+						$CreateRegistrationCommand->setCapCheck(
1117
+							new PublicCapabilities('', 'create_new_registration')
1118
+						);
1119
+					}
1120
+					$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1121
+					if ( ! $registration instanceof EE_Registration) {
1122
+						throw new InvalidEntityException($registration, 'EE_Registration');
1123
+					}
1124
+					$registrations[ $registration->ID() ] = $registration;
1125
+				}
1126
+			}
1127
+			$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1128
+		}
1129
+		return $registrations;
1130
+	}
1131
+
1132
+
1133
+
1134
+	/**
1135
+	 * sorts registrations by REG_count
1136
+	 *
1137
+	 * @access public
1138
+	 * @param EE_Registration $reg_A
1139
+	 * @param EE_Registration $reg_B
1140
+	 * @return int
1141
+	 */
1142
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1143
+	{
1144
+		// this shouldn't ever happen within the same TXN, but oh well
1145
+		if ($reg_A->count() === $reg_B->count()) {
1146
+			return 0;
1147
+		}
1148
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1149
+	}
1150
+
1151
+
1152
+
1153
+	/**
1154
+	 *    _final_verifications
1155
+	 * just makes sure that everything is set up correctly before proceeding
1156
+	 *
1157
+	 * @access    private
1158
+	 * @return    bool
1159
+	 * @throws EE_Error
1160
+	 */
1161
+	private function _final_verifications()
1162
+	{
1163
+		// filter checkout
1164
+		$this->checkout = apply_filters(
1165
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1166
+			$this->checkout
1167
+		);
1168
+		//verify that current step is still set correctly
1169
+		if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1170
+			EE_Error::add_error(
1171
+				__('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1172
+				__FILE__,
1173
+				__FUNCTION__,
1174
+				__LINE__
1175
+			);
1176
+			return false;
1177
+		}
1178
+		// if returning to SPCO, then verify that primary registrant is set
1179
+		if ( ! empty($this->checkout->reg_url_link)) {
1180
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1181
+			if ( ! $valid_registrant instanceof EE_Registration) {
1182
+				EE_Error::add_error(
1183
+					__('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1184
+					__FILE__,
1185
+					__FUNCTION__,
1186
+					__LINE__
1187
+				);
1188
+				return false;
1189
+			}
1190
+			$valid_registrant = null;
1191
+			foreach (
1192
+				$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration
1193
+			) {
1194
+				if (
1195
+					$registration instanceof EE_Registration
1196
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1197
+				) {
1198
+					$valid_registrant = $registration;
1199
+				}
1200
+			}
1201
+			if ( ! $valid_registrant instanceof EE_Registration) {
1202
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1203
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1204
+					// clear the session, mark the checkout as unverified, and try again
1205
+					EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1206
+					EED_Single_Page_Checkout::$_initialized = false;
1207
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1208
+					$this->_initialize();
1209
+					EE_Error::reset_notices();
1210
+					return false;
1211
+				}
1212
+				EE_Error::add_error(
1213
+					__(
1214
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1215
+						'event_espresso'
1216
+					),
1217
+					__FILE__,
1218
+					__FUNCTION__,
1219
+					__LINE__
1220
+				);
1221
+				return false;
1222
+			}
1223
+		}
1224
+		// now that things have been kinda sufficiently verified,
1225
+		// let's add the checkout to the session so that it's available to other systems
1226
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1227
+		return true;
1228
+	}
1229
+
1230
+
1231
+
1232
+	/**
1233
+	 *    _initialize_reg_steps
1234
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1235
+	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1236
+	 *
1237
+	 * @access    private
1238
+	 * @param bool $reinitializing
1239
+	 * @throws EE_Error
1240
+	 */
1241
+	private function _initialize_reg_steps($reinitializing = false)
1242
+	{
1243
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1244
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1245
+		foreach ($this->checkout->reg_steps as $reg_step) {
1246
+			if ( ! $reg_step->initialize_reg_step()) {
1247
+				// if not initialized then maybe this step is being removed...
1248
+				if ( ! $reinitializing && $reg_step->is_current_step()) {
1249
+					// if it was the current step, then we need to start over here
1250
+					$this->_initialize_reg_steps(true);
1251
+					return;
1252
+				}
1253
+				continue;
1254
+			}
1255
+			// add css and JS for current step
1256
+			$reg_step->enqueue_styles_and_scripts();
1257
+			// i18n
1258
+			$reg_step->translate_js_strings();
1259
+			if ($reg_step->is_current_step()) {
1260
+				// the text that appears on the reg step form submit button
1261
+				$reg_step->set_submit_button_text();
1262
+			}
1263
+		}
1264
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1265
+		do_action(
1266
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1267
+			$this->checkout->current_step
1268
+		);
1269
+	}
1270
+
1271
+
1272
+
1273
+	/**
1274
+	 * _check_form_submission
1275
+	 *
1276
+	 * @access private
1277
+	 * @return boolean
1278
+	 */
1279
+	private function _check_form_submission()
1280
+	{
1281
+		//does this request require the reg form to be generated ?
1282
+		if ($this->checkout->generate_reg_form) {
1283
+			// ever heard that song by Blue Rodeo ?
1284
+			try {
1285
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1286
+				// if not displaying a form, then check for form submission
1287
+				if (
1288
+					$this->checkout->process_form_submission
1289
+					&& $this->checkout->current_step->reg_form->was_submitted()
1290
+				) {
1291
+					// clear out any old data in case this step is being run again
1292
+					$this->checkout->current_step->set_valid_data(array());
1293
+					// capture submitted form data
1294
+					$this->checkout->current_step->reg_form->receive_form_submission(
1295
+						apply_filters(
1296
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1297
+							EE_Registry::instance()->REQ->params(),
1298
+							$this->checkout
1299
+						)
1300
+					);
1301
+					// validate submitted form data
1302
+					if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1303
+						// thou shall not pass !!!
1304
+						$this->checkout->continue_reg = false;
1305
+						// any form validation errors?
1306
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1307
+							$submission_error_messages = array();
1308
+							// bad, bad, bad registrant
1309
+							foreach (
1310
+								$this->checkout->current_step->reg_form->get_validation_errors_accumulated()
1311
+								as $validation_error
1312
+							) {
1313
+								if ($validation_error instanceof EE_Validation_Error) {
1314
+									$submission_error_messages[] = sprintf(
1315
+										__('%s : %s', 'event_espresso'),
1316
+										$validation_error->get_form_section()->html_label_text(),
1317
+										$validation_error->getMessage()
1318
+									);
1319
+								}
1320
+							}
1321
+							EE_Error::add_error(
1322
+								implode('<br />', $submission_error_messages),
1323
+								__FILE__, __FUNCTION__, __LINE__
1324
+							);
1325
+						}
1326
+						// well not really... what will happen is
1327
+						// we'll just get redirected back to redo the current step
1328
+						$this->go_to_next_step();
1329
+						return false;
1330
+					}
1331
+				}
1332
+			} catch (EE_Error $e) {
1333
+				$e->get_error();
1334
+			}
1335
+		}
1336
+		return true;
1337
+	}
1338
+
1339
+
1340
+
1341
+	/**
1342
+	 * _process_action
1343
+	 *
1344
+	 * @access private
1345
+	 * @return void
1346
+	 * @throws EE_Error
1347
+	 */
1348
+	private function _process_form_action()
1349
+	{
1350
+		// what cha wanna do?
1351
+		switch ($this->checkout->action) {
1352
+			// AJAX next step reg form
1353
+			case 'display_spco_reg_step' :
1354
+				$this->checkout->redirect = false;
1355
+				if (EE_Registry::instance()->REQ->ajax) {
1356
+					$this->checkout->json_response->set_reg_step_html(
1357
+						$this->checkout->current_step->display_reg_form()
1358
+					);
1359
+				}
1360
+				break;
1361
+			default :
1362
+				// meh... do one of those other steps first
1363
+				if (
1364
+					! empty($this->checkout->action)
1365
+					&& is_callable(array($this->checkout->current_step, $this->checkout->action))
1366
+				) {
1367
+					// dynamically creates hook point like:
1368
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1369
+					do_action(
1370
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1371
+						$this->checkout->current_step
1372
+					);
1373
+					// call action on current step
1374
+					if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1375
+						// good registrant, you get to proceed
1376
+						if (
1377
+							$this->checkout->current_step->success_message() !== ''
1378
+							&& apply_filters(
1379
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1380
+								false
1381
+							)
1382
+						) {
1383
+							EE_Error::add_success(
1384
+								$this->checkout->current_step->success_message()
1385
+								. '<br />' . $this->checkout->next_step->_instructions()
1386
+							);
1387
+						}
1388
+						// pack it up, pack it in...
1389
+						$this->_setup_redirect();
1390
+					}
1391
+					// dynamically creates hook point like:
1392
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1393
+					do_action(
1394
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1395
+						$this->checkout->current_step
1396
+					);
1397
+				} else {
1398
+					EE_Error::add_error(
1399
+						sprintf(
1400
+							__(
1401
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1402
+								'event_espresso'
1403
+							),
1404
+							$this->checkout->action,
1405
+							$this->checkout->current_step->name()
1406
+						),
1407
+						__FILE__,
1408
+						__FUNCTION__,
1409
+						__LINE__
1410
+					);
1411
+				}
1412
+			// end default
1413
+		}
1414
+		// store our progress so far
1415
+		$this->checkout->stash_transaction_and_checkout();
1416
+		// advance to the next step! If you pass GO, collect $200
1417
+		$this->go_to_next_step();
1418
+	}
1419
+
1420
+
1421
+
1422
+	/**
1423
+	 *        add_styles_and_scripts
1424
+	 *
1425
+	 * @access        public
1426
+	 * @return        void
1427
+	 */
1428
+	public function add_styles_and_scripts()
1429
+	{
1430
+		// i18n
1431
+		$this->translate_js_strings();
1432
+		if ($this->checkout->admin_request) {
1433
+			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1434
+		} else {
1435
+			add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1436
+		}
1437
+	}
1438
+
1439
+
1440
+
1441
+	/**
1442
+	 *        translate_js_strings
1443
+	 *
1444
+	 * @access        public
1445
+	 * @return        void
1446
+	 */
1447
+	public function translate_js_strings()
1448
+	{
1449
+		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1450
+		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1451
+		EE_Registry::$i18n_js_strings['server_error'] = __(
1452
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1453
+			'event_espresso'
1454
+		);
1455
+		EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1456
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1457
+			'event_espresso'
1458
+		);
1459
+		EE_Registry::$i18n_js_strings['validation_error'] = __(
1460
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1461
+			'event_espresso'
1462
+		);
1463
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1464
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1465
+			'event_espresso'
1466
+		);
1467
+		EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1468
+			'This registration step could not be completed. Please refresh the page and try again.',
1469
+			'event_espresso'
1470
+		);
1471
+		EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1472
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1473
+			'event_espresso'
1474
+		);
1475
+		EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1476
+			__(
1477
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1478
+				'event_espresso'
1479
+			),
1480
+			'<br/>',
1481
+			'<br/>'
1482
+		);
1483
+		EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1484
+		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1485
+		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1486
+		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1487
+		EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1488
+		EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1489
+		EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1490
+		EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1491
+		EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1492
+		EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1493
+		EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1494
+		EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1495
+		EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1496
+		EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1497
+		EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1498
+		EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1499
+		EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1500
+		EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1501
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1502
+			__(
1503
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
1504
+				'event_espresso'
1505
+			),
1506
+			'<h4 class="important-notice">',
1507
+			'</h4>',
1508
+			'<br />',
1509
+			'<p>',
1510
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1511
+			'">',
1512
+			'</a>',
1513
+			'</p>'
1514
+		);
1515
+		EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1516
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1517
+			true
1518
+		);
1519
+		EE_Registry::$i18n_js_strings['session_extension'] = absint(
1520
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1521
+		);
1522
+		EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1523
+			'M d, Y H:i:s',
1524
+			EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1525
+		);
1526
+	}
1527
+
1528
+
1529
+
1530
+	/**
1531
+	 *    enqueue_styles_and_scripts
1532
+	 *
1533
+	 * @access        public
1534
+	 * @return        void
1535
+	 * @throws EE_Error
1536
+	 */
1537
+	public function enqueue_styles_and_scripts()
1538
+	{
1539
+		// load css
1540
+		wp_register_style(
1541
+			'single_page_checkout',
1542
+			SPCO_CSS_URL . 'single_page_checkout.css',
1543
+			array('espresso_default'),
1544
+			EVENT_ESPRESSO_VERSION
1545
+		);
1546
+		wp_enqueue_style('single_page_checkout');
1547
+		// load JS
1548
+		wp_register_script(
1549
+			'jquery_plugin',
1550
+			EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1551
+			array('jquery'),
1552
+			'1.0.1',
1553
+			true
1554
+		);
1555
+		wp_register_script(
1556
+			'jquery_countdown',
1557
+			EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1558
+			array('jquery_plugin'),
1559
+			'2.0.2',
1560
+			true
1561
+		);
1562
+		wp_register_script(
1563
+			'single_page_checkout',
1564
+			SPCO_JS_URL . 'single_page_checkout.js',
1565
+			array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1566
+			EVENT_ESPRESSO_VERSION,
1567
+			true
1568
+		);
1569
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1570
+			$this->checkout->registration_form->enqueue_js();
1571
+		}
1572
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1573
+			$this->checkout->current_step->reg_form->enqueue_js();
1574
+		}
1575
+		wp_enqueue_script('single_page_checkout');
1576
+		/**
1577
+		 * global action hook for enqueueing styles and scripts with
1578
+		 * spco calls.
1579
+		 */
1580
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1581
+		/**
1582
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1583
+		 * The hook will end up being something like:
1584
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1585
+		 */
1586
+		do_action(
1587
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1588
+			$this
1589
+		);
1590
+	}
1591
+
1592
+
1593
+
1594
+	/**
1595
+	 *    display the Registration Single Page Checkout Form
1596
+	 *
1597
+	 * @access    private
1598
+	 * @return    void
1599
+	 * @throws EE_Error
1600
+	 */
1601
+	private function _display_spco_reg_form()
1602
+	{
1603
+		// if registering via the admin, just display the reg form for the current step
1604
+		if ($this->checkout->admin_request) {
1605
+			EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1606
+		} else {
1607
+			// add powered by EE msg
1608
+			add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1609
+			$empty_cart = count(
1610
+				$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1611
+			) < 1;
1612
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1613
+			$cookies_not_set_msg = '';
1614
+			if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1615
+				$cookies_not_set_msg = apply_filters(
1616
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1617
+					sprintf(
1618
+						__(
1619
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1620
+							'event_espresso'
1621
+						),
1622
+						'<div class="ee-attention">',
1623
+						'</div>',
1624
+						'<h6 class="important-notice">',
1625
+						'</h6>',
1626
+						'<p>',
1627
+						'</p>',
1628
+						'<br />',
1629
+						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1630
+						'</a>'
1631
+					)
1632
+				);
1633
+			}
1634
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1635
+				array(
1636
+					'name'            => 'single-page-checkout',
1637
+					'html_id'         => 'ee-single-page-checkout-dv',
1638
+					'layout_strategy' =>
1639
+						new EE_Template_Layout(
1640
+							array(
1641
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1642
+								'template_args'        => array(
1643
+									'empty_cart'              => $empty_cart,
1644
+									'revisit'                 => $this->checkout->revisit,
1645
+									'reg_steps'               => $this->checkout->reg_steps,
1646
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1647
+										? $this->checkout->next_step->slug()
1648
+										: '',
1649
+									'cancel_page_url'         => $this->checkout->cancel_page_url,
1650
+									'empty_msg'               => apply_filters(
1651
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1652
+										sprintf(
1653
+											__(
1654
+												'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1655
+												'event_espresso'
1656
+											),
1657
+											'<a href="'
1658
+											. get_post_type_archive_link('espresso_events')
1659
+											. '" title="',
1660
+											'">',
1661
+											'</a>'
1662
+										)
1663
+									),
1664
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1665
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1666
+									'session_expiration'      => gmdate(
1667
+										'M d, Y H:i:s',
1668
+										EE_Registry::instance()->SSN->expiration()
1669
+										+ (get_option('gmt_offset') * HOUR_IN_SECONDS)
1670
+									),
1671
+								),
1672
+							)
1673
+						),
1674
+				)
1675
+			);
1676
+			// load template and add to output sent that gets filtered into the_content()
1677
+			EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1678
+		}
1679
+	}
1680
+
1681
+
1682
+
1683
+	/**
1684
+	 *    add_extra_finalize_registration_inputs
1685
+	 *
1686
+	 * @access    public
1687
+	 * @param $next_step
1688
+	 * @internal  param string $label
1689
+	 * @return void
1690
+	 */
1691
+	public function add_extra_finalize_registration_inputs($next_step)
1692
+	{
1693
+		if ($next_step === 'finalize_registration') {
1694
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1695
+		}
1696
+	}
1697
+
1698
+
1699
+
1700
+	/**
1701
+	 *    display_registration_footer
1702
+	 *
1703
+	 * @access    public
1704
+	 * @return    string
1705
+	 */
1706
+	public static function display_registration_footer()
1707
+	{
1708
+		if (
1709
+		apply_filters(
1710
+			'FHEE__EE_Front__Controller__show_reg_footer',
1711
+			EE_Registry::instance()->CFG->admin->show_reg_footer
1712
+		)
1713
+		) {
1714
+			add_filter(
1715
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1716
+				function ($url) {
1717
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1718
+				}
1719
+			);
1720
+			echo apply_filters(
1721
+				'FHEE__EE_Front_Controller__display_registration_footer',
1722
+				\EEH_Template::powered_by_event_espresso(
1723
+					'',
1724
+					'espresso-registration-footer-dv',
1725
+					array('utm_content' => 'registration_checkout')
1726
+				)
1727
+			);
1728
+		}
1729
+		return '';
1730
+	}
1731
+
1732
+
1733
+
1734
+	/**
1735
+	 *    unlock_transaction
1736
+	 *
1737
+	 * @access    public
1738
+	 * @return    void
1739
+	 * @throws EE_Error
1740
+	 */
1741
+	public function unlock_transaction()
1742
+	{
1743
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1744
+			$this->checkout->transaction->unlock();
1745
+		}
1746
+	}
1747
+
1748
+
1749
+
1750
+	/**
1751
+	 *        _setup_redirect
1752
+	 *
1753
+	 * @access    private
1754
+	 * @return void
1755
+	 */
1756
+	private function _setup_redirect()
1757
+	{
1758
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1759
+			$this->checkout->redirect = true;
1760
+			if (empty($this->checkout->redirect_url)) {
1761
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1762
+			}
1763
+			$this->checkout->redirect_url = apply_filters(
1764
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1765
+				$this->checkout->redirect_url,
1766
+				$this->checkout
1767
+			);
1768
+		}
1769
+	}
1770
+
1771
+
1772
+
1773
+	/**
1774
+	 *   handle ajax message responses and redirects
1775
+	 *
1776
+	 * @access public
1777
+	 * @return void
1778
+	 * @throws EE_Error
1779
+	 */
1780
+	public function go_to_next_step()
1781
+	{
1782
+		if (EE_Registry::instance()->REQ->ajax) {
1783
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1784
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1785
+		}
1786
+		$this->unlock_transaction();
1787
+		// just return for these conditions
1788
+		if (
1789
+			$this->checkout->admin_request
1790
+			|| $this->checkout->action === 'redirect_form'
1791
+			|| $this->checkout->action === 'update_checkout'
1792
+		) {
1793
+			return;
1794
+		}
1795
+		// AJAX response
1796
+		$this->_handle_json_response();
1797
+		// redirect to next step or the Thank You page
1798
+		$this->_handle_html_redirects();
1799
+		// hmmm... must be something wrong, so let's just display the form again !
1800
+		$this->_display_spco_reg_form();
1801
+	}
1802
+
1803
+
1804
+
1805
+	/**
1806
+	 *   _handle_json_response
1807
+	 *
1808
+	 * @access protected
1809
+	 * @return void
1810
+	 */
1811
+	protected function _handle_json_response()
1812
+	{
1813
+		// if this is an ajax request
1814
+		if (EE_Registry::instance()->REQ->ajax) {
1815
+			// DEBUG LOG
1816
+			//$this->checkout->log(
1817
+			//	__CLASS__, __FUNCTION__, __LINE__,
1818
+			//	array(
1819
+			//		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1820
+			//		'redirect'                   => $this->checkout->redirect,
1821
+			//		'continue_reg'               => $this->checkout->continue_reg,
1822
+			//	)
1823
+			//);
1824
+			$this->checkout->json_response->set_registration_time_limit(
1825
+				$this->checkout->get_registration_time_limit()
1826
+			);
1827
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1828
+			// just send the ajax (
1829
+			$json_response = apply_filters(
1830
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1831
+				$this->checkout->json_response
1832
+			);
1833
+			echo $json_response;
1834
+			exit();
1835
+		}
1836
+	}
1837
+
1838
+
1839
+
1840
+	/**
1841
+	 *   _handle_redirects
1842
+	 *
1843
+	 * @access protected
1844
+	 * @return void
1845
+	 */
1846
+	protected function _handle_html_redirects()
1847
+	{
1848
+		// going somewhere ?
1849
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1850
+			// store notices in a transient
1851
+			EE_Error::get_notices(false, true, true);
1852
+			// DEBUG LOG
1853
+			//$this->checkout->log(
1854
+			//	__CLASS__, __FUNCTION__, __LINE__,
1855
+			//	array(
1856
+			//		'headers_sent' => headers_sent(),
1857
+			//		'redirect_url'     => $this->checkout->redirect_url,
1858
+			//		'headers_list'    => headers_list(),
1859
+			//	)
1860
+			//);
1861
+			wp_safe_redirect($this->checkout->redirect_url);
1862
+			exit();
1863
+		}
1864
+	}
1865
+
1866
+
1867
+
1868
+	/**
1869
+	 *   set_checkout_anchor
1870
+	 *
1871
+	 * @access public
1872
+	 * @return void
1873
+	 */
1874
+	public function set_checkout_anchor()
1875
+	{
1876
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1877
+	}
1878 1878
 
1879 1879
 
1880 1880
 
Please login to merge, or discard this patch.
Spacing   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -218,19 +218,19 @@  discard block
 block discarded – undo
218 218
      */
219 219
     public static function set_definitions()
220 220
     {
221
-        if(defined('SPCO_BASE_PATH')) {
221
+        if (defined('SPCO_BASE_PATH')) {
222 222
             return;
223 223
         }
224 224
         define(
225 225
             'SPCO_BASE_PATH',
226
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
226
+            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS).DS
227 227
         );
228
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
228
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css'.DS);
229
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img'.DS);
230
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js'.DS);
231
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc'.DS);
232
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps'.DS);
233
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates'.DS);
234 234
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235 235
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
236 236
             __('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
             '</h4>',
240 240
             '<br />',
241 241
             '<p>',
242
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
242
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
243 243
             '">',
244 244
             '</a>',
245 245
             '</p>'
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
             return;
263 263
         }
264 264
         // filter list of reg_steps
265
-        $reg_steps_to_load = (array)apply_filters(
265
+        $reg_steps_to_load = (array) apply_filters(
266 266
             'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
267 267
             EED_Single_Page_Checkout::get_reg_steps()
268 268
         );
@@ -314,25 +314,25 @@  discard block
 block discarded – undo
314 314
         if (empty($reg_steps)) {
315 315
             $reg_steps = array(
316 316
                 10  => array(
317
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
317
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
318 318
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
319 319
                     'slug'       => 'attendee_information',
320 320
                     'has_hooks'  => false,
321 321
                 ),
322 322
                 20  => array(
323
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
323
+                    'file_path'  => SPCO_REG_STEPS_PATH.'registration_confirmation',
324 324
                     'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
325 325
                     'slug'       => 'registration_confirmation',
326 326
                     'has_hooks'  => false,
327 327
                 ),
328 328
                 30  => array(
329
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
329
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
330 330
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
331 331
                     'slug'       => 'payment_options',
332 332
                     'has_hooks'  => true,
333 333
                 ),
334 334
                 999 => array(
335
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
335
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
336 336
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
337 337
                     'slug'       => 'finalize_registration',
338 338
                     'has_hooks'  => false,
@@ -516,7 +516,7 @@  discard block
 block discarded – undo
516 516
             // DEBUG LOG
517 517
             //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
518 518
             // get reg form
519
-            if( ! $this->_check_form_submission()) {
519
+            if ( ! $this->_check_form_submission()) {
520 520
                 EED_Single_Page_Checkout::$_initialized = true;
521 521
                 return;
522 522
             }
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
         );
558 558
         // is session still valid ?
559 559
         if ($clear_session_requested
560
-            || ( EE_Registry::instance()->SSN->expired()
560
+            || (EE_Registry::instance()->SSN->expired()
561 561
               && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
562 562
             )
563 563
         ) {
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
             // EE_Registry::instance()->SSN->reset_cart();
567 567
             // EE_Registry::instance()->SSN->reset_checkout();
568 568
             // EE_Registry::instance()->SSN->reset_transaction();
569
-            if (! $clear_session_requested) {
569
+            if ( ! $clear_session_requested) {
570 570
                 EE_Error::add_attention(
571 571
                     EE_Registry::$i18n_js_strings['registration_expiration_notice'],
572 572
                     __FILE__, __FUNCTION__, __LINE__
@@ -1121,7 +1121,7 @@  discard block
 block discarded – undo
1121 1121
                     if ( ! $registration instanceof EE_Registration) {
1122 1122
                         throw new InvalidEntityException($registration, 'EE_Registration');
1123 1123
                     }
1124
-                    $registrations[ $registration->ID() ] = $registration;
1124
+                    $registrations[$registration->ID()] = $registration;
1125 1125
                 }
1126 1126
             }
1127 1127
             $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1382,7 +1382,7 @@  discard block
 block discarded – undo
1382 1382
                         ) {
1383 1383
                             EE_Error::add_success(
1384 1384
                                 $this->checkout->current_step->success_message()
1385
-                                . '<br />' . $this->checkout->next_step->_instructions()
1385
+                                . '<br />'.$this->checkout->next_step->_instructions()
1386 1386
                             );
1387 1387
                         }
1388 1388
                         // pack it up, pack it in...
@@ -1507,7 +1507,7 @@  discard block
 block discarded – undo
1507 1507
             '</h4>',
1508 1508
             '<br />',
1509 1509
             '<p>',
1510
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1510
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
1511 1511
             '">',
1512 1512
             '</a>',
1513 1513
             '</p>'
@@ -1539,7 +1539,7 @@  discard block
 block discarded – undo
1539 1539
         // load css
1540 1540
         wp_register_style(
1541 1541
             'single_page_checkout',
1542
-            SPCO_CSS_URL . 'single_page_checkout.css',
1542
+            SPCO_CSS_URL.'single_page_checkout.css',
1543 1543
             array('espresso_default'),
1544 1544
             EVENT_ESPRESSO_VERSION
1545 1545
         );
@@ -1547,21 +1547,21 @@  discard block
 block discarded – undo
1547 1547
         // load JS
1548 1548
         wp_register_script(
1549 1549
             'jquery_plugin',
1550
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1550
+            EE_THIRD_PARTY_URL.'jquery	.plugin.min.js',
1551 1551
             array('jquery'),
1552 1552
             '1.0.1',
1553 1553
             true
1554 1554
         );
1555 1555
         wp_register_script(
1556 1556
             'jquery_countdown',
1557
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1557
+            EE_THIRD_PARTY_URL.'jquery	.countdown.min.js',
1558 1558
             array('jquery_plugin'),
1559 1559
             '2.0.2',
1560 1560
             true
1561 1561
         );
1562 1562
         wp_register_script(
1563 1563
             'single_page_checkout',
1564
-            SPCO_JS_URL . 'single_page_checkout.js',
1564
+            SPCO_JS_URL.'single_page_checkout.js',
1565 1565
             array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1566 1566
             EVENT_ESPRESSO_VERSION,
1567 1567
             true
@@ -1584,7 +1584,7 @@  discard block
 block discarded – undo
1584 1584
          *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1585 1585
          */
1586 1586
         do_action(
1587
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1587
+            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(),
1588 1588
             $this
1589 1589
         );
1590 1590
     }
@@ -1638,7 +1638,7 @@  discard block
 block discarded – undo
1638 1638
                     'layout_strategy' =>
1639 1639
                         new EE_Template_Layout(
1640 1640
                             array(
1641
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1641
+                                'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
1642 1642
                                 'template_args'        => array(
1643 1643
                                     'empty_cart'              => $empty_cart,
1644 1644
                                     'revisit'                 => $this->checkout->revisit,
@@ -1713,7 +1713,7 @@  discard block
 block discarded – undo
1713 1713
         ) {
1714 1714
             add_filter(
1715 1715
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1716
-                function ($url) {
1716
+                function($url) {
1717 1717
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1718 1718
                 }
1719 1719
             );
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +1967 added lines, -1967 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 /**
@@ -27,1975 +27,1975 @@  discard block
 block discarded – undo
27 27
 class Transactions_Admin_Page extends EE_Admin_Page
28 28
 {
29 29
 
30
-    /**
31
-     * @var EE_Transaction
32
-     */
33
-    private $_transaction;
34
-
35
-    /**
36
-     * @var EE_Session
37
-     */
38
-    private $_session;
39
-
40
-    /**
41
-     * @var array $_txn_status
42
-     */
43
-    private static $_txn_status;
44
-
45
-    /**
46
-     * @var array $_pay_status
47
-     */
48
-    private static $_pay_status;
49
-
50
-    /**
51
-     * @var array $_existing_reg_payment_REG_IDs
52
-     */
53
-    protected $_existing_reg_payment_REG_IDs = null;
54
-
55
-
56
-    /**
57
-     * @Constructor
58
-     * @access public
59
-     *
60
-     * @param bool $routing
61
-     *
62
-     * @return Transactions_Admin_Page
63
-     */
64
-    public function __construct($routing = true)
65
-    {
66
-        parent::__construct($routing);
67
-    }
68
-
69
-
70
-    /**
71
-     *    _init_page_props
72
-     * @return void
73
-     */
74
-    protected function _init_page_props()
75
-    {
76
-        $this->page_slug        = TXN_PG_SLUG;
77
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
78
-        $this->_admin_base_url  = TXN_ADMIN_URL;
79
-        $this->_admin_base_path = TXN_ADMIN;
80
-    }
81
-
82
-
83
-    /**
84
-     *    _ajax_hooks
85
-     * @return void
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
90
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
91
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
92
-    }
93
-
94
-
95
-    /**
96
-     *    _define_page_props
97
-     * @return void
98
-     */
99
-    protected function _define_page_props()
100
-    {
101
-        $this->_admin_page_title = $this->page_label;
102
-        $this->_labels           = array(
103
-            'buttons' => array(
104
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
105
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
106
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
107
-            )
108
-        );
109
-    }
110
-
111
-
112
-    /**
113
-     *        grab url requests and route them
114
-     * @access private
115
-     * @return void
116
-     */
117
-    public function _set_page_routes()
118
-    {
119
-
120
-        $this->_set_transaction_status_array();
121
-
122
-        $txn_id = ! empty($this->_req_data['TXN_ID']) && ! is_array($this->_req_data['TXN_ID']) ? $this->_req_data['TXN_ID'] : 0;
123
-
124
-        $this->_page_routes = array(
125
-
126
-            'default' => array(
127
-                'func'       => '_transactions_overview_list_table',
128
-                'capability' => 'ee_read_transactions'
129
-            ),
130
-
131
-            'view_transaction' => array(
132
-                'func'       => '_transaction_details',
133
-                'capability' => 'ee_read_transaction',
134
-                'obj_id'     => $txn_id
135
-            ),
136
-
137
-            'send_payment_reminder' => array(
138
-                'func'       => '_send_payment_reminder',
139
-                'noheader'   => true,
140
-                'capability' => 'ee_send_message'
141
-            ),
142
-
143
-            'espresso_apply_payment' => array(
144
-                'func'       => 'apply_payments_or_refunds',
145
-                'noheader'   => true,
146
-                'capability' => 'ee_edit_payments'
147
-            ),
148
-
149
-            'espresso_apply_refund' => array(
150
-                'func'       => 'apply_payments_or_refunds',
151
-                'noheader'   => true,
152
-                'capability' => 'ee_edit_payments'
153
-            ),
154
-
155
-            'espresso_delete_payment' => array(
156
-                'func'       => 'delete_payment',
157
-                'noheader'   => true,
158
-                'capability' => 'ee_delete_payments'
159
-            ),
160
-
161
-        );
162
-
163
-    }
164
-
165
-
166
-    protected function _set_page_config()
167
-    {
168
-        $this->_page_config = array(
169
-            'default'          => array(
170
-                'nav'           => array(
171
-                    'label' => esc_html__('Overview', 'event_espresso'),
172
-                    'order' => 10
173
-                ),
174
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
175
-                'help_tabs'     => array(
176
-                    'transactions_overview_help_tab'                       => array(
177
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
178
-                        'filename' => 'transactions_overview'
179
-                    ),
180
-                    'transactions_overview_table_column_headings_help_tab' => array(
181
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
182
-                        'filename' => 'transactions_overview_table_column_headings'
183
-                    ),
184
-                    'transactions_overview_views_filters_help_tab'         => array(
185
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
186
-                        'filename' => 'transactions_overview_views_filters_search'
187
-                    ),
188
-                ),
189
-                'help_tour'     => array('Transactions_Overview_Help_Tour'),
190
-                /**
191
-                 * commented out because currently we are not displaying tips for transaction list table status but this
192
-                 * may change in a later iteration so want to keep the code for then.
193
-                 */
194
-                //'qtips' => array( 'Transactions_List_Table_Tips' ),
195
-                'require_nonce' => false
196
-            ),
197
-            'view_transaction' => array(
198
-                'nav'       => array(
199
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
200
-                    'order'      => 5,
201
-                    'url'        => isset($this->_req_data['TXN_ID']) ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']),
202
-                        $this->_current_page_view_url) : $this->_admin_base_url,
203
-                    'persistent' => false
204
-                ),
205
-                'help_tabs' => array(
206
-                    'transactions_view_transaction_help_tab'                                              => array(
207
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
208
-                        'filename' => 'transactions_view_transaction'
209
-                    ),
210
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
211
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
212
-                        'filename' => 'transactions_view_transaction_transaction_details_table'
213
-                    ),
214
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
215
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
216
-                        'filename' => 'transactions_view_transaction_attendees_registered'
217
-                    ),
218
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
219
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
220
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information'
221
-                    ),
222
-                ),
223
-                'qtips'     => array('Transaction_Details_Tips'),
224
-                'help_tour' => array('Transaction_Details_Help_Tour'),
225
-                'metaboxes' => array('_transaction_details_metaboxes'),
226
-
227
-                'require_nonce' => false
228
-            )
229
-        );
230
-    }
231
-
232
-
233
-    /**
234
-     * The below methods aren't used by this class currently
235
-     */
236
-    protected function _add_screen_options()
237
-    {
238
-    }
239
-
240
-    protected function _add_feature_pointers()
241
-    {
242
-    }
243
-
244
-    public function admin_init()
245
-    {
246
-        // IF a registration was JUST added via the admin...
247
-        if (
248
-        isset(
249
-            $this->_req_data['redirect_from'],
250
-            $this->_req_data['EVT_ID'],
251
-            $this->_req_data['event_name']
252
-        )
253
-        ) {
254
-            // then set a cookie so that we can block any attempts to use
255
-            // the back button as a way to enter another registration.
256
-            setcookie('ee_registration_added', $this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/');
257
-            // and update the global
258
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
259
-        }
260
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__('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.',
261
-            'event_espresso');
262
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__('An error occurred! Please refresh the page and try again.',
263
-            'event_espresso');
264
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
265
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
266
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
267
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__('This transaction has been overpaid ! Payments Total',
268
-            'event_espresso');
269
-    }
270
-
271
-    public function admin_notices()
272
-    {
273
-    }
274
-
275
-    public function admin_footer_scripts()
276
-    {
277
-    }
278
-
279
-
280
-    /**
281
-     * _set_transaction_status_array
282
-     * sets list of transaction statuses
283
-     *
284
-     * @access private
285
-     * @return void
286
-     */
287
-    private function _set_transaction_status_array()
288
-    {
289
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
290
-    }
291
-
292
-
293
-    /**
294
-     * get_transaction_status_array
295
-     * return the transaction status array for wp_list_table
296
-     *
297
-     * @access public
298
-     * @return array
299
-     */
300
-    public function get_transaction_status_array()
301
-    {
302
-        return self::$_txn_status;
303
-    }
304
-
305
-
306
-    /**
307
-     *    get list of payment statuses
308
-     *
309
-     * @access private
310
-     * @return void
311
-     */
312
-    private function _get_payment_status_array()
313
-    {
314
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
315
-        $this->_template_args['payment_status'] = self::$_pay_status;
316
-
317
-    }
318
-
319
-
320
-    /**
321
-     *    _add_screen_options_default
322
-     *
323
-     * @access protected
324
-     * @return void
325
-     */
326
-    protected function _add_screen_options_default()
327
-    {
328
-        $this->_per_page_screen_option();
329
-    }
330
-
331
-
332
-    /**
333
-     * load_scripts_styles
334
-     *
335
-     * @access public
336
-     * @return void
337
-     */
338
-    public function load_scripts_styles()
339
-    {
340
-        //enqueue style
341
-        wp_register_style('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.css', array(),
342
-            EVENT_ESPRESSO_VERSION);
343
-        wp_enqueue_style('espresso_txn');
344
-        //scripts
345
-        wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
346
-            'ee_admin_js',
347
-            'ee-datepicker',
348
-            'jquery-ui-datepicker',
349
-            'jquery-ui-draggable',
350
-            'ee-dialog',
351
-            'ee-accounting',
352
-            'ee-serialize-full-array'
353
-        ), EVENT_ESPRESSO_VERSION, true);
354
-        wp_enqueue_script('espresso_txn');
355
-
356
-    }
357
-
358
-
359
-    /**
360
-     *    load_scripts_styles_view_transaction
361
-     *
362
-     * @access public
363
-     * @return void
364
-     */
365
-    public function load_scripts_styles_view_transaction()
366
-    {
367
-        //styles
368
-        wp_enqueue_style('espresso-ui-theme');
369
-    }
370
-
371
-
372
-    /**
373
-     *    load_scripts_styles_default
374
-     *
375
-     * @access public
376
-     * @return void
377
-     */
378
-    public function load_scripts_styles_default()
379
-    {
380
-        //styles
381
-        wp_enqueue_style('espresso-ui-theme');
382
-    }
383
-
384
-
385
-    /**
386
-     *    _set_list_table_views_default
387
-     *
388
-     * @access protected
389
-     * @return void
390
-     */
391
-    protected function _set_list_table_views_default()
392
-    {
393
-        $this->_views = array(
394
-            'all'       => array(
395
-                'slug'  => 'all',
396
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
397
-                'count' => 0
398
-            ),
399
-            'abandoned' => array(
400
-                'slug'  => 'abandoned',
401
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
402
-                'count' => 0
403
-            ),
404
-            'failed'    => array(
405
-                'slug'  => 'failed',
406
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
407
-                'count' => 0
408
-            )
409
-        );
410
-    }
411
-
412
-
413
-    /**
414
-     * _set_transaction_object
415
-     * This sets the _transaction property for the transaction details screen
416
-     *
417
-     * @access private
418
-     * @return void
419
-     */
420
-    private function _set_transaction_object()
421
-    {
422
-        if (is_object($this->_transaction)) {
423
-            return;
424
-        } //get out we've already set the object
425
-
426
-        $TXN = EEM_Transaction::instance();
427
-
428
-        $TXN_ID = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
429
-
430
-        //get transaction object
431
-        $this->_transaction = $TXN->get_one_by_ID($TXN_ID);
432
-        $this->_session     = ! empty($this->_transaction) ? $this->_transaction->get('TXN_session_data') : null;
433
-        $this->_transaction->verify_abandoned_transaction_status();
434
-
435
-        if (empty($this->_transaction)) {
436
-            $error_msg = esc_html__('An error occurred and the details for Transaction ID #',
437
-                    'event_espresso') . $TXN_ID . esc_html__(' could not be retrieved.', 'event_espresso');
438
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
439
-        }
440
-    }
441
-
442
-
443
-    /**
444
-     *    _transaction_legend_items
445
-     *
446
-     * @access protected
447
-     * @return array
448
-     */
449
-    protected function _transaction_legend_items()
450
-    {
451
-        EE_Registry::instance()->load_helper('MSG_Template');
452
-        $items = array();
453
-
454
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
455
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
456
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
457
-                $items['view_related_messages'] = array(
458
-                    'class' => $related_for_icon['css_class'],
459
-                    'desc'  => $related_for_icon['label'],
460
-                );
461
-            }
462
-        }
463
-
464
-        $items = apply_filters(
465
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
466
-            array_merge($items,
467
-                array(
468
-                    'view_details'      => array(
469
-                        'class' => 'dashicons dashicons-cart',
470
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso')
471
-                    ),
472
-                    'view_invoice'      => array(
473
-                        'class' => 'dashicons dashicons-media-spreadsheet',
474
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso')
475
-                    ),
476
-                    'view_receipt'      => array(
477
-                        'class' => 'dashicons dashicons-media-default',
478
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso')
479
-                    ),
480
-                    'view_registration' => array(
481
-                        'class' => 'dashicons dashicons-clipboard',
482
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso')
483
-                    ),
484
-                    'payment_overview_link' => array(
485
-                        'class' => 'dashicons dashicons-money',
486
-                        'desc' => esc_html__('Make Payment on Frontend', 'event_espresso')
487
-                    )
488
-                )
489
-            )
490
-        );
491
-
492
-        if (EE_Registry::instance()->CAP->current_user_can('ee_send_message',
493
-            'espresso_transactions_send_payment_reminder')
494
-        ) {
495
-            if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
496
-                $items['send_payment_reminder'] = array(
497
-                    'class' => 'dashicons dashicons-email-alt',
498
-                    'desc'  => esc_html__('Send Payment Reminder', 'event_espresso')
499
-                );
500
-            } else {
501
-                $items['blank*'] = array(
502
-                    'class' => '',
503
-                    'desc'  => ''
504
-                );
505
-            }
506
-        } else {
507
-            $items['blank*'] = array(
508
-                'class' => '',
509
-                'desc'  => ''
510
-            );
511
-        }
512
-        $more_items = apply_filters(
513
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
514
-            array(
515
-                'overpaid'   => array(
516
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
517
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::overpaid_status_code, false, 'sentence')
518
-                ),
519
-                'complete'   => array(
520
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
521
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::complete_status_code, false, 'sentence')
522
-                ),
523
-                'incomplete' => array(
524
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
525
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::incomplete_status_code, false, 'sentence')
526
-                ),
527
-                'abandoned'  => array(
528
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
529
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::abandoned_status_code, false, 'sentence')
530
-                ),
531
-                'failed'     => array(
532
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
533
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::failed_status_code, false, 'sentence')
534
-                )
535
-            )
536
-        );
537
-
538
-        return array_merge($items, $more_items);
539
-    }
540
-
541
-
542
-    /**
543
-     *    _transactions_overview_list_table
544
-     *
545
-     * @access protected
546
-     * @return void
547
-     */
548
-    protected function _transactions_overview_list_table()
549
-    {
550
-        $this->_admin_page_title                   = esc_html__('Transactions', 'event_espresso');
551
-        $event                                     = isset($this->_req_data['EVT_ID']) ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']) : null;
552
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event ? sprintf(esc_html__('%sViewing Transactions for the Event: %s%s',
553
-            'event_espresso'), '<h3>',
554
-            '<a href="' . EE_Admin_Page::add_query_args_and_nonce(array('action' => 'edit', 'post' => $event->ID()),
555
-                EVENTS_ADMIN_URL) . '" title="' . esc_attr__('Click to Edit event',
556
-                'event_espresso') . '">' . $event->get('EVT_name') . '</a>', '</h3>') : '';
557
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
558
-        $this->display_admin_list_table_page_with_no_sidebar();
559
-    }
560
-
561
-
562
-    /**
563
-     *    _transaction_details
564
-     * generates HTML for the View Transaction Details Admin page
565
-     *
566
-     * @access protected
567
-     * @return void
568
-     */
569
-    protected function _transaction_details()
570
-    {
571
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
572
-
573
-        $this->_set_transaction_status_array();
574
-
575
-        $this->_template_args                      = array();
576
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
577
-
578
-        $this->_set_transaction_object();
579
-
580
-        $primary_registration = $this->_transaction->primary_registration();
581
-        $attendee             = $primary_registration instanceof EE_Registration ? $primary_registration->attendee() : null;
582
-
583
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
584
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
585
-
586
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
587
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
588
-
589
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
590
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
591
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
592
-
593
-        $this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
594
-        $this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
595
-
596
-        if (
597
-            $attendee instanceof EE_Attendee
598
-            && EE_Registry::instance()->CAP->current_user_can(
599
-                'ee_send_message',
600
-                'espresso_transactions_send_payment_reminder'
601
-            )
602
-        ) {
603
-            $this->_template_args['send_payment_reminder_button'] =
604
-                EEH_MSG_Template::is_mt_active('payment_reminder')
605
-                && $this->_transaction->get('STS_ID') != EEM_Transaction::complete_status_code
606
-                && $this->_transaction->get('STS_ID') != EEM_Transaction::overpaid_status_code
607
-                    ? EEH_Template::get_button_or_link(
608
-                    EE_Admin_Page::add_query_args_and_nonce(
609
-                        array(
610
-                            'action'      => 'send_payment_reminder',
611
-                            'TXN_ID'      => $this->_transaction->ID(),
612
-                            'redirect_to' => 'view_transaction'
613
-                        ),
614
-                        TXN_ADMIN_URL
615
-                    ),
616
-                    __(' Send Payment Reminder', 'event_espresso'),
617
-                    'button secondary-button right',
618
-                    'dashicons dashicons-email-alt'
619
-                )
620
-                    : '';
621
-        } else {
622
-            $this->_template_args['send_payment_reminder_button'] = '';
623
-        }
624
-
625
-        $amount_due                         = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
626
-        $this->_template_args['amount_due'] = EEH_Template::format_currency($amount_due, true);
627
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
628
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign . $this->_template_args['amount_due'];
629
-        } else {
630
-            $this->_template_args['amount_due'] = $this->_template_args['amount_due'] . EE_Registry::instance()->CFG->currency->sign;
631
-        }
632
-        $this->_template_args['amount_due_class'] = '';
633
-
634
-        if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
635
-            // paid in full
636
-            $this->_template_args['amount_due'] = false;
637
-        } elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
638
-            // overpaid
639
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
640
-        } elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') > 0)) {
641
-            // monies owing
642
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
643
-        } elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') == 0)) {
644
-            // no payments made yet
645
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
646
-        } elseif ($this->_transaction->get('TXN_total') == 0) {
647
-            // free event
648
-            $this->_template_args['amount_due'] = false;
649
-        }
650
-
651
-        $payment_method = $this->_transaction->payment_method();
652
-
653
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
654
-            ? $payment_method->admin_name()
655
-            : esc_html__('Unknown', 'event_espresso');
656
-
657
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
658
-        // link back to overview
659
-        $this->_template_args['txn_overview_url'] = ! empty ($_SERVER['HTTP_REFERER'])
660
-            ? $_SERVER['HTTP_REFERER']
661
-            : TXN_ADMIN_URL;
662
-
663
-
664
-        // next link
665
-        $next_txn                                 = $this->_transaction->next(
666
-            null,
667
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
668
-            'TXN_ID'
669
-        );
670
-        $this->_template_args['next_transaction'] = $next_txn
671
-            ? $this->_next_link(
672
-                EE_Admin_Page::add_query_args_and_nonce(
673
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
674
-                    TXN_ADMIN_URL
675
-                ),
676
-                'dashicons dashicons-arrow-right ee-icon-size-22'
677
-            )
678
-            : '';
679
-        // previous link
680
-        $previous_txn                                 = $this->_transaction->previous(
681
-            null,
682
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
683
-            'TXN_ID'
684
-        );
685
-        $this->_template_args['previous_transaction'] = $previous_txn
686
-            ? $this->_previous_link(
687
-                EE_Admin_Page::add_query_args_and_nonce(
688
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
689
-                    TXN_ADMIN_URL
690
-                ),
691
-                'dashicons dashicons-arrow-left ee-icon-size-22'
692
-            )
693
-            : '';
694
-
695
-        // were we just redirected here after adding a new registration ???
696
-        if (
697
-        isset(
698
-            $this->_req_data['redirect_from'],
699
-            $this->_req_data['EVT_ID'],
700
-            $this->_req_data['event_name']
701
-        )
702
-        ) {
703
-            if (
704
-            EE_Registry::instance()->CAP->current_user_can(
705
-                'ee_edit_registrations',
706
-                'espresso_registrations_new_registration',
707
-                $this->_req_data['EVT_ID']
708
-            )
709
-            ) {
710
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
711
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
712
-                    array(
713
-                        'page'     => 'espresso_registrations',
714
-                        'action'   => 'new_registration',
715
-                        'return'   => 'default',
716
-                        'TXN_ID'   => $this->_transaction->ID(),
717
-                        'event_id' => $this->_req_data['EVT_ID'],
718
-                    ),
719
-                    REG_ADMIN_URL
720
-                );
721
-                $this->_admin_page_title .= '">';
722
-
723
-                $this->_admin_page_title .= sprintf(
724
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
725
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
726
-                );
727
-                $this->_admin_page_title .= '</a>';
728
-            }
729
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
730
-        }
731
-        // grab messages at the last second
732
-        $this->_template_args['notices'] = EE_Error::get_notices();
733
-        // path to template
734
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
735
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template($template_path,
736
-            $this->_template_args, true);
737
-
738
-        // the details template wrapper
739
-        $this->display_admin_page_with_sidebar();
740
-
741
-    }
742
-
743
-
744
-    /**
745
-     *        _transaction_details_metaboxes
746
-     *
747
-     * @access protected
748
-     * @return void
749
-     */
750
-    protected function _transaction_details_metaboxes()
751
-    {
752
-
753
-        $this->_set_transaction_object();
754
-
755
-        add_meta_box('edit-txn-details-mbox', esc_html__('Transaction Details', 'event_espresso'),
756
-            array($this, 'txn_details_meta_box'), $this->_wp_page_slug, 'normal', 'high');
757
-        add_meta_box(
758
-            'edit-txn-attendees-mbox',
759
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
760
-            array($this, 'txn_attendees_meta_box'),
761
-            $this->_wp_page_slug,
762
-            'normal',
763
-            'high',
764
-            array('TXN_ID' => $this->_transaction->ID())
765
-        );
766
-        add_meta_box('edit-txn-registrant-mbox', esc_html__('Primary Contact', 'event_espresso'),
767
-            array($this, 'txn_registrant_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
768
-        add_meta_box('edit-txn-billing-info-mbox', esc_html__('Billing Information', 'event_espresso'),
769
-            array($this, 'txn_billing_info_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
770
-
771
-    }
772
-
773
-
774
-    /**
775
-     * txn_details_meta_box
776
-     * generates HTML for the Transaction main meta box
777
-     *
778
-     * @access public
779
-     * @return void
780
-     */
781
-    public function txn_details_meta_box()
782
-    {
783
-
784
-        $this->_set_transaction_object();
785
-        $this->_template_args['TXN_ID']   = $this->_transaction->ID();
786
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->attendee() : null;
787
-
788
-        //get line table
789
-        EEH_Autoloader::register_line_item_display_autoloaders();
790
-        $Line_Item_Display                       = new EE_Line_Item_Display('admin_table',
791
-            'EE_Admin_Table_Line_Item_Display_Strategy');
792
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item($this->_transaction->total_line_item());
793
-        $this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')->get('REG_code');
794
-
795
-        // process taxes
796
-        $taxes                         = $this->_transaction->get_many_related('Line_Item',
797
-            array(array('LIN_type' => EEM_Line_Item::type_tax)));
798
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
799
-
800
-        $this->_template_args['grand_total']     = EEH_Template::format_currency($this->_transaction->get('TXN_total'),
801
-            false, false);
802
-        $this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
803
-        $this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
30
+	/**
31
+	 * @var EE_Transaction
32
+	 */
33
+	private $_transaction;
34
+
35
+	/**
36
+	 * @var EE_Session
37
+	 */
38
+	private $_session;
39
+
40
+	/**
41
+	 * @var array $_txn_status
42
+	 */
43
+	private static $_txn_status;
44
+
45
+	/**
46
+	 * @var array $_pay_status
47
+	 */
48
+	private static $_pay_status;
49
+
50
+	/**
51
+	 * @var array $_existing_reg_payment_REG_IDs
52
+	 */
53
+	protected $_existing_reg_payment_REG_IDs = null;
54
+
55
+
56
+	/**
57
+	 * @Constructor
58
+	 * @access public
59
+	 *
60
+	 * @param bool $routing
61
+	 *
62
+	 * @return Transactions_Admin_Page
63
+	 */
64
+	public function __construct($routing = true)
65
+	{
66
+		parent::__construct($routing);
67
+	}
68
+
69
+
70
+	/**
71
+	 *    _init_page_props
72
+	 * @return void
73
+	 */
74
+	protected function _init_page_props()
75
+	{
76
+		$this->page_slug        = TXN_PG_SLUG;
77
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
78
+		$this->_admin_base_url  = TXN_ADMIN_URL;
79
+		$this->_admin_base_path = TXN_ADMIN;
80
+	}
81
+
82
+
83
+	/**
84
+	 *    _ajax_hooks
85
+	 * @return void
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
90
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
91
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
92
+	}
93
+
94
+
95
+	/**
96
+	 *    _define_page_props
97
+	 * @return void
98
+	 */
99
+	protected function _define_page_props()
100
+	{
101
+		$this->_admin_page_title = $this->page_label;
102
+		$this->_labels           = array(
103
+			'buttons' => array(
104
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
105
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
106
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
107
+			)
108
+		);
109
+	}
110
+
111
+
112
+	/**
113
+	 *        grab url requests and route them
114
+	 * @access private
115
+	 * @return void
116
+	 */
117
+	public function _set_page_routes()
118
+	{
119
+
120
+		$this->_set_transaction_status_array();
121
+
122
+		$txn_id = ! empty($this->_req_data['TXN_ID']) && ! is_array($this->_req_data['TXN_ID']) ? $this->_req_data['TXN_ID'] : 0;
123
+
124
+		$this->_page_routes = array(
125
+
126
+			'default' => array(
127
+				'func'       => '_transactions_overview_list_table',
128
+				'capability' => 'ee_read_transactions'
129
+			),
130
+
131
+			'view_transaction' => array(
132
+				'func'       => '_transaction_details',
133
+				'capability' => 'ee_read_transaction',
134
+				'obj_id'     => $txn_id
135
+			),
136
+
137
+			'send_payment_reminder' => array(
138
+				'func'       => '_send_payment_reminder',
139
+				'noheader'   => true,
140
+				'capability' => 'ee_send_message'
141
+			),
142
+
143
+			'espresso_apply_payment' => array(
144
+				'func'       => 'apply_payments_or_refunds',
145
+				'noheader'   => true,
146
+				'capability' => 'ee_edit_payments'
147
+			),
148
+
149
+			'espresso_apply_refund' => array(
150
+				'func'       => 'apply_payments_or_refunds',
151
+				'noheader'   => true,
152
+				'capability' => 'ee_edit_payments'
153
+			),
154
+
155
+			'espresso_delete_payment' => array(
156
+				'func'       => 'delete_payment',
157
+				'noheader'   => true,
158
+				'capability' => 'ee_delete_payments'
159
+			),
160
+
161
+		);
162
+
163
+	}
164
+
165
+
166
+	protected function _set_page_config()
167
+	{
168
+		$this->_page_config = array(
169
+			'default'          => array(
170
+				'nav'           => array(
171
+					'label' => esc_html__('Overview', 'event_espresso'),
172
+					'order' => 10
173
+				),
174
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
175
+				'help_tabs'     => array(
176
+					'transactions_overview_help_tab'                       => array(
177
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
178
+						'filename' => 'transactions_overview'
179
+					),
180
+					'transactions_overview_table_column_headings_help_tab' => array(
181
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
182
+						'filename' => 'transactions_overview_table_column_headings'
183
+					),
184
+					'transactions_overview_views_filters_help_tab'         => array(
185
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
186
+						'filename' => 'transactions_overview_views_filters_search'
187
+					),
188
+				),
189
+				'help_tour'     => array('Transactions_Overview_Help_Tour'),
190
+				/**
191
+				 * commented out because currently we are not displaying tips for transaction list table status but this
192
+				 * may change in a later iteration so want to keep the code for then.
193
+				 */
194
+				//'qtips' => array( 'Transactions_List_Table_Tips' ),
195
+				'require_nonce' => false
196
+			),
197
+			'view_transaction' => array(
198
+				'nav'       => array(
199
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
200
+					'order'      => 5,
201
+					'url'        => isset($this->_req_data['TXN_ID']) ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']),
202
+						$this->_current_page_view_url) : $this->_admin_base_url,
203
+					'persistent' => false
204
+				),
205
+				'help_tabs' => array(
206
+					'transactions_view_transaction_help_tab'                                              => array(
207
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
208
+						'filename' => 'transactions_view_transaction'
209
+					),
210
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
211
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
212
+						'filename' => 'transactions_view_transaction_transaction_details_table'
213
+					),
214
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
215
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
216
+						'filename' => 'transactions_view_transaction_attendees_registered'
217
+					),
218
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
219
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
220
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information'
221
+					),
222
+				),
223
+				'qtips'     => array('Transaction_Details_Tips'),
224
+				'help_tour' => array('Transaction_Details_Help_Tour'),
225
+				'metaboxes' => array('_transaction_details_metaboxes'),
226
+
227
+				'require_nonce' => false
228
+			)
229
+		);
230
+	}
231
+
232
+
233
+	/**
234
+	 * The below methods aren't used by this class currently
235
+	 */
236
+	protected function _add_screen_options()
237
+	{
238
+	}
239
+
240
+	protected function _add_feature_pointers()
241
+	{
242
+	}
243
+
244
+	public function admin_init()
245
+	{
246
+		// IF a registration was JUST added via the admin...
247
+		if (
248
+		isset(
249
+			$this->_req_data['redirect_from'],
250
+			$this->_req_data['EVT_ID'],
251
+			$this->_req_data['event_name']
252
+		)
253
+		) {
254
+			// then set a cookie so that we can block any attempts to use
255
+			// the back button as a way to enter another registration.
256
+			setcookie('ee_registration_added', $this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/');
257
+			// and update the global
258
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
259
+		}
260
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__('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.',
261
+			'event_espresso');
262
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__('An error occurred! Please refresh the page and try again.',
263
+			'event_espresso');
264
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
265
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
266
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
267
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__('This transaction has been overpaid ! Payments Total',
268
+			'event_espresso');
269
+	}
270
+
271
+	public function admin_notices()
272
+	{
273
+	}
274
+
275
+	public function admin_footer_scripts()
276
+	{
277
+	}
278
+
279
+
280
+	/**
281
+	 * _set_transaction_status_array
282
+	 * sets list of transaction statuses
283
+	 *
284
+	 * @access private
285
+	 * @return void
286
+	 */
287
+	private function _set_transaction_status_array()
288
+	{
289
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
290
+	}
291
+
292
+
293
+	/**
294
+	 * get_transaction_status_array
295
+	 * return the transaction status array for wp_list_table
296
+	 *
297
+	 * @access public
298
+	 * @return array
299
+	 */
300
+	public function get_transaction_status_array()
301
+	{
302
+		return self::$_txn_status;
303
+	}
304
+
305
+
306
+	/**
307
+	 *    get list of payment statuses
308
+	 *
309
+	 * @access private
310
+	 * @return void
311
+	 */
312
+	private function _get_payment_status_array()
313
+	{
314
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
315
+		$this->_template_args['payment_status'] = self::$_pay_status;
316
+
317
+	}
318
+
319
+
320
+	/**
321
+	 *    _add_screen_options_default
322
+	 *
323
+	 * @access protected
324
+	 * @return void
325
+	 */
326
+	protected function _add_screen_options_default()
327
+	{
328
+		$this->_per_page_screen_option();
329
+	}
330
+
331
+
332
+	/**
333
+	 * load_scripts_styles
334
+	 *
335
+	 * @access public
336
+	 * @return void
337
+	 */
338
+	public function load_scripts_styles()
339
+	{
340
+		//enqueue style
341
+		wp_register_style('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.css', array(),
342
+			EVENT_ESPRESSO_VERSION);
343
+		wp_enqueue_style('espresso_txn');
344
+		//scripts
345
+		wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
346
+			'ee_admin_js',
347
+			'ee-datepicker',
348
+			'jquery-ui-datepicker',
349
+			'jquery-ui-draggable',
350
+			'ee-dialog',
351
+			'ee-accounting',
352
+			'ee-serialize-full-array'
353
+		), EVENT_ESPRESSO_VERSION, true);
354
+		wp_enqueue_script('espresso_txn');
355
+
356
+	}
357
+
358
+
359
+	/**
360
+	 *    load_scripts_styles_view_transaction
361
+	 *
362
+	 * @access public
363
+	 * @return void
364
+	 */
365
+	public function load_scripts_styles_view_transaction()
366
+	{
367
+		//styles
368
+		wp_enqueue_style('espresso-ui-theme');
369
+	}
370
+
371
+
372
+	/**
373
+	 *    load_scripts_styles_default
374
+	 *
375
+	 * @access public
376
+	 * @return void
377
+	 */
378
+	public function load_scripts_styles_default()
379
+	{
380
+		//styles
381
+		wp_enqueue_style('espresso-ui-theme');
382
+	}
383
+
384
+
385
+	/**
386
+	 *    _set_list_table_views_default
387
+	 *
388
+	 * @access protected
389
+	 * @return void
390
+	 */
391
+	protected function _set_list_table_views_default()
392
+	{
393
+		$this->_views = array(
394
+			'all'       => array(
395
+				'slug'  => 'all',
396
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
397
+				'count' => 0
398
+			),
399
+			'abandoned' => array(
400
+				'slug'  => 'abandoned',
401
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
402
+				'count' => 0
403
+			),
404
+			'failed'    => array(
405
+				'slug'  => 'failed',
406
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
407
+				'count' => 0
408
+			)
409
+		);
410
+	}
411
+
412
+
413
+	/**
414
+	 * _set_transaction_object
415
+	 * This sets the _transaction property for the transaction details screen
416
+	 *
417
+	 * @access private
418
+	 * @return void
419
+	 */
420
+	private function _set_transaction_object()
421
+	{
422
+		if (is_object($this->_transaction)) {
423
+			return;
424
+		} //get out we've already set the object
425
+
426
+		$TXN = EEM_Transaction::instance();
427
+
428
+		$TXN_ID = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
429
+
430
+		//get transaction object
431
+		$this->_transaction = $TXN->get_one_by_ID($TXN_ID);
432
+		$this->_session     = ! empty($this->_transaction) ? $this->_transaction->get('TXN_session_data') : null;
433
+		$this->_transaction->verify_abandoned_transaction_status();
434
+
435
+		if (empty($this->_transaction)) {
436
+			$error_msg = esc_html__('An error occurred and the details for Transaction ID #',
437
+					'event_espresso') . $TXN_ID . esc_html__(' could not be retrieved.', 'event_espresso');
438
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
439
+		}
440
+	}
441
+
442
+
443
+	/**
444
+	 *    _transaction_legend_items
445
+	 *
446
+	 * @access protected
447
+	 * @return array
448
+	 */
449
+	protected function _transaction_legend_items()
450
+	{
451
+		EE_Registry::instance()->load_helper('MSG_Template');
452
+		$items = array();
453
+
454
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
455
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
456
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
457
+				$items['view_related_messages'] = array(
458
+					'class' => $related_for_icon['css_class'],
459
+					'desc'  => $related_for_icon['label'],
460
+				);
461
+			}
462
+		}
463
+
464
+		$items = apply_filters(
465
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
466
+			array_merge($items,
467
+				array(
468
+					'view_details'      => array(
469
+						'class' => 'dashicons dashicons-cart',
470
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso')
471
+					),
472
+					'view_invoice'      => array(
473
+						'class' => 'dashicons dashicons-media-spreadsheet',
474
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso')
475
+					),
476
+					'view_receipt'      => array(
477
+						'class' => 'dashicons dashicons-media-default',
478
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso')
479
+					),
480
+					'view_registration' => array(
481
+						'class' => 'dashicons dashicons-clipboard',
482
+						'desc'  => esc_html__('View Registration Details', 'event_espresso')
483
+					),
484
+					'payment_overview_link' => array(
485
+						'class' => 'dashicons dashicons-money',
486
+						'desc' => esc_html__('Make Payment on Frontend', 'event_espresso')
487
+					)
488
+				)
489
+			)
490
+		);
491
+
492
+		if (EE_Registry::instance()->CAP->current_user_can('ee_send_message',
493
+			'espresso_transactions_send_payment_reminder')
494
+		) {
495
+			if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
496
+				$items['send_payment_reminder'] = array(
497
+					'class' => 'dashicons dashicons-email-alt',
498
+					'desc'  => esc_html__('Send Payment Reminder', 'event_espresso')
499
+				);
500
+			} else {
501
+				$items['blank*'] = array(
502
+					'class' => '',
503
+					'desc'  => ''
504
+				);
505
+			}
506
+		} else {
507
+			$items['blank*'] = array(
508
+				'class' => '',
509
+				'desc'  => ''
510
+			);
511
+		}
512
+		$more_items = apply_filters(
513
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
514
+			array(
515
+				'overpaid'   => array(
516
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
517
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::overpaid_status_code, false, 'sentence')
518
+				),
519
+				'complete'   => array(
520
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
521
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::complete_status_code, false, 'sentence')
522
+				),
523
+				'incomplete' => array(
524
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
525
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::incomplete_status_code, false, 'sentence')
526
+				),
527
+				'abandoned'  => array(
528
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
529
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::abandoned_status_code, false, 'sentence')
530
+				),
531
+				'failed'     => array(
532
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
533
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::failed_status_code, false, 'sentence')
534
+				)
535
+			)
536
+		);
537
+
538
+		return array_merge($items, $more_items);
539
+	}
540
+
541
+
542
+	/**
543
+	 *    _transactions_overview_list_table
544
+	 *
545
+	 * @access protected
546
+	 * @return void
547
+	 */
548
+	protected function _transactions_overview_list_table()
549
+	{
550
+		$this->_admin_page_title                   = esc_html__('Transactions', 'event_espresso');
551
+		$event                                     = isset($this->_req_data['EVT_ID']) ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']) : null;
552
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event ? sprintf(esc_html__('%sViewing Transactions for the Event: %s%s',
553
+			'event_espresso'), '<h3>',
554
+			'<a href="' . EE_Admin_Page::add_query_args_and_nonce(array('action' => 'edit', 'post' => $event->ID()),
555
+				EVENTS_ADMIN_URL) . '" title="' . esc_attr__('Click to Edit event',
556
+				'event_espresso') . '">' . $event->get('EVT_name') . '</a>', '</h3>') : '';
557
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
558
+		$this->display_admin_list_table_page_with_no_sidebar();
559
+	}
560
+
561
+
562
+	/**
563
+	 *    _transaction_details
564
+	 * generates HTML for the View Transaction Details Admin page
565
+	 *
566
+	 * @access protected
567
+	 * @return void
568
+	 */
569
+	protected function _transaction_details()
570
+	{
571
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
572
+
573
+		$this->_set_transaction_status_array();
574
+
575
+		$this->_template_args                      = array();
576
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
577
+
578
+		$this->_set_transaction_object();
579
+
580
+		$primary_registration = $this->_transaction->primary_registration();
581
+		$attendee             = $primary_registration instanceof EE_Registration ? $primary_registration->attendee() : null;
582
+
583
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
584
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
585
+
586
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
587
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
588
+
589
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
590
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
591
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
592
+
593
+		$this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
594
+		$this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
595
+
596
+		if (
597
+			$attendee instanceof EE_Attendee
598
+			&& EE_Registry::instance()->CAP->current_user_can(
599
+				'ee_send_message',
600
+				'espresso_transactions_send_payment_reminder'
601
+			)
602
+		) {
603
+			$this->_template_args['send_payment_reminder_button'] =
604
+				EEH_MSG_Template::is_mt_active('payment_reminder')
605
+				&& $this->_transaction->get('STS_ID') != EEM_Transaction::complete_status_code
606
+				&& $this->_transaction->get('STS_ID') != EEM_Transaction::overpaid_status_code
607
+					? EEH_Template::get_button_or_link(
608
+					EE_Admin_Page::add_query_args_and_nonce(
609
+						array(
610
+							'action'      => 'send_payment_reminder',
611
+							'TXN_ID'      => $this->_transaction->ID(),
612
+							'redirect_to' => 'view_transaction'
613
+						),
614
+						TXN_ADMIN_URL
615
+					),
616
+					__(' Send Payment Reminder', 'event_espresso'),
617
+					'button secondary-button right',
618
+					'dashicons dashicons-email-alt'
619
+				)
620
+					: '';
621
+		} else {
622
+			$this->_template_args['send_payment_reminder_button'] = '';
623
+		}
624
+
625
+		$amount_due                         = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
626
+		$this->_template_args['amount_due'] = EEH_Template::format_currency($amount_due, true);
627
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
628
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign . $this->_template_args['amount_due'];
629
+		} else {
630
+			$this->_template_args['amount_due'] = $this->_template_args['amount_due'] . EE_Registry::instance()->CFG->currency->sign;
631
+		}
632
+		$this->_template_args['amount_due_class'] = '';
633
+
634
+		if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
635
+			// paid in full
636
+			$this->_template_args['amount_due'] = false;
637
+		} elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
638
+			// overpaid
639
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
640
+		} elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') > 0)) {
641
+			// monies owing
642
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
643
+		} elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') == 0)) {
644
+			// no payments made yet
645
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
646
+		} elseif ($this->_transaction->get('TXN_total') == 0) {
647
+			// free event
648
+			$this->_template_args['amount_due'] = false;
649
+		}
650
+
651
+		$payment_method = $this->_transaction->payment_method();
652
+
653
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
654
+			? $payment_method->admin_name()
655
+			: esc_html__('Unknown', 'event_espresso');
656
+
657
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
658
+		// link back to overview
659
+		$this->_template_args['txn_overview_url'] = ! empty ($_SERVER['HTTP_REFERER'])
660
+			? $_SERVER['HTTP_REFERER']
661
+			: TXN_ADMIN_URL;
662
+
663
+
664
+		// next link
665
+		$next_txn                                 = $this->_transaction->next(
666
+			null,
667
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
668
+			'TXN_ID'
669
+		);
670
+		$this->_template_args['next_transaction'] = $next_txn
671
+			? $this->_next_link(
672
+				EE_Admin_Page::add_query_args_and_nonce(
673
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
674
+					TXN_ADMIN_URL
675
+				),
676
+				'dashicons dashicons-arrow-right ee-icon-size-22'
677
+			)
678
+			: '';
679
+		// previous link
680
+		$previous_txn                                 = $this->_transaction->previous(
681
+			null,
682
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
683
+			'TXN_ID'
684
+		);
685
+		$this->_template_args['previous_transaction'] = $previous_txn
686
+			? $this->_previous_link(
687
+				EE_Admin_Page::add_query_args_and_nonce(
688
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
689
+					TXN_ADMIN_URL
690
+				),
691
+				'dashicons dashicons-arrow-left ee-icon-size-22'
692
+			)
693
+			: '';
694
+
695
+		// were we just redirected here after adding a new registration ???
696
+		if (
697
+		isset(
698
+			$this->_req_data['redirect_from'],
699
+			$this->_req_data['EVT_ID'],
700
+			$this->_req_data['event_name']
701
+		)
702
+		) {
703
+			if (
704
+			EE_Registry::instance()->CAP->current_user_can(
705
+				'ee_edit_registrations',
706
+				'espresso_registrations_new_registration',
707
+				$this->_req_data['EVT_ID']
708
+			)
709
+			) {
710
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
711
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
712
+					array(
713
+						'page'     => 'espresso_registrations',
714
+						'action'   => 'new_registration',
715
+						'return'   => 'default',
716
+						'TXN_ID'   => $this->_transaction->ID(),
717
+						'event_id' => $this->_req_data['EVT_ID'],
718
+					),
719
+					REG_ADMIN_URL
720
+				);
721
+				$this->_admin_page_title .= '">';
722
+
723
+				$this->_admin_page_title .= sprintf(
724
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
725
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
726
+				);
727
+				$this->_admin_page_title .= '</a>';
728
+			}
729
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
730
+		}
731
+		// grab messages at the last second
732
+		$this->_template_args['notices'] = EE_Error::get_notices();
733
+		// path to template
734
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
735
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template($template_path,
736
+			$this->_template_args, true);
737
+
738
+		// the details template wrapper
739
+		$this->display_admin_page_with_sidebar();
740
+
741
+	}
742
+
743
+
744
+	/**
745
+	 *        _transaction_details_metaboxes
746
+	 *
747
+	 * @access protected
748
+	 * @return void
749
+	 */
750
+	protected function _transaction_details_metaboxes()
751
+	{
752
+
753
+		$this->_set_transaction_object();
754
+
755
+		add_meta_box('edit-txn-details-mbox', esc_html__('Transaction Details', 'event_espresso'),
756
+			array($this, 'txn_details_meta_box'), $this->_wp_page_slug, 'normal', 'high');
757
+		add_meta_box(
758
+			'edit-txn-attendees-mbox',
759
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
760
+			array($this, 'txn_attendees_meta_box'),
761
+			$this->_wp_page_slug,
762
+			'normal',
763
+			'high',
764
+			array('TXN_ID' => $this->_transaction->ID())
765
+		);
766
+		add_meta_box('edit-txn-registrant-mbox', esc_html__('Primary Contact', 'event_espresso'),
767
+			array($this, 'txn_registrant_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
768
+		add_meta_box('edit-txn-billing-info-mbox', esc_html__('Billing Information', 'event_espresso'),
769
+			array($this, 'txn_billing_info_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
770
+
771
+	}
772
+
773
+
774
+	/**
775
+	 * txn_details_meta_box
776
+	 * generates HTML for the Transaction main meta box
777
+	 *
778
+	 * @access public
779
+	 * @return void
780
+	 */
781
+	public function txn_details_meta_box()
782
+	{
783
+
784
+		$this->_set_transaction_object();
785
+		$this->_template_args['TXN_ID']   = $this->_transaction->ID();
786
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->attendee() : null;
787
+
788
+		//get line table
789
+		EEH_Autoloader::register_line_item_display_autoloaders();
790
+		$Line_Item_Display                       = new EE_Line_Item_Display('admin_table',
791
+			'EE_Admin_Table_Line_Item_Display_Strategy');
792
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item($this->_transaction->total_line_item());
793
+		$this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')->get('REG_code');
794
+
795
+		// process taxes
796
+		$taxes                         = $this->_transaction->get_many_related('Line_Item',
797
+			array(array('LIN_type' => EEM_Line_Item::type_tax)));
798
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
799
+
800
+		$this->_template_args['grand_total']     = EEH_Template::format_currency($this->_transaction->get('TXN_total'),
801
+			false, false);
802
+		$this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
803
+		$this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
804 804
 
805 805
 //		$txn_status_class = 'status-' . $this->_transaction->get('STS_ID');
806 806
 
807
-        // process payment details
808
-        $payments = $this->_transaction->get_many_related('Payment');
809
-        if ( ! empty($payments)) {
810
-            $this->_template_args['payments']              = $payments;
811
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
812
-        } else {
813
-            $this->_template_args['payments']              = false;
814
-            $this->_template_args['existing_reg_payments'] = array();
815
-        }
816
-
817
-        $this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
818
-        $this->_template_args['delete_payment_url'] = add_query_arg(array('action' => 'espresso_delete_payment'),
819
-            TXN_ADMIN_URL);
820
-
821
-        if (isset($txn_details['invoice_number'])) {
822
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
823
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__('Invoice Number',
824
-                'event_espresso');
825
-        }
826
-
827
-        $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction->get_first_related('Registration')->get('REG_session');
828
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__('Registration Session',
829
-            'event_espresso');
830
-
831
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '';
832
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__('Transaction placed from IP',
833
-            'event_espresso');
834
-
835
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '';
836
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__('Registrant User Agent',
837
-            'event_espresso');
838
-
839
-        $reg_steps = '<ul>';
840
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
841
-            if ($reg_step_status === true) {
842
-                $reg_steps .= '<li style="color:#70cc50">' . sprintf(esc_html__('%1$s : Completed', 'event_espresso'),
843
-                        ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
844
-            } else if (is_numeric($reg_step_status) && $reg_step_status !== false) {
845
-                $reg_steps .= '<li style="color:#2EA2CC">' . sprintf(
846
-                        esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
847
-                        ucwords(str_replace('_', ' ', $reg_step)),
848
-                        date(get_option('date_format') . ' ' . get_option('time_format'),
849
-                            ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)))
850
-                    ) . '</li>';
851
-            } else {
852
-                $reg_steps .= '<li style="color:#E76700">' . sprintf(esc_html__('%1$s : Never Initiated',
853
-                        'event_espresso'), ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
854
-            }
855
-        }
856
-        $reg_steps .= '</ul>';
857
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
858
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__('Registration Step Progress',
859
-            'event_espresso');
860
-
861
-
862
-        $this->_get_registrations_to_apply_payment_to();
863
-        $this->_get_payment_methods($payments);
864
-        $this->_get_payment_status_array();
865
-        $this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
866
-
867
-        $this->_template_args['transaction_form_url']    = add_query_arg(array(
868
-            'action'  => 'edit_transaction',
869
-            'process' => 'transaction'
870
-        ), TXN_ADMIN_URL);
871
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(array(
872
-            'page'   => 'espresso_transactions',
873
-            'action' => 'espresso_apply_payment'
874
-        ), WP_AJAX_URL);
875
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(array(
876
-            'page'   => 'espresso_transactions',
877
-            'action' => 'espresso_delete_payment'
878
-        ), WP_AJAX_URL);
879
-
880
-        // 'espresso_delete_payment_nonce'
881
-
882
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
883
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
884
-
885
-    }
886
-
887
-
888
-    /**
889
-     * _get_registration_payment_IDs
890
-     *
891
-     *    generates an array of Payment IDs and their corresponding Registration IDs
892
-     *
893
-     * @access protected
894
-     *
895
-     * @param EE_Payment[] $payments
896
-     *
897
-     * @return array
898
-     */
899
-    protected function _get_registration_payment_IDs($payments = array())
900
-    {
901
-        $existing_reg_payments = array();
902
-        // get all reg payments for these payments
903
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(array(
904
-            array(
905
-                'PAY_ID' => array(
906
-                    'IN',
907
-                    array_keys($payments)
908
-                )
909
-            )
910
-        ));
911
-        if ( ! empty($reg_payments)) {
912
-            foreach ($payments as $payment) {
913
-                if ( ! $payment instanceof EE_Payment) {
914
-                    continue;
915
-                } else if ( ! isset($existing_reg_payments[$payment->ID()])) {
916
-                    $existing_reg_payments[$payment->ID()] = array();
917
-                }
918
-                foreach ($reg_payments as $reg_payment) {
919
-                    if ($reg_payment instanceof EE_Registration_Payment && $reg_payment->payment_ID() === $payment->ID()) {
920
-                        $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
921
-                    }
922
-                }
923
-            }
924
-        }
925
-
926
-        return $existing_reg_payments;
927
-    }
928
-
929
-
930
-    /**
931
-     * _get_registrations_to_apply_payment_to
932
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
933
-     * which allows the admin to only apply the payment to the specific registrations
934
-     *
935
-     * @access protected
936
-     * @return void
937
-     * @throws \EE_Error
938
-     */
939
-    protected function _get_registrations_to_apply_payment_to()
940
-    {
941
-        // we want any registration with an active status (ie: not deleted or cancelled)
942
-        $query_params                      = array(
943
-            array(
944
-                'STS_ID' => array(
945
-                    'IN',
946
-                    array(
947
-                        EEM_Registration::status_id_approved,
948
-                        EEM_Registration::status_id_pending_payment,
949
-                        EEM_Registration::status_id_not_approved,
950
-                    )
951
-                )
952
-            )
953
-        );
954
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
955
-                '', 'txn-admin-apply-payment-to-registrations-dv', '', 'clear: both; margin: 1.5em 0 0; display: none;'
956
-            );
957
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
958
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
959
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
960
-            EEH_HTML::tr(
961
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
962
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
963
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
964
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
965
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
966
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
967
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
968
-            )
969
-        );
970
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
971
-        // get registrations for TXN
972
-        $registrations = $this->_transaction->registrations($query_params);
973
-        foreach ($registrations as $registration) {
974
-            if ($registration instanceof EE_Registration) {
975
-                $attendee_name = $registration->attendee() instanceof EE_Attendee
976
-                    ? $registration->attendee()->full_name()
977
-                    : esc_html__('Unknown Attendee', 'event_espresso');
978
-                $owing         = $registration->final_price() - $registration->paid();
979
-                $taxable       = $registration->ticket()->taxable()
980
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
981
-                    : '';
982
-                $checked       = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
983
-                    ? ' checked="checked"'
984
-                    : '';
985
-                $disabled      = $registration->final_price() > 0 ? '' : ' disabled';
986
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
987
-                    EEH_HTML::td($registration->ID()) .
988
-                    EEH_HTML::td($attendee_name) .
989
-                    EEH_HTML::td(
990
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
991
-                    ) .
992
-                    EEH_HTML::td($registration->event_name()) .
993
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
994
-                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
995
-                    EEH_HTML::td(
996
-                        '<input type="checkbox" value="' . $registration->ID()
997
-                        . '" name="txn_admin_payment[registrations]"'
998
-                        . $checked . $disabled . '>',
999
-                        '', 'jst-cntr'
1000
-                    ),
1001
-                    'apply-payment-registration-row-' . $registration->ID()
1002
-                );
1003
-            }
1004
-        }
1005
-        $registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1006
-        $registrations_to_apply_payment_to .= EEH_HTML::tablex();
1007
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1008
-        $registrations_to_apply_payment_to .= EEH_HTML::p(
1009
-            esc_html__(
1010
-                '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.',
1011
-                'event_espresso'
1012
-            ),
1013
-            '', 'clear description'
1014
-        );
1015
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1016
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1017
-    }
1018
-
1019
-
1020
-    /**
1021
-     * _get_reg_status_selection
1022
-     *
1023
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1024
-     *         instead of events.
1025
-     * @access protected
1026
-     * @return void
1027
-     */
1028
-    protected function _get_reg_status_selection()
1029
-    {
1030
-        //first get all possible statuses
1031
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1032
-        //let's add a "don't change" option.
1033
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1034
-        $status_array                                        = array_merge($status_array, $statuses);
1035
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input('txn_reg_status_change[reg_status]',
1036
-            $status_array, 'NAN', 'id="txn-admin-payment-reg-status-inp"', 'txn-reg-status-change-reg-status');
1037
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input('delete_txn_reg_status_change[reg_status]',
1038
-            $status_array, 'NAN', 'delete-txn-admin-payment-reg-status-inp', 'delete-txn-reg-status-change-reg-status');
1039
-
1040
-    }
1041
-
1042
-
1043
-    /**
1044
-     *    _get_payment_methods
1045
-     * Gets all the payment methods available generally, or the ones that are already
1046
-     * selected on these payments (in case their payment methods are no longer active).
1047
-     * Has the side-effect of updating the template args' payment_methods item
1048
-     * @access private
1049
-     *
1050
-     * @param EE_Payment[] to show on this page
1051
-     *
1052
-     * @return void
1053
-     */
1054
-    private function _get_payment_methods($payments = array())
1055
-    {
1056
-        $payment_methods_of_payments = array();
1057
-        foreach ($payments as $payment) {
1058
-            if ($payment instanceof EE_Payment) {
1059
-                $payment_methods_of_payments[] = $payment->get('PMD_ID');
1060
-            }
1061
-        }
1062
-        if ($payment_methods_of_payments) {
1063
-            $query_args = array(
1064
-                array(
1065
-                    'OR*payment_method_for_payment' => array(
1066
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1067
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')
1068
-                    )
1069
-                )
1070
-            );
1071
-        } else {
1072
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1073
-        }
1074
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * txn_attendees_meta_box
1080
-     *    generates HTML for the Attendees Transaction main meta box
1081
-     *
1082
-     * @access public
1083
-     *
1084
-     * @param WP_Post $post
1085
-     * @param array   $metabox
1086
-     *
1087
-     * @return void
1088
-     */
1089
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1090
-    {
1091
-
1092
-        extract($metabox['args']);
1093
-        $this->_template_args['post']            = $post;
1094
-        $this->_template_args['event_attendees'] = array();
1095
-        // process items in cart
1096
-        $line_items = $this->_transaction->get_many_related('Line_Item', array(array('LIN_type' => 'line-item')));
1097
-        if ( ! empty($line_items)) {
1098
-            foreach ($line_items as $item) {
1099
-                if ($item instanceof EE_Line_Item) {
1100
-                    switch ($item->OBJ_type()) {
1101
-
1102
-                        case 'Event' :
1103
-                            break;
1104
-
1105
-                        case 'Ticket' :
1106
-                            $ticket = $item->ticket();
1107
-                            //right now we're only handling tickets here.  Cause its expected that only tickets will have attendees right?
1108
-                            if ( ! $ticket instanceof EE_Ticket) {
1109
-                                continue;
1110
-                            }
1111
-                            try {
1112
-                                $event_name = $ticket->get_event_name();
1113
-                            } catch (Exception $e) {
1114
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1115
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1116
-                            }
1117
-                            $event_name .= ' - ' . $item->get('LIN_name');
1118
-                            $ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1119
-                            // now get all of the registrations for this transaction that use this ticket
1120
-                            $registrations = $ticket->get_many_related('Registration',
1121
-                                array(array('TXN_ID' => $this->_transaction->ID())));
1122
-                            foreach ($registrations as $registration) {
1123
-                                if ( ! $registration instanceof EE_Registration) {
1124
-                                    continue;
1125
-                                }
1126
-                                $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']            = $registration->status_ID();
1127
-                                $this->_template_args['event_attendees'][$registration->ID()]['att_num']           = $registration->count();
1128
-                                $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name'] = $event_name;
1129
-                                $this->_template_args['event_attendees'][$registration->ID()]['ticket_price']      = $ticket_price;
1130
-                                // attendee info
1131
-                                $attendee = $registration->get_first_related('Attendee');
1132
-                                if ($attendee instanceof EE_Attendee) {
1133
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = $attendee->ID();
1134
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = $attendee->full_name();
1135
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name . esc_html__(' Event',
1136
-                                            'event_espresso') . '">' . $attendee->email() . '</a>';
1137
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = EEH_Address::format($attendee,
1138
-                                        'inline', false, false);
1139
-                                } else {
1140
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1141
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1142
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1143
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1144
-                                }
1145
-                            }
1146
-                            break;
1147
-
1148
-                    }
1149
-                }
1150
-            }
1151
-
1152
-            $this->_template_args['transaction_form_url'] = add_query_arg(array(
1153
-                'action'  => 'edit_transaction',
1154
-                'process' => 'attendees'
1155
-            ), TXN_ADMIN_URL);
1156
-            echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1157
-                $this->_template_args, true);
1158
-
1159
-        } else {
1160
-            echo sprintf(
1161
-                esc_html__('%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1162
-                    'event_espresso'),
1163
-                '<p class="important-notice">',
1164
-                '</p>'
1165
-            );
1166
-        }
1167
-    }
1168
-
1169
-
1170
-    /**
1171
-     * txn_registrant_side_meta_box
1172
-     * generates HTML for the Edit Transaction side meta box
1173
-     *
1174
-     * @access public
1175
-     * @throws \EE_Error
1176
-     * @return void
1177
-     */
1178
-    public function txn_registrant_side_meta_box()
1179
-    {
1180
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->get_first_related('Attendee') : null;
1181
-        if ( ! $primary_att instanceof EE_Attendee) {
1182
-            $this->_template_args['no_attendee_message'] = esc_html__('There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1183
-                'event_espresso');
1184
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1185
-        }
1186
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1187
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1188
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1189
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1190
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1191
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1192
-            'action' => 'edit_attendee',
1193
-            'post'   => $primary_att->ID()
1194
-        ), REG_ADMIN_URL);
1195
-        // get formatted address for registrant
1196
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1197
-        echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1198
-            $this->_template_args, true);
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * txn_billing_info_side_meta_box
1204
-     *    generates HTML for the Edit Transaction side meta box
1205
-     *
1206
-     * @access public
1207
-     * @return void
1208
-     */
1209
-    public function txn_billing_info_side_meta_box()
1210
-    {
1211
-
1212
-        $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1213
-        $this->_template_args['billing_form_url'] = add_query_arg(
1214
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1215
-            TXN_ADMIN_URL
1216
-        );
1217
-
1218
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1219
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1220
-    }
1221
-
1222
-
1223
-    /**
1224
-     * apply_payments_or_refunds
1225
-     *    registers a payment or refund made towards a transaction
1226
-     *
1227
-     * @access public
1228
-     * @return void
1229
-     */
1230
-    public function apply_payments_or_refunds()
1231
-    {
1232
-        $json_response_data = array('return_data' => false);
1233
-        $valid_data         = $this->_validate_payment_request_data();
1234
-        if ( ! empty($valid_data)) {
1235
-            $PAY_ID = $valid_data['PAY_ID'];
1236
-            //save  the new payment
1237
-            $payment = $this->_create_payment_from_request_data($valid_data);
1238
-            // get the TXN for this payment
1239
-            $transaction = $payment->transaction();
1240
-            // verify transaction
1241
-            if ($transaction instanceof EE_Transaction) {
1242
-                // calculate_total_payments_and_update_status
1243
-                $this->_process_transaction_payments($transaction);
1244
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1245
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1246
-                // apply payment to registrations (if applicable)
1247
-                if ( ! empty($REG_IDs)) {
1248
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1249
-                    $this->_maybe_send_notifications();
1250
-                    // now process status changes for the same registrations
1251
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1252
-                }
1253
-                $this->_maybe_send_notifications($payment);
1254
-                //prepare to render page
1255
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1256
-                do_action('AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording', $transaction,
1257
-                    $payment);
1258
-            } else {
1259
-                EE_Error::add_error(
1260
-                    esc_html__('A valid Transaction for this payment could not be retrieved.', 'event_espresso'),
1261
-                    __FILE__, __FUNCTION__, __LINE__
1262
-                );
1263
-            }
1264
-        } else {
1265
-            EE_Error::add_error(esc_html__('The payment form data could not be processed. Please try again.',
1266
-                'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1267
-        }
1268
-
1269
-        $notices              = EE_Error::get_notices(false, false, false);
1270
-        $this->_template_args = array(
1271
-            'data'    => $json_response_data,
1272
-            'error'   => $notices['errors'],
1273
-            'success' => $notices['success']
1274
-        );
1275
-        $this->_return_json();
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * _validate_payment_request_data
1281
-     *
1282
-     * @return array
1283
-     */
1284
-    protected function _validate_payment_request_data()
1285
-    {
1286
-        if ( ! isset($this->_req_data['txn_admin_payment'])) {
1287
-            return false;
1288
-        }
1289
-        $payment_form = $this->_generate_payment_form_section();
1290
-        try {
1291
-            if ($payment_form->was_submitted()) {
1292
-                $payment_form->receive_form_submission();
1293
-                if ( ! $payment_form->is_valid()) {
1294
-                    $submission_error_messages = array();
1295
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1296
-                        if ($validation_error instanceof EE_Validation_Error) {
1297
-                            $submission_error_messages[] = sprintf(
1298
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1299
-                                $validation_error->get_form_section()->html_label_text(),
1300
-                                $validation_error->getMessage()
1301
-                            );
1302
-                        }
1303
-                    }
1304
-                    EE_Error::add_error(join('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1305
-
1306
-                    return array();
1307
-                }
1308
-            }
1309
-        } catch (EE_Error $e) {
1310
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1311
-
1312
-            return array();
1313
-        }
1314
-
1315
-        return $payment_form->valid_data();
1316
-    }
1317
-
1318
-
1319
-    /**
1320
-     * _generate_payment_form_section
1321
-     *
1322
-     * @return EE_Form_Section_Proper
1323
-     */
1324
-    protected function _generate_payment_form_section()
1325
-    {
1326
-        return new EE_Form_Section_Proper(
1327
-            array(
1328
-                'name'        => 'txn_admin_payment',
1329
-                'subsections' => array(
1330
-                    'PAY_ID'          => new EE_Text_Input(
1331
-                        array(
1332
-                            'default'               => 0,
1333
-                            'required'              => false,
1334
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1335
-                            'validation_strategies' => array(new EE_Int_Normalization())
1336
-                        )
1337
-                    ),
1338
-                    'TXN_ID'          => new EE_Text_Input(
1339
-                        array(
1340
-                            'default'               => 0,
1341
-                            'required'              => true,
1342
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1343
-                            'validation_strategies' => array(new EE_Int_Normalization())
1344
-                        )
1345
-                    ),
1346
-                    'type'            => new EE_Text_Input(
1347
-                        array(
1348
-                            'default'               => 1,
1349
-                            'required'              => true,
1350
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1351
-                            'validation_strategies' => array(new EE_Int_Normalization())
1352
-                        )
1353
-                    ),
1354
-                    'amount'          => new EE_Text_Input(
1355
-                        array(
1356
-                            'default'               => 0,
1357
-                            'required'              => true,
1358
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1359
-                            'validation_strategies' => array(new EE_Float_Normalization())
1360
-                        )
1361
-                    ),
1362
-                    'status'          => new EE_Text_Input(
1363
-                        array(
1364
-                            'default'         => EEM_Payment::status_id_approved,
1365
-                            'required'        => true,
1366
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1367
-                        )
1368
-                    ),
1369
-                    'PMD_ID'          => new EE_Text_Input(
1370
-                        array(
1371
-                            'default'               => 2,
1372
-                            'required'              => true,
1373
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1374
-                            'validation_strategies' => array(new EE_Int_Normalization())
1375
-                        )
1376
-                    ),
1377
-                    'date'            => new EE_Text_Input(
1378
-                        array(
1379
-                            'default'         => time(),
1380
-                            'required'        => true,
1381
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1382
-                        )
1383
-                    ),
1384
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1385
-                        array(
1386
-                            'default'               => '',
1387
-                            'required'              => false,
1388
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1389
-                            'validation_strategies' => array(
1390
-                                new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1391
-                                    100),
1392
-                            )
1393
-                        )
1394
-                    ),
1395
-                    'po_number'       => new EE_Text_Input(
1396
-                        array(
1397
-                            'default'               => '',
1398
-                            'required'              => false,
1399
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1400
-                            'validation_strategies' => array(
1401
-                                new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1402
-                                    100),
1403
-                            )
1404
-                        )
1405
-                    ),
1406
-                    'accounting'      => new EE_Text_Input(
1407
-                        array(
1408
-                            'default'               => '',
1409
-                            'required'              => false,
1410
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1411
-                            'validation_strategies' => array(
1412
-                                new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1413
-                                    100),
1414
-                            )
1415
-                        )
1416
-                    ),
1417
-                )
1418
-            )
1419
-        );
1420
-    }
1421
-
1422
-
1423
-    /**
1424
-     * _create_payment_from_request_data
1425
-     *
1426
-     * @param array $valid_data
1427
-     *
1428
-     * @return EE_Payment
1429
-     */
1430
-    protected function _create_payment_from_request_data($valid_data)
1431
-    {
1432
-        $PAY_ID = $valid_data['PAY_ID'];
1433
-        // get payment amount
1434
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1435
-        // payments have a type value of 1 and refunds have a type value of -1
1436
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1437
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1438
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1439
-        $date    = $valid_data['date'] ? preg_replace('/\s+/', ' ', $valid_data['date']) : date('Y-m-d g:i a',
1440
-            current_time('timestamp'));
1441
-        $payment = EE_Payment::new_instance(
1442
-            array(
1443
-                'TXN_ID'              => $valid_data['TXN_ID'],
1444
-                'STS_ID'              => $valid_data['status'],
1445
-                'PAY_timestamp'       => $date,
1446
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1447
-                'PMD_ID'              => $valid_data['PMD_ID'],
1448
-                'PAY_amount'          => $amount,
1449
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1450
-                'PAY_po_number'       => $valid_data['po_number'],
1451
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1452
-                'PAY_details'         => $valid_data,
1453
-                'PAY_ID'              => $PAY_ID
1454
-            ),
1455
-            '',
1456
-            array('Y-m-d', 'g:i a')
1457
-        );
1458
-
1459
-        if ( ! $payment->save()) {
1460
-            EE_Error::add_error(
1461
-                sprintf(
1462
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1463
-                    $payment->ID()
1464
-                ),
1465
-                __FILE__, __FUNCTION__, __LINE__
1466
-            );
1467
-        }
1468
-
1469
-        return $payment;
1470
-    }
1471
-
1472
-
1473
-    /**
1474
-     * _process_transaction_payments
1475
-     *
1476
-     * @param \EE_Transaction $transaction
1477
-     *
1478
-     * @return array
1479
-     */
1480
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1481
-    {
1482
-        /** @type EE_Transaction_Payments $transaction_payments */
1483
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1484
-        //update the transaction with this payment
1485
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1486
-            EE_Error::add_success(esc_html__('The payment has been processed successfully.', 'event_espresso'),
1487
-                __FILE__, __FUNCTION__, __LINE__);
1488
-        } else {
1489
-            EE_Error::add_error(
1490
-                esc_html__('The payment was processed successfully but the amount paid for the transaction was not updated.',
1491
-                    'event_espresso')
1492
-                , __FILE__, __FUNCTION__, __LINE__
1493
-            );
1494
-        }
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * _get_REG_IDs_to_apply_payment_to
1500
-     *
1501
-     * returns a list of registration IDs that the payment will apply to
1502
-     *
1503
-     * @param \EE_Payment $payment
1504
-     *
1505
-     * @return array
1506
-     */
1507
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1508
-    {
1509
-        $REG_IDs = array();
1510
-        // grab array of IDs for specific registrations to apply changes to
1511
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1512
-            $REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1513
-        }
1514
-        //nothing specified ? then get all reg IDs
1515
-        if (empty($REG_IDs)) {
1516
-            $registrations = $payment->transaction()->registrations();
1517
-            $REG_IDs       = ! empty($registrations) ? array_keys($registrations) : $this->_get_existing_reg_payment_REG_IDs($payment);
1518
-        }
1519
-
1520
-        // ensure that REG_IDs are integers and NOT strings
1521
-        return array_map('intval', $REG_IDs);
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * @return array
1527
-     */
1528
-    public function existing_reg_payment_REG_IDs()
1529
-    {
1530
-        return $this->_existing_reg_payment_REG_IDs;
1531
-    }
1532
-
1533
-
1534
-    /**
1535
-     * @param array $existing_reg_payment_REG_IDs
1536
-     */
1537
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1538
-    {
1539
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1540
-    }
1541
-
1542
-
1543
-    /**
1544
-     * _get_existing_reg_payment_REG_IDs
1545
-     *
1546
-     * returns a list of registration IDs that the payment is currently related to
1547
-     * as recorded in the database
1548
-     *
1549
-     * @param \EE_Payment $payment
1550
-     *
1551
-     * @return array
1552
-     */
1553
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1554
-    {
1555
-        if ($this->existing_reg_payment_REG_IDs() === null) {
1556
-            // let's get any existing reg payment records for this payment
1557
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1558
-            // but we only want the REG IDs, so grab the array keys
1559
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs) ? array_keys($existing_reg_payment_REG_IDs) : array();
1560
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1561
-        }
1562
-
1563
-        return $this->existing_reg_payment_REG_IDs();
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * _remove_existing_registration_payments
1569
-     *
1570
-     * this calculates the difference between existing relations
1571
-     * to the supplied payment and the new list registration IDs,
1572
-     * removes any related registrations that no longer apply,
1573
-     * and then updates the registration paid fields
1574
-     *
1575
-     * @param \EE_Payment $payment
1576
-     * @param int         $PAY_ID
1577
-     *
1578
-     * @return bool;
1579
-     */
1580
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1581
-    {
1582
-        // newly created payments will have nothing recorded for $PAY_ID
1583
-        if ($PAY_ID == 0) {
1584
-            return false;
1585
-        }
1586
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1587
-        if (empty($existing_reg_payment_REG_IDs)) {
1588
-            return false;
1589
-        }
1590
-        /** @type EE_Transaction_Payments $transaction_payments */
1591
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1592
-
1593
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
1594
-            $payment,
1595
-            array(
1596
-                array(
1597
-                    'PAY_ID' => $payment->ID(),
1598
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1599
-                )
1600
-            )
1601
-        );
1602
-    }
1603
-
1604
-
1605
-    /**
1606
-     * _update_registration_payments
1607
-     *
1608
-     * this applies the payments to the selected registrations
1609
-     * but only if they have not already been paid for
1610
-     *
1611
-     * @param  EE_Transaction $transaction
1612
-     * @param \EE_Payment     $payment
1613
-     * @param array           $REG_IDs
1614
-     *
1615
-     * @return bool
1616
-     */
1617
-    protected function _update_registration_payments(
1618
-        EE_Transaction $transaction,
1619
-        EE_Payment $payment,
1620
-        $REG_IDs = array()
1621
-    ) {
1622
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
1623
-        // so let's do that using our set of REG_IDs from the form
1624
-        $registration_query_where_params = array(
1625
-            'REG_ID' => array('IN', $REG_IDs)
1626
-        );
1627
-        // but add in some conditions regarding payment,
1628
-        // so that we don't apply payments to registrations that are free or have already been paid for
1629
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
1630
-        if ( ! $payment->is_a_refund()) {
1631
-            $registration_query_where_params['REG_final_price']  = array('!=', 0);
1632
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
1633
-        }
1634
-        //EEH_Debug_Tools::printr( $registration_query_where_params, '$registration_query_where_params', __FILE__, __LINE__ );
1635
-        $registrations = $transaction->registrations(array($registration_query_where_params));
1636
-        if ( ! empty($registrations)) {
1637
-            /** @type EE_Payment_Processor $payment_processor */
1638
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
1639
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
1640
-        }
1641
-    }
1642
-
1643
-
1644
-    /**
1645
-     * _process_registration_status_change
1646
-     *
1647
-     * This processes requested registration status changes for all the registrations
1648
-     * on a given transaction and (optionally) sends out notifications for the changes.
1649
-     *
1650
-     * @param  EE_Transaction $transaction
1651
-     * @param array           $REG_IDs
1652
-     *
1653
-     * @return bool
1654
-     */
1655
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
1656
-    {
1657
-        // first if there is no change in status then we get out.
1658
-        if (
1659
-            ! isset($this->_req_data['txn_reg_status_change'], $this->_req_data['txn_reg_status_change']['reg_status'])
1660
-            || $this->_req_data['txn_reg_status_change']['reg_status'] == 'NAN'
1661
-        ) {
1662
-            //no error message, no change requested, just nothing to do man.
1663
-            return false;
1664
-        }
1665
-        /** @type EE_Transaction_Processor $transaction_processor */
1666
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1667
-
1668
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
1669
-        return $transaction_processor->manually_update_registration_statuses(
1670
-            $transaction,
1671
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
1672
-            array(array('REG_ID' => array('IN', $REG_IDs)))
1673
-        );
1674
-    }
1675
-
1676
-
1677
-    /**
1678
-     * _build_payment_json_response
1679
-     *
1680
-     * @access public
1681
-     *
1682
-     * @param \EE_Payment $payment
1683
-     * @param array       $REG_IDs
1684
-     * @param bool | null $delete_txn_reg_status_change
1685
-     *
1686
-     * @return array
1687
-     */
1688
-    protected function _build_payment_json_response(
1689
-        EE_Payment $payment,
1690
-        $REG_IDs = array(),
1691
-        $delete_txn_reg_status_change = null
1692
-    ) {
1693
-        // was the payment deleted ?
1694
-        if (is_bool($delete_txn_reg_status_change)) {
1695
-            return array(
1696
-                'PAY_ID'                       => $payment->ID(),
1697
-                'amount'                       => $payment->amount(),
1698
-                'total_paid'                   => $payment->transaction()->paid(),
1699
-                'txn_status'                   => $payment->transaction()->status_ID(),
1700
-                'pay_status'                   => $payment->STS_ID(),
1701
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
1702
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
1703
-            );
1704
-        } else {
1705
-            $this->_get_payment_status_array();
1706
-
1707
-            return array(
1708
-                'amount'           => $payment->amount(),
1709
-                'total_paid'       => $payment->transaction()->paid(),
1710
-                'txn_status'       => $payment->transaction()->status_ID(),
1711
-                'pay_status'       => $payment->STS_ID(),
1712
-                'PAY_ID'           => $payment->ID(),
1713
-                'STS_ID'           => $payment->STS_ID(),
1714
-                'status'           => self::$_pay_status[$payment->STS_ID()],
1715
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
1716
-                'method'           => strtoupper($payment->source()),
1717
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
1718
-                'gateway'          => $payment->payment_method() ? $payment->payment_method()->admin_name() : esc_html__("Unknown",
1719
-                    'event_espresso'),
1720
-                'gateway_response' => $payment->gateway_response(),
1721
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
1722
-                'po_number'        => $payment->po_number(),
1723
-                'extra_accntng'    => $payment->extra_accntng(),
1724
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
1725
-            );
1726
-        }
1727
-    }
1728
-
1729
-
1730
-    /**
1731
-     * delete_payment
1732
-     *    delete a payment or refund made towards a transaction
1733
-     *
1734
-     * @access public
1735
-     * @return void
1736
-     */
1737
-    public function delete_payment()
1738
-    {
1739
-        $json_response_data = array('return_data' => false);
1740
-        $PAY_ID             = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0;
1741
-        if ($PAY_ID) {
1742
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false;
1743
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
1744
-            if ($payment instanceof EE_Payment) {
1745
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1746
-                /** @type EE_Transaction_Payments $transaction_payments */
1747
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1748
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
1749
-                    $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs,
1750
-                        $delete_txn_reg_status_change);
1751
-                    if ($delete_txn_reg_status_change) {
1752
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
1753
-                        //MAKE sure we also add the delete_txn_req_status_change to the
1754
-                        //$_REQUEST global because that's how messages will be looking for it.
1755
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
1756
-                        $this->_maybe_send_notifications();
1757
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
1758
-                    }
1759
-                }
1760
-            } else {
1761
-                EE_Error::add_error(
1762
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
1763
-                    __FILE__, __FUNCTION__, __LINE__
1764
-                );
1765
-            }
1766
-        } else {
1767
-            EE_Error::add_error(
1768
-                esc_html__('A valid Payment ID was not received, therefore payment form data could not be loaded.',
1769
-                    'event_espresso'),
1770
-                __FILE__, __FUNCTION__, __LINE__
1771
-            );
1772
-        }
1773
-        $notices              = EE_Error::get_notices(false, false, false);
1774
-        $this->_template_args = array(
1775
-            'data'      => $json_response_data,
1776
-            'success'   => $notices['success'],
1777
-            'error'     => $notices['errors'],
1778
-            'attention' => $notices['attention']
1779
-        );
1780
-        $this->_return_json();
1781
-    }
1782
-
1783
-
1784
-    /**
1785
-     * _registration_payment_data_array
1786
-     * adds info for 'owing' and 'paid' for each registration to the json response
1787
-     *
1788
-     * @access protected
1789
-     *
1790
-     * @param array $REG_IDs
1791
-     *
1792
-     * @return array
1793
-     */
1794
-    protected function _registration_payment_data_array($REG_IDs)
1795
-    {
1796
-        $registration_payment_data = array();
1797
-        //if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
1798
-        if ( ! empty($REG_IDs)) {
1799
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
1800
-            foreach ($registrations as $registration) {
1801
-                if ($registration instanceof EE_Registration) {
1802
-                    $registration_payment_data[$registration->ID()] = array(
1803
-                        'paid'  => $registration->pretty_paid(),
1804
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
1805
-                    );
1806
-                }
1807
-            }
1808
-        }
1809
-
1810
-        return $registration_payment_data;
1811
-    }
1812
-
1813
-
1814
-    /**
1815
-     * _maybe_send_notifications
1816
-     *
1817
-     * determines whether or not the admin has indicated that notifications should be sent.
1818
-     * If so, will toggle a filter switch for delivering registration notices.
1819
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
1820
-     *
1821
-     * @access protected
1822
-     *
1823
-     * @param \EE_Payment | null $payment
1824
-     */
1825
-    protected function _maybe_send_notifications($payment = null)
1826
-    {
1827
-        switch ($payment instanceof EE_Payment) {
1828
-            // payment notifications
1829
-            case true :
1830
-                if (
1831
-                    isset(
1832
-                        $this->_req_data['txn_payments'],
1833
-                        $this->_req_data['txn_payments']['send_notifications']
1834
-                    ) &&
1835
-                    filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1836
-                ) {
1837
-                    $this->_process_payment_notification($payment);
1838
-                }
1839
-                break;
1840
-            // registration notifications
1841
-            case false :
1842
-                if (
1843
-                    isset(
1844
-                        $this->_req_data['txn_reg_status_change'],
1845
-                        $this->_req_data['txn_reg_status_change']['send_notifications']
1846
-                    ) &&
1847
-                    filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1848
-                ) {
1849
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
1850
-                }
1851
-                break;
1852
-        }
1853
-    }
1854
-
1855
-
1856
-    /**
1857
-     * _send_payment_reminder
1858
-     *    generates HTML for the View Transaction Details Admin page
1859
-     *
1860
-     * @access protected
1861
-     * @return void
1862
-     */
1863
-    protected function _send_payment_reminder()
1864
-    {
1865
-        $TXN_ID      = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
1866
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
1867
-        $query_args  = isset($this->_req_data['redirect_to']) ? array(
1868
-            'action' => $this->_req_data['redirect_to'],
1869
-            'TXN_ID' => $this->_req_data['TXN_ID']
1870
-        ) : array();
1871
-        do_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
1872
-            $transaction);
1873
-        $this->_redirect_after_action(false, esc_html__('payment reminder', 'event_espresso'),
1874
-            esc_html__('sent', 'event_espresso'), $query_args, true);
1875
-    }
1876
-
1877
-
1878
-    /**
1879
-     *  get_transactions
1880
-     *    get transactions for given parameters (used by list table)
1881
-     *
1882
-     * @param  int     $perpage how many transactions displayed per page
1883
-     * @param  boolean $count   return the count or objects
1884
-     * @param string   $view
1885
-     *
1886
-     * @return mixed int = count || array of transaction objects
1887
-     */
1888
-    public function get_transactions($perpage, $count = false, $view = '')
1889
-    {
1890
-
1891
-        $TXN = EEM_Transaction::instance();
1892
-
1893
-        $start_date = isset($this->_req_data['txn-filter-start-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-start-date']) : date('m/d/Y',
1894
-            strtotime('-10 year'));
1895
-        $end_date   = isset($this->_req_data['txn-filter-end-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-end-date']) : date('m/d/Y');
1896
-
1897
-        //make sure our timestamps start and end right at the boundaries for each day
1898
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1899
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1900
-
1901
-
1902
-        //convert to timestamps
1903
-        $start_date = strtotime($start_date);
1904
-        $end_date   = strtotime($end_date);
1905
-
1906
-        //makes sure start date is the lowest value and vice versa
1907
-        $start_date = min($start_date, $end_date);
1908
-        $end_date   = max($start_date, $end_date);
1909
-
1910
-        //convert to correct format for query
1911
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1912
-            date('Y-m-d H:i:s', $start_date), 'Y-m-d H:i:s');
1913
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1914
-            date('Y-m-d H:i:s', $end_date), 'Y-m-d H:i:s');
1915
-
1916
-
1917
-        //set orderby
1918
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1919
-
1920
-        switch ($this->_req_data['orderby']) {
1921
-            case 'TXN_ID':
1922
-                $orderby = 'TXN_ID';
1923
-                break;
1924
-            case 'ATT_fname':
1925
-                $orderby = 'Registration.Attendee.ATT_fname';
1926
-                break;
1927
-            case 'event_name':
1928
-                $orderby = 'Registration.Event.EVT_name';
1929
-                break;
1930
-            default: //'TXN_timestamp'
1931
-                $orderby = 'TXN_timestamp';
1932
-        }
1933
-
1934
-        $sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order'] : 'DESC';
1935
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
1936
-        $per_page     = isset($perpage) && ! empty($perpage) ? $perpage : 10;
1937
-        $per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
1938
-
1939
-        $offset = ($current_page - 1) * $per_page;
1940
-        $limit  = array($offset, $per_page);
1941
-
1942
-        $_where = array(
1943
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
1944
-            'Registration.REG_count' => 1
1945
-        );
1946
-
1947
-        if (isset($this->_req_data['EVT_ID'])) {
1948
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
1949
-        }
1950
-
1951
-        if (isset($this->_req_data['s'])) {
1952
-            $search_string = '%' . $this->_req_data['s'] . '%';
1953
-            $_where['OR']  = array(
1954
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
1955
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
1956
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
1957
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
1958
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
1959
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
1960
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
1961
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
1962
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
1963
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
1964
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
1965
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
1966
-                'Registration.REG_code'               => array('LIKE', $search_string),
1967
-                'Registration.REG_count'              => array('LIKE', $search_string),
1968
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
1969
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
1970
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
1971
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
1972
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
1973
-                'TXN_session_data'                    => array('LIKE', $search_string),
1974
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string)
1975
-            );
1976
-        }
1977
-
1978
-        //failed transactions
1979
-        $failed    = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'failed' && ! $count) || ($count && $view == 'failed') ? true : false;
1980
-        $abandoned = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'abandoned' && ! $count) || ($count && $view == 'abandoned') ? true : false;
1981
-
1982
-        if ($failed) {
1983
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
1984
-        } else if ($abandoned) {
1985
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
1986
-        } else {
1987
-            $_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
1988
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
1989
-        }
1990
-
1991
-        $query_params = array($_where, 'order_by' => array($orderby => $sort), 'limit' => $limit);
1992
-
1993
-        $transactions = $count ? $TXN->count(array($_where), 'TXN_ID', true) : $TXN->get_all($query_params);
1994
-
1995
-
1996
-        return $transactions;
1997
-
1998
-    }
807
+		// process payment details
808
+		$payments = $this->_transaction->get_many_related('Payment');
809
+		if ( ! empty($payments)) {
810
+			$this->_template_args['payments']              = $payments;
811
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
812
+		} else {
813
+			$this->_template_args['payments']              = false;
814
+			$this->_template_args['existing_reg_payments'] = array();
815
+		}
816
+
817
+		$this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
818
+		$this->_template_args['delete_payment_url'] = add_query_arg(array('action' => 'espresso_delete_payment'),
819
+			TXN_ADMIN_URL);
820
+
821
+		if (isset($txn_details['invoice_number'])) {
822
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
823
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__('Invoice Number',
824
+				'event_espresso');
825
+		}
826
+
827
+		$this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction->get_first_related('Registration')->get('REG_session');
828
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__('Registration Session',
829
+			'event_espresso');
830
+
831
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '';
832
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__('Transaction placed from IP',
833
+			'event_espresso');
834
+
835
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '';
836
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__('Registrant User Agent',
837
+			'event_espresso');
838
+
839
+		$reg_steps = '<ul>';
840
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
841
+			if ($reg_step_status === true) {
842
+				$reg_steps .= '<li style="color:#70cc50">' . sprintf(esc_html__('%1$s : Completed', 'event_espresso'),
843
+						ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
844
+			} else if (is_numeric($reg_step_status) && $reg_step_status !== false) {
845
+				$reg_steps .= '<li style="color:#2EA2CC">' . sprintf(
846
+						esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
847
+						ucwords(str_replace('_', ' ', $reg_step)),
848
+						date(get_option('date_format') . ' ' . get_option('time_format'),
849
+							($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)))
850
+					) . '</li>';
851
+			} else {
852
+				$reg_steps .= '<li style="color:#E76700">' . sprintf(esc_html__('%1$s : Never Initiated',
853
+						'event_espresso'), ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
854
+			}
855
+		}
856
+		$reg_steps .= '</ul>';
857
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
858
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__('Registration Step Progress',
859
+			'event_espresso');
860
+
861
+
862
+		$this->_get_registrations_to_apply_payment_to();
863
+		$this->_get_payment_methods($payments);
864
+		$this->_get_payment_status_array();
865
+		$this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
866
+
867
+		$this->_template_args['transaction_form_url']    = add_query_arg(array(
868
+			'action'  => 'edit_transaction',
869
+			'process' => 'transaction'
870
+		), TXN_ADMIN_URL);
871
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(array(
872
+			'page'   => 'espresso_transactions',
873
+			'action' => 'espresso_apply_payment'
874
+		), WP_AJAX_URL);
875
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(array(
876
+			'page'   => 'espresso_transactions',
877
+			'action' => 'espresso_delete_payment'
878
+		), WP_AJAX_URL);
879
+
880
+		// 'espresso_delete_payment_nonce'
881
+
882
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
883
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
884
+
885
+	}
886
+
887
+
888
+	/**
889
+	 * _get_registration_payment_IDs
890
+	 *
891
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
892
+	 *
893
+	 * @access protected
894
+	 *
895
+	 * @param EE_Payment[] $payments
896
+	 *
897
+	 * @return array
898
+	 */
899
+	protected function _get_registration_payment_IDs($payments = array())
900
+	{
901
+		$existing_reg_payments = array();
902
+		// get all reg payments for these payments
903
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(array(
904
+			array(
905
+				'PAY_ID' => array(
906
+					'IN',
907
+					array_keys($payments)
908
+				)
909
+			)
910
+		));
911
+		if ( ! empty($reg_payments)) {
912
+			foreach ($payments as $payment) {
913
+				if ( ! $payment instanceof EE_Payment) {
914
+					continue;
915
+				} else if ( ! isset($existing_reg_payments[$payment->ID()])) {
916
+					$existing_reg_payments[$payment->ID()] = array();
917
+				}
918
+				foreach ($reg_payments as $reg_payment) {
919
+					if ($reg_payment instanceof EE_Registration_Payment && $reg_payment->payment_ID() === $payment->ID()) {
920
+						$existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
921
+					}
922
+				}
923
+			}
924
+		}
925
+
926
+		return $existing_reg_payments;
927
+	}
928
+
929
+
930
+	/**
931
+	 * _get_registrations_to_apply_payment_to
932
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
933
+	 * which allows the admin to only apply the payment to the specific registrations
934
+	 *
935
+	 * @access protected
936
+	 * @return void
937
+	 * @throws \EE_Error
938
+	 */
939
+	protected function _get_registrations_to_apply_payment_to()
940
+	{
941
+		// we want any registration with an active status (ie: not deleted or cancelled)
942
+		$query_params                      = array(
943
+			array(
944
+				'STS_ID' => array(
945
+					'IN',
946
+					array(
947
+						EEM_Registration::status_id_approved,
948
+						EEM_Registration::status_id_pending_payment,
949
+						EEM_Registration::status_id_not_approved,
950
+					)
951
+				)
952
+			)
953
+		);
954
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
955
+				'', 'txn-admin-apply-payment-to-registrations-dv', '', 'clear: both; margin: 1.5em 0 0; display: none;'
956
+			);
957
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
958
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
959
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
960
+			EEH_HTML::tr(
961
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
962
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
963
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
964
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
965
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
966
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
967
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
968
+			)
969
+		);
970
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
971
+		// get registrations for TXN
972
+		$registrations = $this->_transaction->registrations($query_params);
973
+		foreach ($registrations as $registration) {
974
+			if ($registration instanceof EE_Registration) {
975
+				$attendee_name = $registration->attendee() instanceof EE_Attendee
976
+					? $registration->attendee()->full_name()
977
+					: esc_html__('Unknown Attendee', 'event_espresso');
978
+				$owing         = $registration->final_price() - $registration->paid();
979
+				$taxable       = $registration->ticket()->taxable()
980
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
981
+					: '';
982
+				$checked       = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
983
+					? ' checked="checked"'
984
+					: '';
985
+				$disabled      = $registration->final_price() > 0 ? '' : ' disabled';
986
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
987
+					EEH_HTML::td($registration->ID()) .
988
+					EEH_HTML::td($attendee_name) .
989
+					EEH_HTML::td(
990
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
991
+					) .
992
+					EEH_HTML::td($registration->event_name()) .
993
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
994
+					EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
995
+					EEH_HTML::td(
996
+						'<input type="checkbox" value="' . $registration->ID()
997
+						. '" name="txn_admin_payment[registrations]"'
998
+						. $checked . $disabled . '>',
999
+						'', 'jst-cntr'
1000
+					),
1001
+					'apply-payment-registration-row-' . $registration->ID()
1002
+				);
1003
+			}
1004
+		}
1005
+		$registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1006
+		$registrations_to_apply_payment_to .= EEH_HTML::tablex();
1007
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1008
+		$registrations_to_apply_payment_to .= EEH_HTML::p(
1009
+			esc_html__(
1010
+				'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.',
1011
+				'event_espresso'
1012
+			),
1013
+			'', 'clear description'
1014
+		);
1015
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1016
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1017
+	}
1018
+
1019
+
1020
+	/**
1021
+	 * _get_reg_status_selection
1022
+	 *
1023
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1024
+	 *         instead of events.
1025
+	 * @access protected
1026
+	 * @return void
1027
+	 */
1028
+	protected function _get_reg_status_selection()
1029
+	{
1030
+		//first get all possible statuses
1031
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1032
+		//let's add a "don't change" option.
1033
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1034
+		$status_array                                        = array_merge($status_array, $statuses);
1035
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input('txn_reg_status_change[reg_status]',
1036
+			$status_array, 'NAN', 'id="txn-admin-payment-reg-status-inp"', 'txn-reg-status-change-reg-status');
1037
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input('delete_txn_reg_status_change[reg_status]',
1038
+			$status_array, 'NAN', 'delete-txn-admin-payment-reg-status-inp', 'delete-txn-reg-status-change-reg-status');
1039
+
1040
+	}
1041
+
1042
+
1043
+	/**
1044
+	 *    _get_payment_methods
1045
+	 * Gets all the payment methods available generally, or the ones that are already
1046
+	 * selected on these payments (in case their payment methods are no longer active).
1047
+	 * Has the side-effect of updating the template args' payment_methods item
1048
+	 * @access private
1049
+	 *
1050
+	 * @param EE_Payment[] to show on this page
1051
+	 *
1052
+	 * @return void
1053
+	 */
1054
+	private function _get_payment_methods($payments = array())
1055
+	{
1056
+		$payment_methods_of_payments = array();
1057
+		foreach ($payments as $payment) {
1058
+			if ($payment instanceof EE_Payment) {
1059
+				$payment_methods_of_payments[] = $payment->get('PMD_ID');
1060
+			}
1061
+		}
1062
+		if ($payment_methods_of_payments) {
1063
+			$query_args = array(
1064
+				array(
1065
+					'OR*payment_method_for_payment' => array(
1066
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1067
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')
1068
+					)
1069
+				)
1070
+			);
1071
+		} else {
1072
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1073
+		}
1074
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * txn_attendees_meta_box
1080
+	 *    generates HTML for the Attendees Transaction main meta box
1081
+	 *
1082
+	 * @access public
1083
+	 *
1084
+	 * @param WP_Post $post
1085
+	 * @param array   $metabox
1086
+	 *
1087
+	 * @return void
1088
+	 */
1089
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1090
+	{
1091
+
1092
+		extract($metabox['args']);
1093
+		$this->_template_args['post']            = $post;
1094
+		$this->_template_args['event_attendees'] = array();
1095
+		// process items in cart
1096
+		$line_items = $this->_transaction->get_many_related('Line_Item', array(array('LIN_type' => 'line-item')));
1097
+		if ( ! empty($line_items)) {
1098
+			foreach ($line_items as $item) {
1099
+				if ($item instanceof EE_Line_Item) {
1100
+					switch ($item->OBJ_type()) {
1101
+
1102
+						case 'Event' :
1103
+							break;
1104
+
1105
+						case 'Ticket' :
1106
+							$ticket = $item->ticket();
1107
+							//right now we're only handling tickets here.  Cause its expected that only tickets will have attendees right?
1108
+							if ( ! $ticket instanceof EE_Ticket) {
1109
+								continue;
1110
+							}
1111
+							try {
1112
+								$event_name = $ticket->get_event_name();
1113
+							} catch (Exception $e) {
1114
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1115
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1116
+							}
1117
+							$event_name .= ' - ' . $item->get('LIN_name');
1118
+							$ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1119
+							// now get all of the registrations for this transaction that use this ticket
1120
+							$registrations = $ticket->get_many_related('Registration',
1121
+								array(array('TXN_ID' => $this->_transaction->ID())));
1122
+							foreach ($registrations as $registration) {
1123
+								if ( ! $registration instanceof EE_Registration) {
1124
+									continue;
1125
+								}
1126
+								$this->_template_args['event_attendees'][$registration->ID()]['STS_ID']            = $registration->status_ID();
1127
+								$this->_template_args['event_attendees'][$registration->ID()]['att_num']           = $registration->count();
1128
+								$this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name'] = $event_name;
1129
+								$this->_template_args['event_attendees'][$registration->ID()]['ticket_price']      = $ticket_price;
1130
+								// attendee info
1131
+								$attendee = $registration->get_first_related('Attendee');
1132
+								if ($attendee instanceof EE_Attendee) {
1133
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']   = $attendee->ID();
1134
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] = $attendee->full_name();
1135
+									$this->_template_args['event_attendees'][$registration->ID()]['email']    = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name . esc_html__(' Event',
1136
+											'event_espresso') . '">' . $attendee->email() . '</a>';
1137
+									$this->_template_args['event_attendees'][$registration->ID()]['address']  = EEH_Address::format($attendee,
1138
+										'inline', false, false);
1139
+								} else {
1140
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1141
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1142
+									$this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1143
+									$this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1144
+								}
1145
+							}
1146
+							break;
1147
+
1148
+					}
1149
+				}
1150
+			}
1151
+
1152
+			$this->_template_args['transaction_form_url'] = add_query_arg(array(
1153
+				'action'  => 'edit_transaction',
1154
+				'process' => 'attendees'
1155
+			), TXN_ADMIN_URL);
1156
+			echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1157
+				$this->_template_args, true);
1158
+
1159
+		} else {
1160
+			echo sprintf(
1161
+				esc_html__('%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1162
+					'event_espresso'),
1163
+				'<p class="important-notice">',
1164
+				'</p>'
1165
+			);
1166
+		}
1167
+	}
1168
+
1169
+
1170
+	/**
1171
+	 * txn_registrant_side_meta_box
1172
+	 * generates HTML for the Edit Transaction side meta box
1173
+	 *
1174
+	 * @access public
1175
+	 * @throws \EE_Error
1176
+	 * @return void
1177
+	 */
1178
+	public function txn_registrant_side_meta_box()
1179
+	{
1180
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->get_first_related('Attendee') : null;
1181
+		if ( ! $primary_att instanceof EE_Attendee) {
1182
+			$this->_template_args['no_attendee_message'] = esc_html__('There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1183
+				'event_espresso');
1184
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1185
+		}
1186
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1187
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1188
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1189
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1190
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1191
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1192
+			'action' => 'edit_attendee',
1193
+			'post'   => $primary_att->ID()
1194
+		), REG_ADMIN_URL);
1195
+		// get formatted address for registrant
1196
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1197
+		echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1198
+			$this->_template_args, true);
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * txn_billing_info_side_meta_box
1204
+	 *    generates HTML for the Edit Transaction side meta box
1205
+	 *
1206
+	 * @access public
1207
+	 * @return void
1208
+	 */
1209
+	public function txn_billing_info_side_meta_box()
1210
+	{
1211
+
1212
+		$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1213
+		$this->_template_args['billing_form_url'] = add_query_arg(
1214
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1215
+			TXN_ADMIN_URL
1216
+		);
1217
+
1218
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1219
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1220
+	}
1221
+
1222
+
1223
+	/**
1224
+	 * apply_payments_or_refunds
1225
+	 *    registers a payment or refund made towards a transaction
1226
+	 *
1227
+	 * @access public
1228
+	 * @return void
1229
+	 */
1230
+	public function apply_payments_or_refunds()
1231
+	{
1232
+		$json_response_data = array('return_data' => false);
1233
+		$valid_data         = $this->_validate_payment_request_data();
1234
+		if ( ! empty($valid_data)) {
1235
+			$PAY_ID = $valid_data['PAY_ID'];
1236
+			//save  the new payment
1237
+			$payment = $this->_create_payment_from_request_data($valid_data);
1238
+			// get the TXN for this payment
1239
+			$transaction = $payment->transaction();
1240
+			// verify transaction
1241
+			if ($transaction instanceof EE_Transaction) {
1242
+				// calculate_total_payments_and_update_status
1243
+				$this->_process_transaction_payments($transaction);
1244
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1245
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1246
+				// apply payment to registrations (if applicable)
1247
+				if ( ! empty($REG_IDs)) {
1248
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1249
+					$this->_maybe_send_notifications();
1250
+					// now process status changes for the same registrations
1251
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1252
+				}
1253
+				$this->_maybe_send_notifications($payment);
1254
+				//prepare to render page
1255
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1256
+				do_action('AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording', $transaction,
1257
+					$payment);
1258
+			} else {
1259
+				EE_Error::add_error(
1260
+					esc_html__('A valid Transaction for this payment could not be retrieved.', 'event_espresso'),
1261
+					__FILE__, __FUNCTION__, __LINE__
1262
+				);
1263
+			}
1264
+		} else {
1265
+			EE_Error::add_error(esc_html__('The payment form data could not be processed. Please try again.',
1266
+				'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1267
+		}
1268
+
1269
+		$notices              = EE_Error::get_notices(false, false, false);
1270
+		$this->_template_args = array(
1271
+			'data'    => $json_response_data,
1272
+			'error'   => $notices['errors'],
1273
+			'success' => $notices['success']
1274
+		);
1275
+		$this->_return_json();
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * _validate_payment_request_data
1281
+	 *
1282
+	 * @return array
1283
+	 */
1284
+	protected function _validate_payment_request_data()
1285
+	{
1286
+		if ( ! isset($this->_req_data['txn_admin_payment'])) {
1287
+			return false;
1288
+		}
1289
+		$payment_form = $this->_generate_payment_form_section();
1290
+		try {
1291
+			if ($payment_form->was_submitted()) {
1292
+				$payment_form->receive_form_submission();
1293
+				if ( ! $payment_form->is_valid()) {
1294
+					$submission_error_messages = array();
1295
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1296
+						if ($validation_error instanceof EE_Validation_Error) {
1297
+							$submission_error_messages[] = sprintf(
1298
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1299
+								$validation_error->get_form_section()->html_label_text(),
1300
+								$validation_error->getMessage()
1301
+							);
1302
+						}
1303
+					}
1304
+					EE_Error::add_error(join('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1305
+
1306
+					return array();
1307
+				}
1308
+			}
1309
+		} catch (EE_Error $e) {
1310
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1311
+
1312
+			return array();
1313
+		}
1314
+
1315
+		return $payment_form->valid_data();
1316
+	}
1317
+
1318
+
1319
+	/**
1320
+	 * _generate_payment_form_section
1321
+	 *
1322
+	 * @return EE_Form_Section_Proper
1323
+	 */
1324
+	protected function _generate_payment_form_section()
1325
+	{
1326
+		return new EE_Form_Section_Proper(
1327
+			array(
1328
+				'name'        => 'txn_admin_payment',
1329
+				'subsections' => array(
1330
+					'PAY_ID'          => new EE_Text_Input(
1331
+						array(
1332
+							'default'               => 0,
1333
+							'required'              => false,
1334
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1335
+							'validation_strategies' => array(new EE_Int_Normalization())
1336
+						)
1337
+					),
1338
+					'TXN_ID'          => new EE_Text_Input(
1339
+						array(
1340
+							'default'               => 0,
1341
+							'required'              => true,
1342
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1343
+							'validation_strategies' => array(new EE_Int_Normalization())
1344
+						)
1345
+					),
1346
+					'type'            => new EE_Text_Input(
1347
+						array(
1348
+							'default'               => 1,
1349
+							'required'              => true,
1350
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1351
+							'validation_strategies' => array(new EE_Int_Normalization())
1352
+						)
1353
+					),
1354
+					'amount'          => new EE_Text_Input(
1355
+						array(
1356
+							'default'               => 0,
1357
+							'required'              => true,
1358
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1359
+							'validation_strategies' => array(new EE_Float_Normalization())
1360
+						)
1361
+					),
1362
+					'status'          => new EE_Text_Input(
1363
+						array(
1364
+							'default'         => EEM_Payment::status_id_approved,
1365
+							'required'        => true,
1366
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1367
+						)
1368
+					),
1369
+					'PMD_ID'          => new EE_Text_Input(
1370
+						array(
1371
+							'default'               => 2,
1372
+							'required'              => true,
1373
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1374
+							'validation_strategies' => array(new EE_Int_Normalization())
1375
+						)
1376
+					),
1377
+					'date'            => new EE_Text_Input(
1378
+						array(
1379
+							'default'         => time(),
1380
+							'required'        => true,
1381
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1382
+						)
1383
+					),
1384
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1385
+						array(
1386
+							'default'               => '',
1387
+							'required'              => false,
1388
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1389
+							'validation_strategies' => array(
1390
+								new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1391
+									100),
1392
+							)
1393
+						)
1394
+					),
1395
+					'po_number'       => new EE_Text_Input(
1396
+						array(
1397
+							'default'               => '',
1398
+							'required'              => false,
1399
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1400
+							'validation_strategies' => array(
1401
+								new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1402
+									100),
1403
+							)
1404
+						)
1405
+					),
1406
+					'accounting'      => new EE_Text_Input(
1407
+						array(
1408
+							'default'               => '',
1409
+							'required'              => false,
1410
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1411
+							'validation_strategies' => array(
1412
+								new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1413
+									100),
1414
+							)
1415
+						)
1416
+					),
1417
+				)
1418
+			)
1419
+		);
1420
+	}
1421
+
1422
+
1423
+	/**
1424
+	 * _create_payment_from_request_data
1425
+	 *
1426
+	 * @param array $valid_data
1427
+	 *
1428
+	 * @return EE_Payment
1429
+	 */
1430
+	protected function _create_payment_from_request_data($valid_data)
1431
+	{
1432
+		$PAY_ID = $valid_data['PAY_ID'];
1433
+		// get payment amount
1434
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1435
+		// payments have a type value of 1 and refunds have a type value of -1
1436
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1437
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1438
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1439
+		$date    = $valid_data['date'] ? preg_replace('/\s+/', ' ', $valid_data['date']) : date('Y-m-d g:i a',
1440
+			current_time('timestamp'));
1441
+		$payment = EE_Payment::new_instance(
1442
+			array(
1443
+				'TXN_ID'              => $valid_data['TXN_ID'],
1444
+				'STS_ID'              => $valid_data['status'],
1445
+				'PAY_timestamp'       => $date,
1446
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1447
+				'PMD_ID'              => $valid_data['PMD_ID'],
1448
+				'PAY_amount'          => $amount,
1449
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1450
+				'PAY_po_number'       => $valid_data['po_number'],
1451
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1452
+				'PAY_details'         => $valid_data,
1453
+				'PAY_ID'              => $PAY_ID
1454
+			),
1455
+			'',
1456
+			array('Y-m-d', 'g:i a')
1457
+		);
1458
+
1459
+		if ( ! $payment->save()) {
1460
+			EE_Error::add_error(
1461
+				sprintf(
1462
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1463
+					$payment->ID()
1464
+				),
1465
+				__FILE__, __FUNCTION__, __LINE__
1466
+			);
1467
+		}
1468
+
1469
+		return $payment;
1470
+	}
1471
+
1472
+
1473
+	/**
1474
+	 * _process_transaction_payments
1475
+	 *
1476
+	 * @param \EE_Transaction $transaction
1477
+	 *
1478
+	 * @return array
1479
+	 */
1480
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1481
+	{
1482
+		/** @type EE_Transaction_Payments $transaction_payments */
1483
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1484
+		//update the transaction with this payment
1485
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1486
+			EE_Error::add_success(esc_html__('The payment has been processed successfully.', 'event_espresso'),
1487
+				__FILE__, __FUNCTION__, __LINE__);
1488
+		} else {
1489
+			EE_Error::add_error(
1490
+				esc_html__('The payment was processed successfully but the amount paid for the transaction was not updated.',
1491
+					'event_espresso')
1492
+				, __FILE__, __FUNCTION__, __LINE__
1493
+			);
1494
+		}
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * _get_REG_IDs_to_apply_payment_to
1500
+	 *
1501
+	 * returns a list of registration IDs that the payment will apply to
1502
+	 *
1503
+	 * @param \EE_Payment $payment
1504
+	 *
1505
+	 * @return array
1506
+	 */
1507
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1508
+	{
1509
+		$REG_IDs = array();
1510
+		// grab array of IDs for specific registrations to apply changes to
1511
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1512
+			$REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1513
+		}
1514
+		//nothing specified ? then get all reg IDs
1515
+		if (empty($REG_IDs)) {
1516
+			$registrations = $payment->transaction()->registrations();
1517
+			$REG_IDs       = ! empty($registrations) ? array_keys($registrations) : $this->_get_existing_reg_payment_REG_IDs($payment);
1518
+		}
1519
+
1520
+		// ensure that REG_IDs are integers and NOT strings
1521
+		return array_map('intval', $REG_IDs);
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * @return array
1527
+	 */
1528
+	public function existing_reg_payment_REG_IDs()
1529
+	{
1530
+		return $this->_existing_reg_payment_REG_IDs;
1531
+	}
1532
+
1533
+
1534
+	/**
1535
+	 * @param array $existing_reg_payment_REG_IDs
1536
+	 */
1537
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1538
+	{
1539
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1540
+	}
1541
+
1542
+
1543
+	/**
1544
+	 * _get_existing_reg_payment_REG_IDs
1545
+	 *
1546
+	 * returns a list of registration IDs that the payment is currently related to
1547
+	 * as recorded in the database
1548
+	 *
1549
+	 * @param \EE_Payment $payment
1550
+	 *
1551
+	 * @return array
1552
+	 */
1553
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1554
+	{
1555
+		if ($this->existing_reg_payment_REG_IDs() === null) {
1556
+			// let's get any existing reg payment records for this payment
1557
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1558
+			// but we only want the REG IDs, so grab the array keys
1559
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs) ? array_keys($existing_reg_payment_REG_IDs) : array();
1560
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1561
+		}
1562
+
1563
+		return $this->existing_reg_payment_REG_IDs();
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * _remove_existing_registration_payments
1569
+	 *
1570
+	 * this calculates the difference between existing relations
1571
+	 * to the supplied payment and the new list registration IDs,
1572
+	 * removes any related registrations that no longer apply,
1573
+	 * and then updates the registration paid fields
1574
+	 *
1575
+	 * @param \EE_Payment $payment
1576
+	 * @param int         $PAY_ID
1577
+	 *
1578
+	 * @return bool;
1579
+	 */
1580
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1581
+	{
1582
+		// newly created payments will have nothing recorded for $PAY_ID
1583
+		if ($PAY_ID == 0) {
1584
+			return false;
1585
+		}
1586
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1587
+		if (empty($existing_reg_payment_REG_IDs)) {
1588
+			return false;
1589
+		}
1590
+		/** @type EE_Transaction_Payments $transaction_payments */
1591
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1592
+
1593
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
1594
+			$payment,
1595
+			array(
1596
+				array(
1597
+					'PAY_ID' => $payment->ID(),
1598
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1599
+				)
1600
+			)
1601
+		);
1602
+	}
1603
+
1604
+
1605
+	/**
1606
+	 * _update_registration_payments
1607
+	 *
1608
+	 * this applies the payments to the selected registrations
1609
+	 * but only if they have not already been paid for
1610
+	 *
1611
+	 * @param  EE_Transaction $transaction
1612
+	 * @param \EE_Payment     $payment
1613
+	 * @param array           $REG_IDs
1614
+	 *
1615
+	 * @return bool
1616
+	 */
1617
+	protected function _update_registration_payments(
1618
+		EE_Transaction $transaction,
1619
+		EE_Payment $payment,
1620
+		$REG_IDs = array()
1621
+	) {
1622
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
1623
+		// so let's do that using our set of REG_IDs from the form
1624
+		$registration_query_where_params = array(
1625
+			'REG_ID' => array('IN', $REG_IDs)
1626
+		);
1627
+		// but add in some conditions regarding payment,
1628
+		// so that we don't apply payments to registrations that are free or have already been paid for
1629
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
1630
+		if ( ! $payment->is_a_refund()) {
1631
+			$registration_query_where_params['REG_final_price']  = array('!=', 0);
1632
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
1633
+		}
1634
+		//EEH_Debug_Tools::printr( $registration_query_where_params, '$registration_query_where_params', __FILE__, __LINE__ );
1635
+		$registrations = $transaction->registrations(array($registration_query_where_params));
1636
+		if ( ! empty($registrations)) {
1637
+			/** @type EE_Payment_Processor $payment_processor */
1638
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
1639
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
1640
+		}
1641
+	}
1642
+
1643
+
1644
+	/**
1645
+	 * _process_registration_status_change
1646
+	 *
1647
+	 * This processes requested registration status changes for all the registrations
1648
+	 * on a given transaction and (optionally) sends out notifications for the changes.
1649
+	 *
1650
+	 * @param  EE_Transaction $transaction
1651
+	 * @param array           $REG_IDs
1652
+	 *
1653
+	 * @return bool
1654
+	 */
1655
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
1656
+	{
1657
+		// first if there is no change in status then we get out.
1658
+		if (
1659
+			! isset($this->_req_data['txn_reg_status_change'], $this->_req_data['txn_reg_status_change']['reg_status'])
1660
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] == 'NAN'
1661
+		) {
1662
+			//no error message, no change requested, just nothing to do man.
1663
+			return false;
1664
+		}
1665
+		/** @type EE_Transaction_Processor $transaction_processor */
1666
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1667
+
1668
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
1669
+		return $transaction_processor->manually_update_registration_statuses(
1670
+			$transaction,
1671
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
1672
+			array(array('REG_ID' => array('IN', $REG_IDs)))
1673
+		);
1674
+	}
1675
+
1676
+
1677
+	/**
1678
+	 * _build_payment_json_response
1679
+	 *
1680
+	 * @access public
1681
+	 *
1682
+	 * @param \EE_Payment $payment
1683
+	 * @param array       $REG_IDs
1684
+	 * @param bool | null $delete_txn_reg_status_change
1685
+	 *
1686
+	 * @return array
1687
+	 */
1688
+	protected function _build_payment_json_response(
1689
+		EE_Payment $payment,
1690
+		$REG_IDs = array(),
1691
+		$delete_txn_reg_status_change = null
1692
+	) {
1693
+		// was the payment deleted ?
1694
+		if (is_bool($delete_txn_reg_status_change)) {
1695
+			return array(
1696
+				'PAY_ID'                       => $payment->ID(),
1697
+				'amount'                       => $payment->amount(),
1698
+				'total_paid'                   => $payment->transaction()->paid(),
1699
+				'txn_status'                   => $payment->transaction()->status_ID(),
1700
+				'pay_status'                   => $payment->STS_ID(),
1701
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
1702
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
1703
+			);
1704
+		} else {
1705
+			$this->_get_payment_status_array();
1706
+
1707
+			return array(
1708
+				'amount'           => $payment->amount(),
1709
+				'total_paid'       => $payment->transaction()->paid(),
1710
+				'txn_status'       => $payment->transaction()->status_ID(),
1711
+				'pay_status'       => $payment->STS_ID(),
1712
+				'PAY_ID'           => $payment->ID(),
1713
+				'STS_ID'           => $payment->STS_ID(),
1714
+				'status'           => self::$_pay_status[$payment->STS_ID()],
1715
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
1716
+				'method'           => strtoupper($payment->source()),
1717
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
1718
+				'gateway'          => $payment->payment_method() ? $payment->payment_method()->admin_name() : esc_html__("Unknown",
1719
+					'event_espresso'),
1720
+				'gateway_response' => $payment->gateway_response(),
1721
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
1722
+				'po_number'        => $payment->po_number(),
1723
+				'extra_accntng'    => $payment->extra_accntng(),
1724
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
1725
+			);
1726
+		}
1727
+	}
1728
+
1729
+
1730
+	/**
1731
+	 * delete_payment
1732
+	 *    delete a payment or refund made towards a transaction
1733
+	 *
1734
+	 * @access public
1735
+	 * @return void
1736
+	 */
1737
+	public function delete_payment()
1738
+	{
1739
+		$json_response_data = array('return_data' => false);
1740
+		$PAY_ID             = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0;
1741
+		if ($PAY_ID) {
1742
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false;
1743
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
1744
+			if ($payment instanceof EE_Payment) {
1745
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1746
+				/** @type EE_Transaction_Payments $transaction_payments */
1747
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1748
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
1749
+					$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs,
1750
+						$delete_txn_reg_status_change);
1751
+					if ($delete_txn_reg_status_change) {
1752
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
1753
+						//MAKE sure we also add the delete_txn_req_status_change to the
1754
+						//$_REQUEST global because that's how messages will be looking for it.
1755
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
1756
+						$this->_maybe_send_notifications();
1757
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
1758
+					}
1759
+				}
1760
+			} else {
1761
+				EE_Error::add_error(
1762
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
1763
+					__FILE__, __FUNCTION__, __LINE__
1764
+				);
1765
+			}
1766
+		} else {
1767
+			EE_Error::add_error(
1768
+				esc_html__('A valid Payment ID was not received, therefore payment form data could not be loaded.',
1769
+					'event_espresso'),
1770
+				__FILE__, __FUNCTION__, __LINE__
1771
+			);
1772
+		}
1773
+		$notices              = EE_Error::get_notices(false, false, false);
1774
+		$this->_template_args = array(
1775
+			'data'      => $json_response_data,
1776
+			'success'   => $notices['success'],
1777
+			'error'     => $notices['errors'],
1778
+			'attention' => $notices['attention']
1779
+		);
1780
+		$this->_return_json();
1781
+	}
1782
+
1783
+
1784
+	/**
1785
+	 * _registration_payment_data_array
1786
+	 * adds info for 'owing' and 'paid' for each registration to the json response
1787
+	 *
1788
+	 * @access protected
1789
+	 *
1790
+	 * @param array $REG_IDs
1791
+	 *
1792
+	 * @return array
1793
+	 */
1794
+	protected function _registration_payment_data_array($REG_IDs)
1795
+	{
1796
+		$registration_payment_data = array();
1797
+		//if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
1798
+		if ( ! empty($REG_IDs)) {
1799
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
1800
+			foreach ($registrations as $registration) {
1801
+				if ($registration instanceof EE_Registration) {
1802
+					$registration_payment_data[$registration->ID()] = array(
1803
+						'paid'  => $registration->pretty_paid(),
1804
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
1805
+					);
1806
+				}
1807
+			}
1808
+		}
1809
+
1810
+		return $registration_payment_data;
1811
+	}
1812
+
1813
+
1814
+	/**
1815
+	 * _maybe_send_notifications
1816
+	 *
1817
+	 * determines whether or not the admin has indicated that notifications should be sent.
1818
+	 * If so, will toggle a filter switch for delivering registration notices.
1819
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
1820
+	 *
1821
+	 * @access protected
1822
+	 *
1823
+	 * @param \EE_Payment | null $payment
1824
+	 */
1825
+	protected function _maybe_send_notifications($payment = null)
1826
+	{
1827
+		switch ($payment instanceof EE_Payment) {
1828
+			// payment notifications
1829
+			case true :
1830
+				if (
1831
+					isset(
1832
+						$this->_req_data['txn_payments'],
1833
+						$this->_req_data['txn_payments']['send_notifications']
1834
+					) &&
1835
+					filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1836
+				) {
1837
+					$this->_process_payment_notification($payment);
1838
+				}
1839
+				break;
1840
+			// registration notifications
1841
+			case false :
1842
+				if (
1843
+					isset(
1844
+						$this->_req_data['txn_reg_status_change'],
1845
+						$this->_req_data['txn_reg_status_change']['send_notifications']
1846
+					) &&
1847
+					filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1848
+				) {
1849
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
1850
+				}
1851
+				break;
1852
+		}
1853
+	}
1854
+
1855
+
1856
+	/**
1857
+	 * _send_payment_reminder
1858
+	 *    generates HTML for the View Transaction Details Admin page
1859
+	 *
1860
+	 * @access protected
1861
+	 * @return void
1862
+	 */
1863
+	protected function _send_payment_reminder()
1864
+	{
1865
+		$TXN_ID      = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
1866
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
1867
+		$query_args  = isset($this->_req_data['redirect_to']) ? array(
1868
+			'action' => $this->_req_data['redirect_to'],
1869
+			'TXN_ID' => $this->_req_data['TXN_ID']
1870
+		) : array();
1871
+		do_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
1872
+			$transaction);
1873
+		$this->_redirect_after_action(false, esc_html__('payment reminder', 'event_espresso'),
1874
+			esc_html__('sent', 'event_espresso'), $query_args, true);
1875
+	}
1876
+
1877
+
1878
+	/**
1879
+	 *  get_transactions
1880
+	 *    get transactions for given parameters (used by list table)
1881
+	 *
1882
+	 * @param  int     $perpage how many transactions displayed per page
1883
+	 * @param  boolean $count   return the count or objects
1884
+	 * @param string   $view
1885
+	 *
1886
+	 * @return mixed int = count || array of transaction objects
1887
+	 */
1888
+	public function get_transactions($perpage, $count = false, $view = '')
1889
+	{
1890
+
1891
+		$TXN = EEM_Transaction::instance();
1892
+
1893
+		$start_date = isset($this->_req_data['txn-filter-start-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-start-date']) : date('m/d/Y',
1894
+			strtotime('-10 year'));
1895
+		$end_date   = isset($this->_req_data['txn-filter-end-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-end-date']) : date('m/d/Y');
1896
+
1897
+		//make sure our timestamps start and end right at the boundaries for each day
1898
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1899
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1900
+
1901
+
1902
+		//convert to timestamps
1903
+		$start_date = strtotime($start_date);
1904
+		$end_date   = strtotime($end_date);
1905
+
1906
+		//makes sure start date is the lowest value and vice versa
1907
+		$start_date = min($start_date, $end_date);
1908
+		$end_date   = max($start_date, $end_date);
1909
+
1910
+		//convert to correct format for query
1911
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1912
+			date('Y-m-d H:i:s', $start_date), 'Y-m-d H:i:s');
1913
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1914
+			date('Y-m-d H:i:s', $end_date), 'Y-m-d H:i:s');
1915
+
1916
+
1917
+		//set orderby
1918
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1919
+
1920
+		switch ($this->_req_data['orderby']) {
1921
+			case 'TXN_ID':
1922
+				$orderby = 'TXN_ID';
1923
+				break;
1924
+			case 'ATT_fname':
1925
+				$orderby = 'Registration.Attendee.ATT_fname';
1926
+				break;
1927
+			case 'event_name':
1928
+				$orderby = 'Registration.Event.EVT_name';
1929
+				break;
1930
+			default: //'TXN_timestamp'
1931
+				$orderby = 'TXN_timestamp';
1932
+		}
1933
+
1934
+		$sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order'] : 'DESC';
1935
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
1936
+		$per_page     = isset($perpage) && ! empty($perpage) ? $perpage : 10;
1937
+		$per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
1938
+
1939
+		$offset = ($current_page - 1) * $per_page;
1940
+		$limit  = array($offset, $per_page);
1941
+
1942
+		$_where = array(
1943
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
1944
+			'Registration.REG_count' => 1
1945
+		);
1946
+
1947
+		if (isset($this->_req_data['EVT_ID'])) {
1948
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
1949
+		}
1950
+
1951
+		if (isset($this->_req_data['s'])) {
1952
+			$search_string = '%' . $this->_req_data['s'] . '%';
1953
+			$_where['OR']  = array(
1954
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
1955
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
1956
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
1957
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
1958
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
1959
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
1960
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
1961
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
1962
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
1963
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
1964
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
1965
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
1966
+				'Registration.REG_code'               => array('LIKE', $search_string),
1967
+				'Registration.REG_count'              => array('LIKE', $search_string),
1968
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
1969
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
1970
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
1971
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
1972
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
1973
+				'TXN_session_data'                    => array('LIKE', $search_string),
1974
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string)
1975
+			);
1976
+		}
1977
+
1978
+		//failed transactions
1979
+		$failed    = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'failed' && ! $count) || ($count && $view == 'failed') ? true : false;
1980
+		$abandoned = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'abandoned' && ! $count) || ($count && $view == 'abandoned') ? true : false;
1981
+
1982
+		if ($failed) {
1983
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
1984
+		} else if ($abandoned) {
1985
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
1986
+		} else {
1987
+			$_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
1988
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
1989
+		}
1990
+
1991
+		$query_params = array($_where, 'order_by' => array($orderby => $sort), 'limit' => $limit);
1992
+
1993
+		$transactions = $count ? $TXN->count(array($_where), 'TXN_ID', true) : $TXN->get_all($query_params);
1994
+
1995
+
1996
+		return $transactions;
1997
+
1998
+	}
1999 1999
 
2000 2000
 
2001 2001
 }
Please login to merge, or discard this patch.
core/libraries/plugin_api/EE_Register_Capabilities.lib.php 2 patches
Indentation   +159 added lines, -159 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@  discard block
 block discarded – undo
7 7
  * @since           4.5.0
8 8
  */
9 9
 if (! defined('EVENT_ESPRESSO_VERSION')) {
10
-    exit('No direct script access allowed');
10
+	exit('No direct script access allowed');
11 11
 }
12 12
 
13 13
 /**
@@ -21,174 +21,174 @@  discard block
 block discarded – undo
21 21
 class EE_Register_Capabilities implements EEI_Plugin_API
22 22
 {
23 23
 
24
-    /**
25
-     * Holds the settings for a specific registration.
26
-     *
27
-     * @var array
28
-     */
29
-    protected static $_registry = array();
24
+	/**
25
+	 * Holds the settings for a specific registration.
26
+	 *
27
+	 * @var array
28
+	 */
29
+	protected static $_registry = array();
30 30
 
31 31
 
32
-    /**
33
-     * Used to register capability items with EE core.
34
-     *
35
-     * @since 4.5.0
36
-     * @param string $cap_reference                                                       usually will be a class name
37
-     *                                                                                    that references capability
38
-     *                                                                                    related items setup for
39
-     *                                                                                    something.
40
-     * @param array  $setup_args                                                          {
41
-     *                                                                                    An array of items related to
42
-     *                                                                                    registering capabilities.
43
-     * @type array   $capabilities                                                        An array mapping capability
44
-     *       strings to core WP Role. Something like: array(
45
-     *                                                                                    'administrator'    => array(
46
-     *                                                                                    'read_cap', 'edit_cap',
47
-     *                                                                                    'delete_cap'),
48
-     *                                                                                    'author'                =>
49
-     *                                                                                    array( 'read_cap' )
50
-     *                                                                                    ).
51
-     * @type array   $capability_maps                                                     EE_Meta_Capability_Map[]
52
-     * @see   EE_Capabilities.php for php docs on these objects.
53
-     *                                                                                    Should be indexed by the
54
-     *                                                                                    classname for the capability
55
-     *                                                                                    map and values representing
56
-     *                                                                                    the arguments for the map.
57
-     *                                                                                    }
58
-     * @throws EE_Error
59
-     * @return void
60
-     */
61
-    public static function register($cap_reference = null, $setup_args = array())
62
-    {
63
-        //required fields MUST be present, so let's make sure they are.
64
-        if ($cap_reference === null || ! is_array($setup_args) || empty($setup_args['capabilities'])) {
65
-            throw new EE_Error(
66
-                __('In order to register capabilities with EE_Register_Capabilities::register, you must include a unique name to reference the capabilities being registered, plus an array containing the following keys: "capabilities".',
67
-                    'event_espresso')
68
-            );
69
-        }
70
-        //make sure we don't register twice
71
-        if (isset(self::$_registry[$cap_reference])) {
72
-            return;
73
-        }
74
-        //make sure this is not registered too late or too early.
75
-        if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')) {
76
-            EE_Error::doing_it_wrong(__METHOD__,
77
-                sprintf(__('%s has been registered too late.  Please ensure that EE_Register_Capabilities::register has been called at some point before the "AHEE__EE_System___detect_if_activation_or_upgrade__begin" action hook has been called.',
78
-                    'event_espresso'), $cap_reference), '4.5.0');
79
-        }
80
-        //some preliminary sanitization and setting to the $_registry property
81
-        self::$_registry[ $cap_reference ] = array(
82
-            'caps'               => isset($setup_args['capabilities']) && is_array($setup_args['capabilities'])
83
-                ? $setup_args['capabilities']
84
-                : array(),
85
-            'cap_maps'           => isset($setup_args['capability_maps'])
86
-                ? $setup_args['capability_maps']
87
-                : array(),
88
-        );
89
-        //set initial caps (note that EE_Capabilities takes care of making sure that the caps get added only once)
90
-        add_filter(
91
-            'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
92
-            array('EE_Register_Capabilities', 'register_capabilities')
93
-        );
94
-        //add filter for cap maps
95
-        add_filter(
96
-            'FHEE__EE_Capabilities___set_meta_caps__meta_caps',
97
-            array('EE_Register_Capabilities', 'register_cap_maps')
98
-        );
99
-    }
32
+	/**
33
+	 * Used to register capability items with EE core.
34
+	 *
35
+	 * @since 4.5.0
36
+	 * @param string $cap_reference                                                       usually will be a class name
37
+	 *                                                                                    that references capability
38
+	 *                                                                                    related items setup for
39
+	 *                                                                                    something.
40
+	 * @param array  $setup_args                                                          {
41
+	 *                                                                                    An array of items related to
42
+	 *                                                                                    registering capabilities.
43
+	 * @type array   $capabilities                                                        An array mapping capability
44
+	 *       strings to core WP Role. Something like: array(
45
+	 *                                                                                    'administrator'    => array(
46
+	 *                                                                                    'read_cap', 'edit_cap',
47
+	 *                                                                                    'delete_cap'),
48
+	 *                                                                                    'author'                =>
49
+	 *                                                                                    array( 'read_cap' )
50
+	 *                                                                                    ).
51
+	 * @type array   $capability_maps                                                     EE_Meta_Capability_Map[]
52
+	 * @see   EE_Capabilities.php for php docs on these objects.
53
+	 *                                                                                    Should be indexed by the
54
+	 *                                                                                    classname for the capability
55
+	 *                                                                                    map and values representing
56
+	 *                                                                                    the arguments for the map.
57
+	 *                                                                                    }
58
+	 * @throws EE_Error
59
+	 * @return void
60
+	 */
61
+	public static function register($cap_reference = null, $setup_args = array())
62
+	{
63
+		//required fields MUST be present, so let's make sure they are.
64
+		if ($cap_reference === null || ! is_array($setup_args) || empty($setup_args['capabilities'])) {
65
+			throw new EE_Error(
66
+				__('In order to register capabilities with EE_Register_Capabilities::register, you must include a unique name to reference the capabilities being registered, plus an array containing the following keys: "capabilities".',
67
+					'event_espresso')
68
+			);
69
+		}
70
+		//make sure we don't register twice
71
+		if (isset(self::$_registry[$cap_reference])) {
72
+			return;
73
+		}
74
+		//make sure this is not registered too late or too early.
75
+		if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')) {
76
+			EE_Error::doing_it_wrong(__METHOD__,
77
+				sprintf(__('%s has been registered too late.  Please ensure that EE_Register_Capabilities::register has been called at some point before the "AHEE__EE_System___detect_if_activation_or_upgrade__begin" action hook has been called.',
78
+					'event_espresso'), $cap_reference), '4.5.0');
79
+		}
80
+		//some preliminary sanitization and setting to the $_registry property
81
+		self::$_registry[ $cap_reference ] = array(
82
+			'caps'               => isset($setup_args['capabilities']) && is_array($setup_args['capabilities'])
83
+				? $setup_args['capabilities']
84
+				: array(),
85
+			'cap_maps'           => isset($setup_args['capability_maps'])
86
+				? $setup_args['capability_maps']
87
+				: array(),
88
+		);
89
+		//set initial caps (note that EE_Capabilities takes care of making sure that the caps get added only once)
90
+		add_filter(
91
+			'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
92
+			array('EE_Register_Capabilities', 'register_capabilities')
93
+		);
94
+		//add filter for cap maps
95
+		add_filter(
96
+			'FHEE__EE_Capabilities___set_meta_caps__meta_caps',
97
+			array('EE_Register_Capabilities', 'register_cap_maps')
98
+		);
99
+	}
100 100
 
101 101
 
102
-    /**
103
-     * callback for FHEE__EE_Capabilities__init_caps_map__caps filter.
104
-     * Takes care of registering additional capabilities to the caps map.   Note, that this also on the initial
105
-     * registration ensures that new capabilities are added to existing roles.
106
-     *
107
-     * @param array $incoming_caps The original caps map.
108
-     * @return array merged in new caps.
109
-     */
110
-    public static function register_capabilities($incoming_caps)
111
-    {
112
-        foreach (self::$_registry as $cap_reference => $caps_and_cap_map) {
113
-            $incoming_caps = array_merge_recursive($incoming_caps, $caps_and_cap_map['caps']);
114
-        }
115
-        return $incoming_caps;
116
-    }
102
+	/**
103
+	 * callback for FHEE__EE_Capabilities__init_caps_map__caps filter.
104
+	 * Takes care of registering additional capabilities to the caps map.   Note, that this also on the initial
105
+	 * registration ensures that new capabilities are added to existing roles.
106
+	 *
107
+	 * @param array $incoming_caps The original caps map.
108
+	 * @return array merged in new caps.
109
+	 */
110
+	public static function register_capabilities($incoming_caps)
111
+	{
112
+		foreach (self::$_registry as $cap_reference => $caps_and_cap_map) {
113
+			$incoming_caps = array_merge_recursive($incoming_caps, $caps_and_cap_map['caps']);
114
+		}
115
+		return $incoming_caps;
116
+	}
117 117
 
118 118
 
119
-    /**
120
-     * Callback for the 'FHEE__EE_Capabilities___set_meta_caps__meta_caps' filter which registers an array of
121
-     * capability maps for the WP meta_caps filter called in EE_Capabilities.
122
-     *
123
-     * @since 4.5.0
124
-     * @param EE_Meta_Capability_Map[] $cap_maps The existing cap maps array.
125
-     * @return EE_Meta_Capability_Map[]
126
-     * @throws EE_Error
127
-     */
128
-    public static function register_cap_maps($cap_maps)
129
-    {
130
-        //loop through and instantiate cap maps.
131
-        foreach (self::$_registry as $cap_reference => $setup) {
132
-            if (! isset($setup['cap_maps'])) {
133
-                continue;
134
-            }
135
-            foreach ($setup['cap_maps'] as $cap_class => $args) {
119
+	/**
120
+	 * Callback for the 'FHEE__EE_Capabilities___set_meta_caps__meta_caps' filter which registers an array of
121
+	 * capability maps for the WP meta_caps filter called in EE_Capabilities.
122
+	 *
123
+	 * @since 4.5.0
124
+	 * @param EE_Meta_Capability_Map[] $cap_maps The existing cap maps array.
125
+	 * @return EE_Meta_Capability_Map[]
126
+	 * @throws EE_Error
127
+	 */
128
+	public static function register_cap_maps($cap_maps)
129
+	{
130
+		//loop through and instantiate cap maps.
131
+		foreach (self::$_registry as $cap_reference => $setup) {
132
+			if (! isset($setup['cap_maps'])) {
133
+				continue;
134
+			}
135
+			foreach ($setup['cap_maps'] as $cap_class => $args) {
136 136
 
137
-                /**
138
-                 * account for cases where capability maps may be indexed
139
-                 * numerically to allow for the same map class to be utilized
140
-                 * In those cases, maps will be setup in an array like:
141
-                 * array(
142
-                 *    0 => array( 'EE_Meta_Capability' => array(
143
-                 *        'ee_edit_cap', array( 'Object_Name',
144
-                 *        'ee_edit_published_cap',
145
-                 *        'ee_edit_others_cap', 'ee_edit_private_cap' )
146
-                 *        ) )
147
-                 *    1 => ...
148
-                 * )
149
-                 * instead of:
150
-                 * array(
151
-                 *    'EE_Meta_Capability' => array(
152
-                 *        'ee_edit_cap', array( 'Object_Name',
153
-                 *        'ee_edit_published_cap',
154
-                 *        'ee_edit_others_cap', 'ee_edit_private_cap' )
155
-                 *        ),
156
-                 *    ...
157
-                 * )
158
-                 */
159
-                if (is_numeric($cap_class)) {
160
-                    $cap_class = key($args);
161
-                    $args      = $args[$cap_class];
162
-                }
137
+				/**
138
+				 * account for cases where capability maps may be indexed
139
+				 * numerically to allow for the same map class to be utilized
140
+				 * In those cases, maps will be setup in an array like:
141
+				 * array(
142
+				 *    0 => array( 'EE_Meta_Capability' => array(
143
+				 *        'ee_edit_cap', array( 'Object_Name',
144
+				 *        'ee_edit_published_cap',
145
+				 *        'ee_edit_others_cap', 'ee_edit_private_cap' )
146
+				 *        ) )
147
+				 *    1 => ...
148
+				 * )
149
+				 * instead of:
150
+				 * array(
151
+				 *    'EE_Meta_Capability' => array(
152
+				 *        'ee_edit_cap', array( 'Object_Name',
153
+				 *        'ee_edit_published_cap',
154
+				 *        'ee_edit_others_cap', 'ee_edit_private_cap' )
155
+				 *        ),
156
+				 *    ...
157
+				 * )
158
+				 */
159
+				if (is_numeric($cap_class)) {
160
+					$cap_class = key($args);
161
+					$args      = $args[$cap_class];
162
+				}
163 163
 
164
-                if (! class_exists($cap_class)) {
165
-                    throw new EE_Error(sprintf(__('An addon (%s) has tried to register a capability map improperly.  Capability map arrays must be indexed by capability map classname, and an array for the class arguments',
166
-                        'event_espresso'), $cap_reference));
167
-                }
164
+				if (! class_exists($cap_class)) {
165
+					throw new EE_Error(sprintf(__('An addon (%s) has tried to register a capability map improperly.  Capability map arrays must be indexed by capability map classname, and an array for the class arguments',
166
+						'event_espresso'), $cap_reference));
167
+				}
168 168
 
169
-                if (count($args) !== 2) {
170
-                    throw new EE_Error(sprintf(__('An addon (%s) has tried to register a capability map improperly.  Capability map arrays must be indexed by capability map classname, and an array for the class arguments.  The array should have two values the first being a string and the second an array.',
171
-                        'event_espresso'), $cap_reference));
172
-                }
173
-                $cap_maps[] = new $cap_class($args[0], $args[1]);
174
-            }
175
-        }
176
-        return $cap_maps;
177
-    }
169
+				if (count($args) !== 2) {
170
+					throw new EE_Error(sprintf(__('An addon (%s) has tried to register a capability map improperly.  Capability map arrays must be indexed by capability map classname, and an array for the class arguments.  The array should have two values the first being a string and the second an array.',
171
+						'event_espresso'), $cap_reference));
172
+				}
173
+				$cap_maps[] = new $cap_class($args[0], $args[1]);
174
+			}
175
+		}
176
+		return $cap_maps;
177
+	}
178 178
 
179 179
 
180 180
 
181
-    /**
182
-     * @param string $cap_reference
183
-     * @throws EE_Error
184
-     */
185
-    public static function deregister($cap_reference = '')
186
-    {
187
-        if (! empty(self::$_registry[$cap_reference])) {
188
-            if (! empty(self::$_registry[ $cap_reference ]['caps'])) {
189
-                EE_Capabilities::instance()->removeCaps(self::$_registry[ $cap_reference ]['caps']);
190
-            }
191
-            unset(self::$_registry[$cap_reference]);
192
-        }
193
-    }
181
+	/**
182
+	 * @param string $cap_reference
183
+	 * @throws EE_Error
184
+	 */
185
+	public static function deregister($cap_reference = '')
186
+	{
187
+		if (! empty(self::$_registry[$cap_reference])) {
188
+			if (! empty(self::$_registry[ $cap_reference ]['caps'])) {
189
+				EE_Capabilities::instance()->removeCaps(self::$_registry[ $cap_reference ]['caps']);
190
+			}
191
+			unset(self::$_registry[$cap_reference]);
192
+		}
193
+	}
194 194
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
  * @subpackage      plugin api, capabilities
7 7
  * @since           4.5.0
8 8
  */
9
-if (! defined('EVENT_ESPRESSO_VERSION')) {
9
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
10 10
     exit('No direct script access allowed');
11 11
 }
12 12
 
@@ -72,13 +72,13 @@  discard block
 block discarded – undo
72 72
             return;
73 73
         }
74 74
         //make sure this is not registered too late or too early.
75
-        if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')) {
75
+        if ( ! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')) {
76 76
             EE_Error::doing_it_wrong(__METHOD__,
77 77
                 sprintf(__('%s has been registered too late.  Please ensure that EE_Register_Capabilities::register has been called at some point before the "AHEE__EE_System___detect_if_activation_or_upgrade__begin" action hook has been called.',
78 78
                     'event_espresso'), $cap_reference), '4.5.0');
79 79
         }
80 80
         //some preliminary sanitization and setting to the $_registry property
81
-        self::$_registry[ $cap_reference ] = array(
81
+        self::$_registry[$cap_reference] = array(
82 82
             'caps'               => isset($setup_args['capabilities']) && is_array($setup_args['capabilities'])
83 83
                 ? $setup_args['capabilities']
84 84
                 : array(),
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
     {
130 130
         //loop through and instantiate cap maps.
131 131
         foreach (self::$_registry as $cap_reference => $setup) {
132
-            if (! isset($setup['cap_maps'])) {
132
+            if ( ! isset($setup['cap_maps'])) {
133 133
                 continue;
134 134
             }
135 135
             foreach ($setup['cap_maps'] as $cap_class => $args) {
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
                     $args      = $args[$cap_class];
162 162
                 }
163 163
 
164
-                if (! class_exists($cap_class)) {
164
+                if ( ! class_exists($cap_class)) {
165 165
                     throw new EE_Error(sprintf(__('An addon (%s) has tried to register a capability map improperly.  Capability map arrays must be indexed by capability map classname, and an array for the class arguments',
166 166
                         'event_espresso'), $cap_reference));
167 167
                 }
@@ -184,9 +184,9 @@  discard block
 block discarded – undo
184 184
      */
185 185
     public static function deregister($cap_reference = '')
186 186
     {
187
-        if (! empty(self::$_registry[$cap_reference])) {
188
-            if (! empty(self::$_registry[ $cap_reference ]['caps'])) {
189
-                EE_Capabilities::instance()->removeCaps(self::$_registry[ $cap_reference ]['caps']);
187
+        if ( ! empty(self::$_registry[$cap_reference])) {
188
+            if ( ! empty(self::$_registry[$cap_reference]['caps'])) {
189
+                EE_Capabilities::instance()->removeCaps(self::$_registry[$cap_reference]['caps']);
190 190
             }
191 191
             unset(self::$_registry[$cap_reference]);
192 192
         }
Please login to merge, or discard this patch.
core/libraries/payment_methods/EE_Payment_Method_Manager.lib.php 2 patches
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@  discard block
 block discarded – undo
20 20
     /**
21 21
      * prefix added to all payment method capabilities names
22 22
      */
23
-    const   CAPABILITIES_PREFIX= 'ee_payment_method_';
23
+    const   CAPABILITIES_PREFIX = 'ee_payment_method_';
24 24
 
25 25
     /**
26 26
      * @var EE_Payment_Method_Manager $_instance
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
     public static function instance()
77 77
     {
78 78
         // check if class object is instantiated, and instantiated properly
79
-        if (! self::$_instance instanceof EE_Payment_Method_Manager) {
79
+        if ( ! self::$_instance instanceof EE_Payment_Method_Manager) {
80 80
             EE_Registry::instance()->load_lib('PMT_Base');
81 81
             self::$_instance = new self();
82 82
         }
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
      */
110 110
     public function maybe_register_payment_methods($force_recheck = false)
111 111
     {
112
-        if (! $this->_payment_method_types || $force_recheck) {
112
+        if ( ! $this->_payment_method_types || $force_recheck) {
113 113
             $this->_register_payment_methods();
114 114
         }
115 115
     }
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
     protected function _register_payment_methods()
125 125
     {
126 126
         // grab list of installed modules
127
-        $pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
127
+        $pm_to_register = glob(EE_PAYMENT_METHODS.'*', GLOB_ONLYDIR);
128 128
         // filter list of modules to register
129 129
         $pm_to_register = apply_filters(
130 130
             'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
@@ -165,31 +165,31 @@  discard block
 block discarded – undo
165 165
         // create class name from module directory name
166 166
         $module = str_replace(array('_', ' '), array(' ', '_'), $module_dir);
167 167
         // add class prefix
168
-        $module_class = 'EE_PMT_' . $module;
168
+        $module_class = 'EE_PMT_'.$module;
169 169
         // does the module exist ?
170
-        if (! is_readable($payment_method_path . DS . $module_class . $module_ext)) {
170
+        if ( ! is_readable($payment_method_path.DS.$module_class.$module_ext)) {
171 171
             $msg = sprintf(
172 172
                 esc_html__(
173 173
                     'The requested %s payment method file could not be found or is not readable due to file permissions.',
174 174
                     'event_espresso'
175 175
                 ), $module
176 176
             );
177
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
177
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
178 178
             return false;
179 179
         }
180 180
         // load the module class file
181
-        require_once($payment_method_path . DS . $module_class . $module_ext);
181
+        require_once($payment_method_path.DS.$module_class.$module_ext);
182 182
         // verify that class exists
183
-        if (! class_exists($module_class)) {
183
+        if ( ! class_exists($module_class)) {
184 184
             $msg = sprintf(
185 185
                 esc_html__('The requested %s module class does not exist.', 'event_espresso'),
186 186
                 $module_class
187 187
             );
188
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
188
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
189 189
             return false;
190 190
         }
191 191
         // add to array of registered modules
192
-        $this->_payment_method_types[$module] = $payment_method_path . DS . $module_class . $module_ext;
192
+        $this->_payment_method_types[$module] = $payment_method_path.DS.$module_class.$module_ext;
193 193
         return true;
194 194
     }
195 195
 
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
         if ($force_recheck || empty($this->payment_method_objects)) {
257 257
             $this->maybe_register_payment_methods($force_recheck);
258 258
             foreach ($this->payment_method_type_names(true) as $classname) {
259
-                if (! isset($this->payment_method_objects[$classname])) {
259
+                if ( ! isset($this->payment_method_objects[$classname])) {
260 260
                     $this->payment_method_objects[$classname] = new $classname;
261 261
                 }
262 262
             }
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
      */
289 289
     public function payment_method_class_from_type($type)
290 290
     {
291
-        return 'EE_PMT_' . $type;
291
+        return 'EE_PMT_'.$type;
292 292
     }
293 293
 
294 294
 
@@ -304,13 +304,13 @@  discard block
 block discarded – undo
304 304
     {
305 305
         $this->maybe_register_payment_methods();
306 306
         $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
307
-        if (! $payment_method instanceof EE_Payment_Method) {
307
+        if ( ! $payment_method instanceof EE_Payment_Method) {
308 308
             $pm_type_class = $this->payment_method_class_from_type($payment_method_type);
309 309
             if (class_exists($pm_type_class)) {
310 310
                 /** @var $pm_type_obj EE_PMT_Base */
311 311
                 $pm_type_obj = new $pm_type_class;
312 312
                 $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
313
-                if (! $payment_method) {
313
+                if ( ! $payment_method) {
314 314
                     $payment_method = $this->create_payment_method_of_type($pm_type_obj);
315 315
                 }
316 316
                 $payment_method->set_type($payment_method_type);
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
                         'The Invoice payment method has been activated. It requires the invoice message type, html messenger, and pdf messenger be activated as well for the %1$smessages system%2$s, so it has been automatically verified that they are also active.',
342 342
                         'event_espresso'
343 343
                     ),
344
-                    '<a href="' . admin_url('admin.php?page=espresso_messages') . '">',
344
+                    '<a href="'.admin_url('admin.php?page=espresso_messages').'">',
345 345
                     '</a>'
346 346
                 ),
347 347
                 true
@@ -368,7 +368,7 @@  discard block
 block discarded – undo
368 368
                 'PMD_type'       => $pm_type_obj->system_name(),
369 369
                 'PMD_name'       => $pm_type_obj->pretty_name(),
370 370
                 'PMD_admin_name' => $pm_type_obj->pretty_name(),
371
-                'PMD_slug'       => $pm_type_obj->system_name(),//automatically converted to slug
371
+                'PMD_slug'       => $pm_type_obj->system_name(), //automatically converted to slug
372 372
                 'PMD_wp_user'    => $current_user->ID,
373 373
                 'PMD_order'      => EEM_Payment_Method::instance()->count(
374 374
                         array(array('PMD_type' => array('!=', 'Admin_Only')))
@@ -391,14 +391,14 @@  discard block
 block discarded – undo
391 391
     {
392 392
         $pm_type_obj = $payment_method->type_obj();
393 393
         $payment_method->set_description($pm_type_obj->default_description());
394
-        if (! $payment_method->button_url()) {
394
+        if ( ! $payment_method->button_url()) {
395 395
             $payment_method->set_button_url($pm_type_obj->default_button_url());
396 396
         }
397 397
         //now add setup its default extra meta properties
398 398
         $extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
399
-        if (! empty($extra_metas)) {
399
+        if ( ! empty($extra_metas)) {
400 400
             //verify the payment method has an ID before adding extra meta
401
-            if (! $payment_method->ID()) {
401
+            if ( ! $payment_method->ID()) {
402 402
                 $payment_method->save();
403 403
             }
404 404
             foreach ($extra_metas as $meta_name => $input) {
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
     {
507 507
         $caps = array();
508 508
         foreach ($this->payment_method_type_names() as $payment_method_name) {
509
-            $caps = $this->addPaymentMethodCap($payment_method_name,$caps);
509
+            $caps = $this->addPaymentMethodCap($payment_method_name, $caps);
510 510
         }
511 511
         return $caps;
512 512
     }
@@ -541,7 +541,7 @@  discard block
 block discarded – undo
541 541
                 )
542 542
             );
543 543
         }
544
-        if(! isset($payment_method_caps[$role])) {
544
+        if ( ! isset($payment_method_caps[$role])) {
545 545
             $payment_method_caps[$role] = array();
546 546
         }
547 547
         $payment_method_caps[$role][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX
Please login to merge, or discard this patch.
Indentation   +564 added lines, -564 removed lines patch added patch discarded remove patch
@@ -19,570 +19,570 @@
 block discarded – undo
19 19
 class EE_Payment_Method_Manager implements ResettableInterface
20 20
 {
21 21
 
22
-    /**
23
-     * prefix added to all payment method capabilities names
24
-     */
25
-    const   CAPABILITIES_PREFIX= 'ee_payment_method_';
26
-
27
-    /**
28
-     * @var EE_Payment_Method_Manager $_instance
29
-     */
30
-    private static $_instance;
31
-
32
-    /**
33
-     * @var boolean
34
-     */
35
-    protected $payment_method_caps_initialized = false;
36
-
37
-    /**
38
-     * @var array keys are class names without 'EE_PMT_', values are their filepaths
39
-     */
40
-    protected $_payment_method_types = array();
41
-
42
-    /**
43
-     * @var EE_PMT_Base[]
44
-     */
45
-    protected $payment_method_objects = array();
46
-
47
-
48
-
49
-    /**
50
-     * EE_Payment_Method_Manager constructor.
51
-     *
52
-     * @throws EE_Error
53
-     * @throws DomainException
54
-     */
55
-    public function __construct()
56
-    {
57
-        // if in admin lets ensure caps are set.
58
-        if (is_admin()) {
59
-            $this->_register_payment_methods();
60
-            // set them immediately
61
-            $this->initializePaymentMethodCaps();
62
-            // plus any time they get reset
63
-            add_filter(
64
-                'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
65
-                array($this, 'addPaymentMethodCapsDuringReset')
66
-            );
67
-        }
68
-    }
69
-
70
-
71
-
72
-    /**
73
-     * @singleton method used to instantiate class object
74
-     * @return EE_Payment_Method_Manager instance
75
-     * @throws DomainException
76
-     * @throws EE_Error
77
-     */
78
-    public static function instance()
79
-    {
80
-        // check if class object is instantiated, and instantiated properly
81
-        if (! self::$_instance instanceof EE_Payment_Method_Manager) {
82
-            EE_Registry::instance()->load_lib('PMT_Base');
83
-            self::$_instance = new self();
84
-        }
85
-        return self::$_instance;
86
-    }
87
-
88
-
89
-
90
-    /**
91
-     * Resets the instance and returns a new one
92
-     *
93
-     * @return EE_Payment_Method_Manager
94
-     * @throws DomainException
95
-     * @throws EE_Error
96
-     */
97
-    public static function reset()
98
-    {
99
-        self::$_instance = null;
100
-        return self::instance();
101
-    }
102
-
103
-
104
-
105
-    /**
106
-     * If necessary, re-register payment methods
107
-     *
108
-     * @param boolean $force_recheck whether to recheck for payment method types,
109
-     *                               or just re-use the PMTs we found last time we checked during this request (if
110
-     *                               we have not yet checked during this request, then we need to check anyways)
111
-     */
112
-    public function maybe_register_payment_methods($force_recheck = false)
113
-    {
114
-        if (! $this->_payment_method_types || $force_recheck) {
115
-            $this->_register_payment_methods();
116
-        }
117
-    }
118
-
119
-
120
-
121
-    /**
122
-     * register_payment_methods
123
-     *
124
-     * @return array
125
-     */
126
-    protected function _register_payment_methods()
127
-    {
128
-        // grab list of installed modules
129
-        $pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
130
-        // filter list of modules to register
131
-        $pm_to_register = apply_filters(
132
-            'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
133
-            $pm_to_register
134
-        );
135
-        // remove any duplicates if that should happen for some reason
136
-        $pm_to_register = array_unique($pm_to_register);
137
-        // loop through folders
138
-        foreach ($pm_to_register as $pm_path) {
139
-            $this->register_payment_method($pm_path);
140
-        }
141
-        do_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods');
142
-        // filter list of installed modules
143
-        //keep them organized alphabetically by the payment method type's name
144
-        ksort($this->_payment_method_types);
145
-        return apply_filters(
146
-            'FHEE__EE_Payment_Method_Manager__register_payment_methods__installed_payment_methods',
147
-            $this->_payment_method_types
148
-        );
149
-    }
150
-
151
-
152
-
153
-    /**
154
-     * register_payment_method- makes core aware of this payment method
155
-     *
156
-     * @param string $payment_method_path - full path up to and including payment method folder
157
-     * @return boolean
158
-     */
159
-    public function register_payment_method($payment_method_path = '')
160
-    {
161
-        do_action('AHEE__EE_Payment_Method_Manager__register_payment_method__begin', $payment_method_path);
162
-        $module_ext = '.pm.php';
163
-        // make all separators match
164
-        $payment_method_path = rtrim(str_replace('/\\', DS, $payment_method_path), DS);
165
-        // grab and sanitize module name
166
-        $module_dir = basename($payment_method_path);
167
-        // create class name from module directory name
168
-        $module = str_replace(array('_', ' '), array(' ', '_'), $module_dir);
169
-        // add class prefix
170
-        $module_class = 'EE_PMT_' . $module;
171
-        // does the module exist ?
172
-        if (! is_readable($payment_method_path . DS . $module_class . $module_ext)) {
173
-            $msg = sprintf(
174
-                esc_html__(
175
-                    'The requested %s payment method file could not be found or is not readable due to file permissions.',
176
-                    'event_espresso'
177
-                ), $module
178
-            );
179
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
180
-            return false;
181
-        }
182
-        // load the module class file
183
-        require_once($payment_method_path . DS . $module_class . $module_ext);
184
-        // verify that class exists
185
-        if (! class_exists($module_class)) {
186
-            $msg = sprintf(
187
-                esc_html__('The requested %s module class does not exist.', 'event_espresso'),
188
-                $module_class
189
-            );
190
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
191
-            return false;
192
-        }
193
-        // add to array of registered modules
194
-        $this->_payment_method_types[$module] = $payment_method_path . DS . $module_class . $module_ext;
195
-        return true;
196
-    }
197
-
198
-
199
-
200
-    /**
201
-     * Checks if a payment method has been registered, and if so includes it
202
-     *
203
-     * @param string  $payment_method_name like 'PayPal_Pro', (ie class name without the prefix 'EEPM_')
204
-     * @param boolean $force_recheck       whether to force re-checking for new payment method types
205
-     * @return boolean
206
-     */
207
-    public function payment_method_type_exists($payment_method_name, $force_recheck = false)
208
-    {
209
-        if (
210
-            $force_recheck
211
-            || ! is_array($this->_payment_method_types)
212
-            || ! isset($this->_payment_method_types[$payment_method_name])
213
-        ) {
214
-            $this->maybe_register_payment_methods($force_recheck);
215
-        }
216
-        if (isset($this->_payment_method_types[$payment_method_name])) {
217
-            require_once($this->_payment_method_types[$payment_method_name]);
218
-            return true;
219
-        }
220
-        return false;
221
-    }
222
-
223
-
224
-
225
-    /**
226
-     * Returns all the class names of the various payment method types
227
-     *
228
-     * @param boolean $with_prefixes TRUE: get payment method type class names; false just their 'names'
229
-     *                               (what you'd find in wp_esp_payment_method.PMD_type)
230
-     * @param boolean $force_recheck whether to force re-checking for new payment method types
231
-     * @return array
232
-     */
233
-    public function payment_method_type_names($with_prefixes = false, $force_recheck = false)
234
-    {
235
-        $this->maybe_register_payment_methods($force_recheck);
236
-        if ($with_prefixes) {
237
-            $classnames = array_keys($this->_payment_method_types);
238
-            $payment_methods = array();
239
-            foreach ($classnames as $classname) {
240
-                $payment_methods[] = $this->payment_method_class_from_type($classname);
241
-            }
242
-            return $payment_methods;
243
-        }
244
-        return array_keys($this->_payment_method_types);
245
-    }
246
-
247
-
248
-
249
-    /**
250
-     * Gets an object of each payment method type, none of which are bound to a
251
-     * payment method instance
252
-     *
253
-     * @param boolean $force_recheck whether to force re-checking for new payment method types
254
-     * @return EE_PMT_Base[]
255
-     */
256
-    public function payment_method_types($force_recheck = false)
257
-    {
258
-        if ($force_recheck || empty($this->payment_method_objects)) {
259
-            $this->maybe_register_payment_methods($force_recheck);
260
-            foreach ($this->payment_method_type_names(true) as $classname) {
261
-                if (! isset($this->payment_method_objects[$classname])) {
262
-                    $this->payment_method_objects[$classname] = new $classname;
263
-                }
264
-            }
265
-        }
266
-        return $this->payment_method_objects;
267
-    }
268
-
269
-
270
-
271
-    /**
272
-     * Changes the payment method's class name into the payment method type's name
273
-     * (as used on the payment method's table's PMD_type field)
274
-     *
275
-     * @param string $classname
276
-     * @return string
277
-     */
278
-    public function payment_method_type_sans_class_prefix($classname)
279
-    {
280
-        return str_replace('EE_PMT_', '', $classname);
281
-    }
282
-
283
-
284
-
285
-    /**
286
-     * Does the opposite of payment-method_type_sans_prefix
287
-     *
288
-     * @param string $type
289
-     * @return string
290
-     */
291
-    public function payment_method_class_from_type($type)
292
-    {
293
-        return 'EE_PMT_' . $type;
294
-    }
295
-
296
-
297
-
298
-    /**
299
-     * Activates a payment method of the given type.
300
-     *
301
-     * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
302
-     * @return EE_Payment_Method
303
-     * @throws EE_Error
304
-     */
305
-    public function activate_a_payment_method_of_type($payment_method_type)
306
-    {
307
-        $this->maybe_register_payment_methods();
308
-        $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
309
-        if (! $payment_method instanceof EE_Payment_Method) {
310
-            $pm_type_class = $this->payment_method_class_from_type($payment_method_type);
311
-            if (class_exists($pm_type_class)) {
312
-                /** @var $pm_type_obj EE_PMT_Base */
313
-                $pm_type_obj = new $pm_type_class;
314
-                $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
315
-                if (! $payment_method) {
316
-                    $payment_method = $this->create_payment_method_of_type($pm_type_obj);
317
-                }
318
-                $payment_method->set_type($payment_method_type);
319
-                $this->initialize_payment_method($payment_method);
320
-            } else {
321
-                throw new EE_Error(
322
-                    sprintf(
323
-                        esc_html__(
324
-                            'There is no payment method of type %1$s, so it could not be activated',
325
-                            'event_espresso'
326
-                        ),
327
-                        $pm_type_class
328
-                    )
329
-                );
330
-            }
331
-        }
332
-        $payment_method->set_active();
333
-        $payment_method->save();
334
-        if ($payment_method->type() === 'Invoice') {
335
-            /** @type EE_Message_Resource_Manager $message_resource_manager */
336
-            $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
337
-            $message_resource_manager->ensure_message_type_is_active('invoice', 'html');
338
-            $message_resource_manager->ensure_messenger_is_active('pdf');
339
-            EE_Error::add_persistent_admin_notice(
340
-                'invoice_pm_requirements_notice',
341
-                sprintf(
342
-                    esc_html__(
343
-                        'The Invoice payment method has been activated. It requires the invoice message type, html messenger, and pdf messenger be activated as well for the %1$smessages system%2$s, so it has been automatically verified that they are also active.',
344
-                        'event_espresso'
345
-                    ),
346
-                    '<a href="' . admin_url('admin.php?page=espresso_messages') . '">',
347
-                    '</a>'
348
-                ),
349
-                true
350
-            );
351
-        }
352
-        return $payment_method;
353
-    }
354
-
355
-
356
-
357
-    /**
358
-     * Creates a payment method of the specified type. Does not save it.
359
-     *
360
-     * @global WP_User    $current_user
361
-     * @param EE_PMT_Base $pm_type_obj
362
-     * @return EE_Payment_Method
363
-     * @throws EE_Error
364
-     */
365
-    public function create_payment_method_of_type($pm_type_obj)
366
-    {
367
-        global $current_user;
368
-        $payment_method = EE_Payment_Method::new_instance(
369
-            array(
370
-                'PMD_type'       => $pm_type_obj->system_name(),
371
-                'PMD_name'       => $pm_type_obj->pretty_name(),
372
-                'PMD_admin_name' => $pm_type_obj->pretty_name(),
373
-                'PMD_slug'       => $pm_type_obj->system_name(),//automatically converted to slug
374
-                'PMD_wp_user'    => $current_user->ID,
375
-                'PMD_order'      => EEM_Payment_Method::instance()->count(
376
-                        array(array('PMD_type' => array('!=', 'Admin_Only')))
377
-                    ) * 10,
378
-            )
379
-        );
380
-        return $payment_method;
381
-    }
382
-
383
-
384
-
385
-    /**
386
-     * Sets the initial payment method properties (including extra meta)
387
-     *
388
-     * @param EE_Payment_Method $payment_method
389
-     * @return EE_Payment_Method
390
-     * @throws EE_Error
391
-     */
392
-    public function initialize_payment_method($payment_method)
393
-    {
394
-        $pm_type_obj = $payment_method->type_obj();
395
-        $payment_method->set_description($pm_type_obj->default_description());
396
-        if (! $payment_method->button_url()) {
397
-            $payment_method->set_button_url($pm_type_obj->default_button_url());
398
-        }
399
-        //now add setup its default extra meta properties
400
-        $extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
401
-        if (! empty($extra_metas)) {
402
-            //verify the payment method has an ID before adding extra meta
403
-            if (! $payment_method->ID()) {
404
-                $payment_method->save();
405
-            }
406
-            foreach ($extra_metas as $meta_name => $input) {
407
-                $payment_method->update_extra_meta($meta_name, $input->raw_value());
408
-            }
409
-        }
410
-        return $payment_method;
411
-    }
412
-
413
-
414
-
415
-    /**
416
-     * Makes sure the payment method is related to the specified payment method
417
-     *
418
-     * @deprecated in 4.9.40 because the currency payment method table is being deprecated
419
-     * @param EE_Payment_Method $payment_method
420
-     * @return EE_Payment_Method
421
-     * @throws EE_Error
422
-     */
423
-    public function set_usable_currencies_on_payment_method($payment_method)
424
-    {
425
-        EE_Error::doing_it_wrong(
426
-            'EE_Payment_Method_Manager::set_usable_currencies_on_payment_method',
427
-            esc_html__(
428
-                'We no longer define what currencies are usable by payment methods. Its not used nor efficient.',
429
-                'event_espresso'
430
-            ),
431
-            '4.9.40'
432
-        );
433
-        return $payment_method;
434
-    }
435
-
436
-
437
-
438
-    /**
439
-     * Deactivates a payment method of the given payment method slug.
440
-     *
441
-     * @param string $payment_method_slug The slug for the payment method to deactivate.
442
-     * @return int count of rows updated.
443
-     * @throws EE_Error
444
-     */
445
-    public function deactivate_payment_method($payment_method_slug)
446
-    {
447
-        EE_Log::instance()->log(
448
-            __FILE__,
449
-            __FUNCTION__,
450
-            sprintf(
451
-                esc_html__(
452
-                    'Payment method with slug %1$s is being deactivated by site admin',
453
-                    'event_espresso'
454
-                ),
455
-                $payment_method_slug
456
-            ),
457
-            'payment_method_change'
458
-        );
459
-        $count_updated = EEM_Payment_Method::instance()->update(
460
-            array('PMD_scope' => array()),
461
-            array(array('PMD_slug' => $payment_method_slug))
462
-        );
463
-        return $count_updated;
464
-    }
465
-
466
-
467
-
468
-    /**
469
-     * initializes payment method access caps via EE_Capabilities::init_role_caps()
470
-     * upon EE_Payment_Method_Manager construction
471
-     *
472
-     * @throws EE_Error
473
-     * @throws DomainException
474
-     */
475
-    protected function initializePaymentMethodCaps()
476
-    {
477
-        // don't do this twice
478
-        if ($this->payment_method_caps_initialized) {
479
-            return;
480
-        }
481
-        EE_Capabilities::instance()->addCaps(
482
-            $this->getPaymentMethodCaps()
483
-        );
484
-        $this->payment_method_caps_initialized = true;
485
-    }
486
-
487
-
488
-
489
-    /**
490
-     * array  of dynamic payment method access caps.
491
-     * at the time of writing, october 20 2014, these are the caps added:
492
-     *  ee_payment_method_admin_only
493
-     *  ee_payment_method_aim
494
-     *  ee_payment_method_bank
495
-     *  ee_payment_method_check
496
-     *  ee_payment_method_invoice
497
-     *  ee_payment_method_mijireh
498
-     *  ee_payment_method_paypal_pro
499
-     *  ee_payment_method_paypal_standard
500
-     * Any other payment methods added to core or via addons will also get
501
-     * their related capability automatically added too, so long as they are
502
-     * registered properly using EE_Register_Payment_Method::register()
503
-     *
504
-     * @return array
505
-     * @throws DomainException
506
-     */
507
-    protected function getPaymentMethodCaps()
508
-    {
509
-        $caps = array();
510
-        foreach ($this->payment_method_type_names() as $payment_method_name) {
511
-            $caps = $this->addPaymentMethodCap($payment_method_name,$caps);
512
-        }
513
-        return $caps;
514
-    }
515
-
516
-
517
-
518
-    /**
519
-     * @param string $payment_method_name
520
-     * @param array  $payment_method_caps
521
-     * @param string $role
522
-     * @return array
523
-     * @throws DomainException
524
-     */
525
-    public function addPaymentMethodCap($payment_method_name, array $payment_method_caps, $role = 'administrator')
526
-    {
527
-        if (empty($payment_method_name)) {
528
-            throw new DomainException(
529
-                esc_html__(
530
-                    'The name of a payment method must be specified to add capabilities.',
531
-                    'event_espresso'
532
-                )
533
-            );
534
-        }
535
-        if (empty($role)) {
536
-            throw new DomainException(
537
-                sprintf(
538
-                    esc_html__(
539
-                        'No role was supplied while trying to add capabilities for the %1$s payment method.',
540
-                        'event_espresso'
541
-                    ),
542
-                    $payment_method_name
543
-                )
544
-            );
545
-        }
546
-        if(! isset($payment_method_caps[$role])) {
547
-            $payment_method_caps[$role] = array();
548
-        }
549
-        $payment_method_caps[$role][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX
550
-                                                  . strtolower($payment_method_name);
551
-        return $payment_method_caps;
552
-    }
553
-
554
-
555
-
556
-    /**
557
-     * callback for FHEE__EE_Capabilities__init_role_caps__caps_map filter
558
-     * to add dynamic payment method access caps when capabilities are reset
559
-     * (or if that filter is called and PM caps are not already set)
560
-     *
561
-     * @param array $caps capabilities being filtered
562
-     * @param bool  $reset
563
-     * @return array
564
-     * @throws DomainException
565
-     */
566
-    public function addPaymentMethodCapsDuringReset(array $caps, $reset = false)
567
-    {
568
-        if ($reset || ! $this->payment_method_caps_initialized) {
569
-            $this->payment_method_caps_initialized = true;
570
-            $caps = array_merge_recursive($caps, $this->getPaymentMethodCaps());
571
-        }
572
-        return $caps;
573
-    }
574
-
575
-
576
-
577
-    /**
578
-     * @deprecated 4.9.42
579
-     * @param $caps
580
-     * @return mixed
581
-     */
582
-    public function add_payment_method_caps($caps)
583
-    {
584
-        return $caps;
585
-    }
22
+	/**
23
+	 * prefix added to all payment method capabilities names
24
+	 */
25
+	const   CAPABILITIES_PREFIX= 'ee_payment_method_';
26
+
27
+	/**
28
+	 * @var EE_Payment_Method_Manager $_instance
29
+	 */
30
+	private static $_instance;
31
+
32
+	/**
33
+	 * @var boolean
34
+	 */
35
+	protected $payment_method_caps_initialized = false;
36
+
37
+	/**
38
+	 * @var array keys are class names without 'EE_PMT_', values are their filepaths
39
+	 */
40
+	protected $_payment_method_types = array();
41
+
42
+	/**
43
+	 * @var EE_PMT_Base[]
44
+	 */
45
+	protected $payment_method_objects = array();
46
+
47
+
48
+
49
+	/**
50
+	 * EE_Payment_Method_Manager constructor.
51
+	 *
52
+	 * @throws EE_Error
53
+	 * @throws DomainException
54
+	 */
55
+	public function __construct()
56
+	{
57
+		// if in admin lets ensure caps are set.
58
+		if (is_admin()) {
59
+			$this->_register_payment_methods();
60
+			// set them immediately
61
+			$this->initializePaymentMethodCaps();
62
+			// plus any time they get reset
63
+			add_filter(
64
+				'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
65
+				array($this, 'addPaymentMethodCapsDuringReset')
66
+			);
67
+		}
68
+	}
69
+
70
+
71
+
72
+	/**
73
+	 * @singleton method used to instantiate class object
74
+	 * @return EE_Payment_Method_Manager instance
75
+	 * @throws DomainException
76
+	 * @throws EE_Error
77
+	 */
78
+	public static function instance()
79
+	{
80
+		// check if class object is instantiated, and instantiated properly
81
+		if (! self::$_instance instanceof EE_Payment_Method_Manager) {
82
+			EE_Registry::instance()->load_lib('PMT_Base');
83
+			self::$_instance = new self();
84
+		}
85
+		return self::$_instance;
86
+	}
87
+
88
+
89
+
90
+	/**
91
+	 * Resets the instance and returns a new one
92
+	 *
93
+	 * @return EE_Payment_Method_Manager
94
+	 * @throws DomainException
95
+	 * @throws EE_Error
96
+	 */
97
+	public static function reset()
98
+	{
99
+		self::$_instance = null;
100
+		return self::instance();
101
+	}
102
+
103
+
104
+
105
+	/**
106
+	 * If necessary, re-register payment methods
107
+	 *
108
+	 * @param boolean $force_recheck whether to recheck for payment method types,
109
+	 *                               or just re-use the PMTs we found last time we checked during this request (if
110
+	 *                               we have not yet checked during this request, then we need to check anyways)
111
+	 */
112
+	public function maybe_register_payment_methods($force_recheck = false)
113
+	{
114
+		if (! $this->_payment_method_types || $force_recheck) {
115
+			$this->_register_payment_methods();
116
+		}
117
+	}
118
+
119
+
120
+
121
+	/**
122
+	 * register_payment_methods
123
+	 *
124
+	 * @return array
125
+	 */
126
+	protected function _register_payment_methods()
127
+	{
128
+		// grab list of installed modules
129
+		$pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
130
+		// filter list of modules to register
131
+		$pm_to_register = apply_filters(
132
+			'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
133
+			$pm_to_register
134
+		);
135
+		// remove any duplicates if that should happen for some reason
136
+		$pm_to_register = array_unique($pm_to_register);
137
+		// loop through folders
138
+		foreach ($pm_to_register as $pm_path) {
139
+			$this->register_payment_method($pm_path);
140
+		}
141
+		do_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods');
142
+		// filter list of installed modules
143
+		//keep them organized alphabetically by the payment method type's name
144
+		ksort($this->_payment_method_types);
145
+		return apply_filters(
146
+			'FHEE__EE_Payment_Method_Manager__register_payment_methods__installed_payment_methods',
147
+			$this->_payment_method_types
148
+		);
149
+	}
150
+
151
+
152
+
153
+	/**
154
+	 * register_payment_method- makes core aware of this payment method
155
+	 *
156
+	 * @param string $payment_method_path - full path up to and including payment method folder
157
+	 * @return boolean
158
+	 */
159
+	public function register_payment_method($payment_method_path = '')
160
+	{
161
+		do_action('AHEE__EE_Payment_Method_Manager__register_payment_method__begin', $payment_method_path);
162
+		$module_ext = '.pm.php';
163
+		// make all separators match
164
+		$payment_method_path = rtrim(str_replace('/\\', DS, $payment_method_path), DS);
165
+		// grab and sanitize module name
166
+		$module_dir = basename($payment_method_path);
167
+		// create class name from module directory name
168
+		$module = str_replace(array('_', ' '), array(' ', '_'), $module_dir);
169
+		// add class prefix
170
+		$module_class = 'EE_PMT_' . $module;
171
+		// does the module exist ?
172
+		if (! is_readable($payment_method_path . DS . $module_class . $module_ext)) {
173
+			$msg = sprintf(
174
+				esc_html__(
175
+					'The requested %s payment method file could not be found or is not readable due to file permissions.',
176
+					'event_espresso'
177
+				), $module
178
+			);
179
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
180
+			return false;
181
+		}
182
+		// load the module class file
183
+		require_once($payment_method_path . DS . $module_class . $module_ext);
184
+		// verify that class exists
185
+		if (! class_exists($module_class)) {
186
+			$msg = sprintf(
187
+				esc_html__('The requested %s module class does not exist.', 'event_espresso'),
188
+				$module_class
189
+			);
190
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
191
+			return false;
192
+		}
193
+		// add to array of registered modules
194
+		$this->_payment_method_types[$module] = $payment_method_path . DS . $module_class . $module_ext;
195
+		return true;
196
+	}
197
+
198
+
199
+
200
+	/**
201
+	 * Checks if a payment method has been registered, and if so includes it
202
+	 *
203
+	 * @param string  $payment_method_name like 'PayPal_Pro', (ie class name without the prefix 'EEPM_')
204
+	 * @param boolean $force_recheck       whether to force re-checking for new payment method types
205
+	 * @return boolean
206
+	 */
207
+	public function payment_method_type_exists($payment_method_name, $force_recheck = false)
208
+	{
209
+		if (
210
+			$force_recheck
211
+			|| ! is_array($this->_payment_method_types)
212
+			|| ! isset($this->_payment_method_types[$payment_method_name])
213
+		) {
214
+			$this->maybe_register_payment_methods($force_recheck);
215
+		}
216
+		if (isset($this->_payment_method_types[$payment_method_name])) {
217
+			require_once($this->_payment_method_types[$payment_method_name]);
218
+			return true;
219
+		}
220
+		return false;
221
+	}
222
+
223
+
224
+
225
+	/**
226
+	 * Returns all the class names of the various payment method types
227
+	 *
228
+	 * @param boolean $with_prefixes TRUE: get payment method type class names; false just their 'names'
229
+	 *                               (what you'd find in wp_esp_payment_method.PMD_type)
230
+	 * @param boolean $force_recheck whether to force re-checking for new payment method types
231
+	 * @return array
232
+	 */
233
+	public function payment_method_type_names($with_prefixes = false, $force_recheck = false)
234
+	{
235
+		$this->maybe_register_payment_methods($force_recheck);
236
+		if ($with_prefixes) {
237
+			$classnames = array_keys($this->_payment_method_types);
238
+			$payment_methods = array();
239
+			foreach ($classnames as $classname) {
240
+				$payment_methods[] = $this->payment_method_class_from_type($classname);
241
+			}
242
+			return $payment_methods;
243
+		}
244
+		return array_keys($this->_payment_method_types);
245
+	}
246
+
247
+
248
+
249
+	/**
250
+	 * Gets an object of each payment method type, none of which are bound to a
251
+	 * payment method instance
252
+	 *
253
+	 * @param boolean $force_recheck whether to force re-checking for new payment method types
254
+	 * @return EE_PMT_Base[]
255
+	 */
256
+	public function payment_method_types($force_recheck = false)
257
+	{
258
+		if ($force_recheck || empty($this->payment_method_objects)) {
259
+			$this->maybe_register_payment_methods($force_recheck);
260
+			foreach ($this->payment_method_type_names(true) as $classname) {
261
+				if (! isset($this->payment_method_objects[$classname])) {
262
+					$this->payment_method_objects[$classname] = new $classname;
263
+				}
264
+			}
265
+		}
266
+		return $this->payment_method_objects;
267
+	}
268
+
269
+
270
+
271
+	/**
272
+	 * Changes the payment method's class name into the payment method type's name
273
+	 * (as used on the payment method's table's PMD_type field)
274
+	 *
275
+	 * @param string $classname
276
+	 * @return string
277
+	 */
278
+	public function payment_method_type_sans_class_prefix($classname)
279
+	{
280
+		return str_replace('EE_PMT_', '', $classname);
281
+	}
282
+
283
+
284
+
285
+	/**
286
+	 * Does the opposite of payment-method_type_sans_prefix
287
+	 *
288
+	 * @param string $type
289
+	 * @return string
290
+	 */
291
+	public function payment_method_class_from_type($type)
292
+	{
293
+		return 'EE_PMT_' . $type;
294
+	}
295
+
296
+
297
+
298
+	/**
299
+	 * Activates a payment method of the given type.
300
+	 *
301
+	 * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
302
+	 * @return EE_Payment_Method
303
+	 * @throws EE_Error
304
+	 */
305
+	public function activate_a_payment_method_of_type($payment_method_type)
306
+	{
307
+		$this->maybe_register_payment_methods();
308
+		$payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
309
+		if (! $payment_method instanceof EE_Payment_Method) {
310
+			$pm_type_class = $this->payment_method_class_from_type($payment_method_type);
311
+			if (class_exists($pm_type_class)) {
312
+				/** @var $pm_type_obj EE_PMT_Base */
313
+				$pm_type_obj = new $pm_type_class;
314
+				$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
315
+				if (! $payment_method) {
316
+					$payment_method = $this->create_payment_method_of_type($pm_type_obj);
317
+				}
318
+				$payment_method->set_type($payment_method_type);
319
+				$this->initialize_payment_method($payment_method);
320
+			} else {
321
+				throw new EE_Error(
322
+					sprintf(
323
+						esc_html__(
324
+							'There is no payment method of type %1$s, so it could not be activated',
325
+							'event_espresso'
326
+						),
327
+						$pm_type_class
328
+					)
329
+				);
330
+			}
331
+		}
332
+		$payment_method->set_active();
333
+		$payment_method->save();
334
+		if ($payment_method->type() === 'Invoice') {
335
+			/** @type EE_Message_Resource_Manager $message_resource_manager */
336
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
337
+			$message_resource_manager->ensure_message_type_is_active('invoice', 'html');
338
+			$message_resource_manager->ensure_messenger_is_active('pdf');
339
+			EE_Error::add_persistent_admin_notice(
340
+				'invoice_pm_requirements_notice',
341
+				sprintf(
342
+					esc_html__(
343
+						'The Invoice payment method has been activated. It requires the invoice message type, html messenger, and pdf messenger be activated as well for the %1$smessages system%2$s, so it has been automatically verified that they are also active.',
344
+						'event_espresso'
345
+					),
346
+					'<a href="' . admin_url('admin.php?page=espresso_messages') . '">',
347
+					'</a>'
348
+				),
349
+				true
350
+			);
351
+		}
352
+		return $payment_method;
353
+	}
354
+
355
+
356
+
357
+	/**
358
+	 * Creates a payment method of the specified type. Does not save it.
359
+	 *
360
+	 * @global WP_User    $current_user
361
+	 * @param EE_PMT_Base $pm_type_obj
362
+	 * @return EE_Payment_Method
363
+	 * @throws EE_Error
364
+	 */
365
+	public function create_payment_method_of_type($pm_type_obj)
366
+	{
367
+		global $current_user;
368
+		$payment_method = EE_Payment_Method::new_instance(
369
+			array(
370
+				'PMD_type'       => $pm_type_obj->system_name(),
371
+				'PMD_name'       => $pm_type_obj->pretty_name(),
372
+				'PMD_admin_name' => $pm_type_obj->pretty_name(),
373
+				'PMD_slug'       => $pm_type_obj->system_name(),//automatically converted to slug
374
+				'PMD_wp_user'    => $current_user->ID,
375
+				'PMD_order'      => EEM_Payment_Method::instance()->count(
376
+						array(array('PMD_type' => array('!=', 'Admin_Only')))
377
+					) * 10,
378
+			)
379
+		);
380
+		return $payment_method;
381
+	}
382
+
383
+
384
+
385
+	/**
386
+	 * Sets the initial payment method properties (including extra meta)
387
+	 *
388
+	 * @param EE_Payment_Method $payment_method
389
+	 * @return EE_Payment_Method
390
+	 * @throws EE_Error
391
+	 */
392
+	public function initialize_payment_method($payment_method)
393
+	{
394
+		$pm_type_obj = $payment_method->type_obj();
395
+		$payment_method->set_description($pm_type_obj->default_description());
396
+		if (! $payment_method->button_url()) {
397
+			$payment_method->set_button_url($pm_type_obj->default_button_url());
398
+		}
399
+		//now add setup its default extra meta properties
400
+		$extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
401
+		if (! empty($extra_metas)) {
402
+			//verify the payment method has an ID before adding extra meta
403
+			if (! $payment_method->ID()) {
404
+				$payment_method->save();
405
+			}
406
+			foreach ($extra_metas as $meta_name => $input) {
407
+				$payment_method->update_extra_meta($meta_name, $input->raw_value());
408
+			}
409
+		}
410
+		return $payment_method;
411
+	}
412
+
413
+
414
+
415
+	/**
416
+	 * Makes sure the payment method is related to the specified payment method
417
+	 *
418
+	 * @deprecated in 4.9.40 because the currency payment method table is being deprecated
419
+	 * @param EE_Payment_Method $payment_method
420
+	 * @return EE_Payment_Method
421
+	 * @throws EE_Error
422
+	 */
423
+	public function set_usable_currencies_on_payment_method($payment_method)
424
+	{
425
+		EE_Error::doing_it_wrong(
426
+			'EE_Payment_Method_Manager::set_usable_currencies_on_payment_method',
427
+			esc_html__(
428
+				'We no longer define what currencies are usable by payment methods. Its not used nor efficient.',
429
+				'event_espresso'
430
+			),
431
+			'4.9.40'
432
+		);
433
+		return $payment_method;
434
+	}
435
+
436
+
437
+
438
+	/**
439
+	 * Deactivates a payment method of the given payment method slug.
440
+	 *
441
+	 * @param string $payment_method_slug The slug for the payment method to deactivate.
442
+	 * @return int count of rows updated.
443
+	 * @throws EE_Error
444
+	 */
445
+	public function deactivate_payment_method($payment_method_slug)
446
+	{
447
+		EE_Log::instance()->log(
448
+			__FILE__,
449
+			__FUNCTION__,
450
+			sprintf(
451
+				esc_html__(
452
+					'Payment method with slug %1$s is being deactivated by site admin',
453
+					'event_espresso'
454
+				),
455
+				$payment_method_slug
456
+			),
457
+			'payment_method_change'
458
+		);
459
+		$count_updated = EEM_Payment_Method::instance()->update(
460
+			array('PMD_scope' => array()),
461
+			array(array('PMD_slug' => $payment_method_slug))
462
+		);
463
+		return $count_updated;
464
+	}
465
+
466
+
467
+
468
+	/**
469
+	 * initializes payment method access caps via EE_Capabilities::init_role_caps()
470
+	 * upon EE_Payment_Method_Manager construction
471
+	 *
472
+	 * @throws EE_Error
473
+	 * @throws DomainException
474
+	 */
475
+	protected function initializePaymentMethodCaps()
476
+	{
477
+		// don't do this twice
478
+		if ($this->payment_method_caps_initialized) {
479
+			return;
480
+		}
481
+		EE_Capabilities::instance()->addCaps(
482
+			$this->getPaymentMethodCaps()
483
+		);
484
+		$this->payment_method_caps_initialized = true;
485
+	}
486
+
487
+
488
+
489
+	/**
490
+	 * array  of dynamic payment method access caps.
491
+	 * at the time of writing, october 20 2014, these are the caps added:
492
+	 *  ee_payment_method_admin_only
493
+	 *  ee_payment_method_aim
494
+	 *  ee_payment_method_bank
495
+	 *  ee_payment_method_check
496
+	 *  ee_payment_method_invoice
497
+	 *  ee_payment_method_mijireh
498
+	 *  ee_payment_method_paypal_pro
499
+	 *  ee_payment_method_paypal_standard
500
+	 * Any other payment methods added to core or via addons will also get
501
+	 * their related capability automatically added too, so long as they are
502
+	 * registered properly using EE_Register_Payment_Method::register()
503
+	 *
504
+	 * @return array
505
+	 * @throws DomainException
506
+	 */
507
+	protected function getPaymentMethodCaps()
508
+	{
509
+		$caps = array();
510
+		foreach ($this->payment_method_type_names() as $payment_method_name) {
511
+			$caps = $this->addPaymentMethodCap($payment_method_name,$caps);
512
+		}
513
+		return $caps;
514
+	}
515
+
516
+
517
+
518
+	/**
519
+	 * @param string $payment_method_name
520
+	 * @param array  $payment_method_caps
521
+	 * @param string $role
522
+	 * @return array
523
+	 * @throws DomainException
524
+	 */
525
+	public function addPaymentMethodCap($payment_method_name, array $payment_method_caps, $role = 'administrator')
526
+	{
527
+		if (empty($payment_method_name)) {
528
+			throw new DomainException(
529
+				esc_html__(
530
+					'The name of a payment method must be specified to add capabilities.',
531
+					'event_espresso'
532
+				)
533
+			);
534
+		}
535
+		if (empty($role)) {
536
+			throw new DomainException(
537
+				sprintf(
538
+					esc_html__(
539
+						'No role was supplied while trying to add capabilities for the %1$s payment method.',
540
+						'event_espresso'
541
+					),
542
+					$payment_method_name
543
+				)
544
+			);
545
+		}
546
+		if(! isset($payment_method_caps[$role])) {
547
+			$payment_method_caps[$role] = array();
548
+		}
549
+		$payment_method_caps[$role][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX
550
+												  . strtolower($payment_method_name);
551
+		return $payment_method_caps;
552
+	}
553
+
554
+
555
+
556
+	/**
557
+	 * callback for FHEE__EE_Capabilities__init_role_caps__caps_map filter
558
+	 * to add dynamic payment method access caps when capabilities are reset
559
+	 * (or if that filter is called and PM caps are not already set)
560
+	 *
561
+	 * @param array $caps capabilities being filtered
562
+	 * @param bool  $reset
563
+	 * @return array
564
+	 * @throws DomainException
565
+	 */
566
+	public function addPaymentMethodCapsDuringReset(array $caps, $reset = false)
567
+	{
568
+		if ($reset || ! $this->payment_method_caps_initialized) {
569
+			$this->payment_method_caps_initialized = true;
570
+			$caps = array_merge_recursive($caps, $this->getPaymentMethodCaps());
571
+		}
572
+		return $caps;
573
+	}
574
+
575
+
576
+
577
+	/**
578
+	 * @deprecated 4.9.42
579
+	 * @param $caps
580
+	 * @return mixed
581
+	 */
582
+	public function add_payment_method_caps($caps)
583
+	{
584
+		return $caps;
585
+	}
586 586
 
587 587
 
588 588
 
Please login to merge, or discard this patch.
core/libraries/plugin_api/EE_Register_Payment_Method.lib.php 1 patch
Indentation   +143 added lines, -143 removed lines patch added patch discarded remove patch
@@ -18,149 +18,149 @@
 block discarded – undo
18 18
 class EE_Register_Payment_Method implements EEI_Plugin_API
19 19
 {
20 20
 
21
-    /**
22
-     * Holds values for registered payment methods
23
-     *
24
-     * @var array
25
-     */
26
-    protected static $_settings = array();
27
-
28
-
29
-
30
-    /**
31
-     * Method for registering new EE_PMT_Base children
32
-     *
33
-     * @since    4.5.0
34
-     * @param string  $payment_method_id    a unique identifier for this set of modules Required.
35
-     * @param  array  $setup_args           an array of arguments provided for registering modules Required.{
36
-     * @type string[] $payment_method_paths each element is the folder containing the EE_PMT_Base child class
37
-     *                                      (eg, 'public_html/wp-content/plugins/my_plugin/Payomatic/' which contains
38
-     *                                      the files EE_PMT_Payomatic.pm.php)
39
-     *                                      }
40
-     * @throws EE_Error
41
-     * @type array payment_method_paths    an array of full server paths to folders containing any EE_PMT_Base
42
-     *                                      children, or to the EED_Module files themselves
43
-     * @return void
44
-     * @throws DomainException
45
-     */
46
-    public static function register($payment_method_id = null, $setup_args = array())
47
-    {
48
-        //required fields MUST be present, so let's make sure they are.
49
-        if (empty($payment_method_id) || ! is_array($setup_args) || empty($setup_args['payment_method_paths'])) {
50
-            throw new EE_Error(
51
-                esc_html__(
52
-                    'In order to register Payment Methods with EE_Register_Payment_Method::register(), you must include a "payment_method_id" (a unique identifier for this set of modules), and an array containing the following keys: "payment_method_paths" (an array of full server paths to folders that contain modules, or to the module files themselves)',
53
-                    'event_espresso'
54
-                )
55
-            );
56
-        }
57
-        //make sure we don't register twice
58
-        if (isset(self::$_settings[$payment_method_id])) {
59
-            return;
60
-        }
61
-        //make sure this was called in the right place!
62
-        if (
63
-            ! did_action('AHEE__EE_System__load_espresso_addons')
64
-            || did_action('AHEE__EE_System__register_shortcodes_modules_and_widgets')
65
-        ) {
66
-            EE_Error::doing_it_wrong(
67
-                __METHOD__,
68
-                esc_html__(
69
-                    'An attempt to register modules has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__register_shortcodes_modules_and_widgets" hook to register modules.',
70
-                    'event_espresso'
71
-                ),
72
-                '4.3.0'
73
-            );
74
-        }
75
-        //setup $_settings array from incoming values.
76
-        self::$_settings[$payment_method_id] = array(
77
-            // array of full server paths to any EE_PMT_Base children used
78
-            'payment_method_paths' => isset($setup_args['payment_method_paths'])
79
-                ? (array)$setup_args['payment_method_paths']
80
-                : array(),
81
-        );
82
-        // add to list of modules to be registered
83
-        add_filter(
84
-            'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
85
-            array('EE_Register_Payment_Method', 'add_payment_methods')
86
-        );
87
-        // If EE_Payment_Method_Manager::register_payment_methods has already been called,
88
-        // then we need to add our caps for this payment method manually
89
-        if (did_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods')) {
90
-            // register payment methods directly
91
-            foreach (self::$_settings[$payment_method_id]['payment_method_paths'] as $payment_method_path) {
92
-                EE_Payment_Method_Manager::instance()->register_payment_method($payment_method_path);
93
-            }
94
-            EE_Capabilities::instance()->addCaps(
95
-                self::getPaymentMethodCapabilities(self::$_settings[$payment_method_id])
96
-            );
97
-        }
98
-    }
99
-
100
-
101
-
102
-    /**
103
-     * Filters the list of payment methods to add ours.
104
-     * and they're just full filepaths to FOLDERS containing a payment method class file. Eg.
105
-     *
106
-     * @param array $payment_method_folders array of paths to all payment methods that require registering
107
-     * @return array
108
-     */
109
-    public static function add_payment_methods($payment_method_folders)
110
-    {
111
-        foreach (self::$_settings as $settings) {
112
-            foreach ($settings['payment_method_paths'] as $payment_method_path) {
113
-                $payment_method_folders[] = $payment_method_path;
114
-            }
115
-        }
116
-        return $payment_method_folders;
117
-    }
118
-
119
-
120
-
121
-    /**
122
-     * This deregisters a module that was previously registered with a specific $module_id.
123
-     *
124
-     * @since    4.3.0
125
-     *
126
-     * @param string $module_id the name for the module that was previously registered
127
-     * @return void
128
-     * @throws DomainException
129
-     * @throws EE_Error
130
-     */
131
-    public static function deregister($module_id = null)
132
-    {
133
-        if (isset(self::$_settings[$module_id])) {
134
-            EE_Capabilities::instance()->removeCaps(
135
-                self::getPaymentMethodCapabilities(self::$_settings[$module_id])
136
-            );
137
-            unset(self::$_settings[$module_id]);
138
-        }
139
-    }
140
-
141
-
142
-
143
-    /**
144
-     * returns an array of the caps that get added when a Payment Method is registered
145
-     *
146
-     * @param array $settings
147
-     * @return array
148
-     * @throws DomainException
149
-     * @throws EE_Error
150
-     */
151
-    private static function getPaymentMethodCapabilities(array $settings)
152
-    {
153
-        $payment_method_caps = array('administrator' => array());
154
-        if (isset($settings['payment_method_paths'])) {
155
-            foreach ($settings['payment_method_paths'] as $payment_method_path) {
156
-                $payment_method_caps = EE_Payment_Method_Manager::instance()->addPaymentMethodCap(
157
-                    strtolower(basename($payment_method_path)),
158
-                    $payment_method_caps
159
-                );
160
-            }
161
-        }
162
-        return $payment_method_caps;
163
-    }
21
+	/**
22
+	 * Holds values for registered payment methods
23
+	 *
24
+	 * @var array
25
+	 */
26
+	protected static $_settings = array();
27
+
28
+
29
+
30
+	/**
31
+	 * Method for registering new EE_PMT_Base children
32
+	 *
33
+	 * @since    4.5.0
34
+	 * @param string  $payment_method_id    a unique identifier for this set of modules Required.
35
+	 * @param  array  $setup_args           an array of arguments provided for registering modules Required.{
36
+	 * @type string[] $payment_method_paths each element is the folder containing the EE_PMT_Base child class
37
+	 *                                      (eg, 'public_html/wp-content/plugins/my_plugin/Payomatic/' which contains
38
+	 *                                      the files EE_PMT_Payomatic.pm.php)
39
+	 *                                      }
40
+	 * @throws EE_Error
41
+	 * @type array payment_method_paths    an array of full server paths to folders containing any EE_PMT_Base
42
+	 *                                      children, or to the EED_Module files themselves
43
+	 * @return void
44
+	 * @throws DomainException
45
+	 */
46
+	public static function register($payment_method_id = null, $setup_args = array())
47
+	{
48
+		//required fields MUST be present, so let's make sure they are.
49
+		if (empty($payment_method_id) || ! is_array($setup_args) || empty($setup_args['payment_method_paths'])) {
50
+			throw new EE_Error(
51
+				esc_html__(
52
+					'In order to register Payment Methods with EE_Register_Payment_Method::register(), you must include a "payment_method_id" (a unique identifier for this set of modules), and an array containing the following keys: "payment_method_paths" (an array of full server paths to folders that contain modules, or to the module files themselves)',
53
+					'event_espresso'
54
+				)
55
+			);
56
+		}
57
+		//make sure we don't register twice
58
+		if (isset(self::$_settings[$payment_method_id])) {
59
+			return;
60
+		}
61
+		//make sure this was called in the right place!
62
+		if (
63
+			! did_action('AHEE__EE_System__load_espresso_addons')
64
+			|| did_action('AHEE__EE_System__register_shortcodes_modules_and_widgets')
65
+		) {
66
+			EE_Error::doing_it_wrong(
67
+				__METHOD__,
68
+				esc_html__(
69
+					'An attempt to register modules has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__register_shortcodes_modules_and_widgets" hook to register modules.',
70
+					'event_espresso'
71
+				),
72
+				'4.3.0'
73
+			);
74
+		}
75
+		//setup $_settings array from incoming values.
76
+		self::$_settings[$payment_method_id] = array(
77
+			// array of full server paths to any EE_PMT_Base children used
78
+			'payment_method_paths' => isset($setup_args['payment_method_paths'])
79
+				? (array)$setup_args['payment_method_paths']
80
+				: array(),
81
+		);
82
+		// add to list of modules to be registered
83
+		add_filter(
84
+			'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
85
+			array('EE_Register_Payment_Method', 'add_payment_methods')
86
+		);
87
+		// If EE_Payment_Method_Manager::register_payment_methods has already been called,
88
+		// then we need to add our caps for this payment method manually
89
+		if (did_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods')) {
90
+			// register payment methods directly
91
+			foreach (self::$_settings[$payment_method_id]['payment_method_paths'] as $payment_method_path) {
92
+				EE_Payment_Method_Manager::instance()->register_payment_method($payment_method_path);
93
+			}
94
+			EE_Capabilities::instance()->addCaps(
95
+				self::getPaymentMethodCapabilities(self::$_settings[$payment_method_id])
96
+			);
97
+		}
98
+	}
99
+
100
+
101
+
102
+	/**
103
+	 * Filters the list of payment methods to add ours.
104
+	 * and they're just full filepaths to FOLDERS containing a payment method class file. Eg.
105
+	 *
106
+	 * @param array $payment_method_folders array of paths to all payment methods that require registering
107
+	 * @return array
108
+	 */
109
+	public static function add_payment_methods($payment_method_folders)
110
+	{
111
+		foreach (self::$_settings as $settings) {
112
+			foreach ($settings['payment_method_paths'] as $payment_method_path) {
113
+				$payment_method_folders[] = $payment_method_path;
114
+			}
115
+		}
116
+		return $payment_method_folders;
117
+	}
118
+
119
+
120
+
121
+	/**
122
+	 * This deregisters a module that was previously registered with a specific $module_id.
123
+	 *
124
+	 * @since    4.3.0
125
+	 *
126
+	 * @param string $module_id the name for the module that was previously registered
127
+	 * @return void
128
+	 * @throws DomainException
129
+	 * @throws EE_Error
130
+	 */
131
+	public static function deregister($module_id = null)
132
+	{
133
+		if (isset(self::$_settings[$module_id])) {
134
+			EE_Capabilities::instance()->removeCaps(
135
+				self::getPaymentMethodCapabilities(self::$_settings[$module_id])
136
+			);
137
+			unset(self::$_settings[$module_id]);
138
+		}
139
+	}
140
+
141
+
142
+
143
+	/**
144
+	 * returns an array of the caps that get added when a Payment Method is registered
145
+	 *
146
+	 * @param array $settings
147
+	 * @return array
148
+	 * @throws DomainException
149
+	 * @throws EE_Error
150
+	 */
151
+	private static function getPaymentMethodCapabilities(array $settings)
152
+	{
153
+		$payment_method_caps = array('administrator' => array());
154
+		if (isset($settings['payment_method_paths'])) {
155
+			foreach ($settings['payment_method_paths'] as $payment_method_path) {
156
+				$payment_method_caps = EE_Payment_Method_Manager::instance()->addPaymentMethodCap(
157
+					strtolower(basename($payment_method_path)),
158
+					$payment_method_caps
159
+				);
160
+			}
161
+		}
162
+		return $payment_method_caps;
163
+	}
164 164
 
165 165
 }
166 166
 // End of file EE_Register_Payment_Method.lib.php
Please login to merge, or discard this patch.
core/EE_Registry.core.php 3 patches
Doc Comments   +1 added lines patch added patch discarded remove patch
@@ -272,6 +272,7 @@
 block discarded – undo
272 272
 
273 273
     /**
274 274
      * @param mixed string | EED_Module $module
275
+     * @param string $module
275 276
      * @throws EE_Error
276 277
      * @throws ReflectionException
277 278
      */
Please login to merge, or discard this patch.
Indentation   +1495 added lines, -1495 removed lines patch added patch discarded remove patch
@@ -22,1501 +22,1501 @@
 block discarded – undo
22 22
 class EE_Registry implements ResettableInterface
23 23
 {
24 24
 
25
-    /**
26
-     * @var EE_Registry $_instance
27
-     */
28
-    private static $_instance;
29
-
30
-    /**
31
-     * @var EE_Dependency_Map $_dependency_map
32
-     */
33
-    protected $_dependency_map;
34
-
35
-    /**
36
-     * @var array $_class_abbreviations
37
-     */
38
-    protected $_class_abbreviations = array();
39
-
40
-    /**
41
-     * @var CommandBusInterface $BUS
42
-     */
43
-    public $BUS;
44
-
45
-    /**
46
-     * @var EE_Cart $CART
47
-     */
48
-    public $CART;
49
-
50
-    /**
51
-     * @var EE_Config $CFG
52
-     */
53
-    public $CFG;
54
-
55
-    /**
56
-     * @var EE_Network_Config $NET_CFG
57
-     */
58
-    public $NET_CFG;
59
-
60
-    /**
61
-     * StdClass object for storing library classes in
62
-     *
63
-     * @var StdClass $LIB
64
-     */
65
-    public $LIB;
66
-
67
-    /**
68
-     * @var EE_Request_Handler $REQ
69
-     */
70
-    public $REQ;
71
-
72
-    /**
73
-     * @var EE_Session $SSN
74
-     */
75
-    public $SSN;
76
-
77
-    /**
78
-     * @since 4.5.0
79
-     * @var EE_Capabilities $CAP
80
-     */
81
-    public $CAP;
82
-
83
-    /**
84
-     * @since 4.9.0
85
-     * @var EE_Message_Resource_Manager $MRM
86
-     */
87
-    public $MRM;
88
-
89
-
90
-    /**
91
-     * @var Registry $AssetsRegistry
92
-     */
93
-    public $AssetsRegistry;
94
-
95
-    /**
96
-     * StdClass object for holding addons which have registered themselves to work with EE core
97
-     *
98
-     * @var EE_Addon[] $addons
99
-     */
100
-    public $addons;
101
-
102
-    /**
103
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
104
-     *
105
-     * @var EEM_Base[] $models
106
-     */
107
-    public $models = array();
108
-
109
-    /**
110
-     * @var EED_Module[] $modules
111
-     */
112
-    public $modules;
113
-
114
-    /**
115
-     * @var EES_Shortcode[] $shortcodes
116
-     */
117
-    public $shortcodes;
118
-
119
-    /**
120
-     * @var WP_Widget[] $widgets
121
-     */
122
-    public $widgets;
123
-
124
-    /**
125
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
126
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
127
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
128
-     * classnames (eg "EEM_Event")
129
-     *
130
-     * @var array $non_abstract_db_models
131
-     */
132
-    public $non_abstract_db_models = array();
133
-
134
-
135
-    /**
136
-     * internationalization for JS strings
137
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
138
-     *    in js file:  var translatedString = eei18n.string_key;
139
-     *
140
-     * @var array $i18n_js_strings
141
-     */
142
-    public static $i18n_js_strings = array();
143
-
144
-
145
-    /**
146
-     * $main_file - path to espresso.php
147
-     *
148
-     * @var array $main_file
149
-     */
150
-    public $main_file;
151
-
152
-    /**
153
-     * array of ReflectionClass objects where the key is the class name
154
-     *
155
-     * @var ReflectionClass[] $_reflectors
156
-     */
157
-    public $_reflectors;
158
-
159
-    /**
160
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
161
-     *
162
-     * @var boolean $_cache_on
163
-     */
164
-    protected $_cache_on = true;
165
-
166
-
167
-
168
-    /**
169
-     * @singleton method used to instantiate class object
170
-     * @param  EE_Dependency_Map $dependency_map
171
-     * @return EE_Registry instance
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidInterfaceException
174
-     * @throws InvalidDataTypeException
175
-     */
176
-    public static function instance(EE_Dependency_Map $dependency_map = null)
177
-    {
178
-        // check if class object is instantiated
179
-        if (! self::$_instance instanceof EE_Registry) {
180
-            self::$_instance = new self($dependency_map);
181
-        }
182
-        return self::$_instance;
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * protected constructor to prevent direct creation
189
-     *
190
-     * @Constructor
191
-     * @param  EE_Dependency_Map $dependency_map
192
-     * @throws InvalidDataTypeException
193
-     * @throws InvalidInterfaceException
194
-     * @throws InvalidArgumentException
195
-     */
196
-    protected function __construct(EE_Dependency_Map $dependency_map)
197
-    {
198
-        $this->_dependency_map = $dependency_map;
199
-        $this->LIB = new stdClass();
200
-        $this->addons = new stdClass();
201
-        $this->modules = new stdClass();
202
-        $this->shortcodes = new stdClass();
203
-        $this->widgets = new stdClass();
204
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
205
-    }
206
-
207
-
208
-
209
-    /**
210
-     * initialize
211
-     *
212
-     * @throws EE_Error
213
-     * @throws ReflectionException
214
-     */
215
-    public function initialize()
216
-    {
217
-        $this->_class_abbreviations = apply_filters(
218
-            'FHEE__EE_Registry____construct___class_abbreviations',
219
-            array(
220
-                'EE_Config'                                       => 'CFG',
221
-                'EE_Session'                                      => 'SSN',
222
-                'EE_Capabilities'                                 => 'CAP',
223
-                'EE_Cart'                                         => 'CART',
224
-                'EE_Network_Config'                               => 'NET_CFG',
225
-                'EE_Request_Handler'                              => 'REQ',
226
-                'EE_Message_Resource_Manager'                     => 'MRM',
227
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
228
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
229
-            )
230
-        );
231
-        $this->load_core('Base', array(), true);
232
-        // add our request and response objects to the cache
233
-        $request_loader = $this->_dependency_map->class_loader('EE_Request');
234
-        $this->_set_cached_class(
235
-            $request_loader(),
236
-            'EE_Request'
237
-        );
238
-        $response_loader = $this->_dependency_map->class_loader('EE_Response');
239
-        $this->_set_cached_class(
240
-            $response_loader(),
241
-            'EE_Response'
242
-        );
243
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
244
-    }
245
-
246
-
247
-
248
-    /**
249
-     * @return void
250
-     */
251
-    public function init()
252
-    {
253
-        // Get current page protocol
254
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
255
-        // Output admin-ajax.php URL with same protocol as current page
256
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
257
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
258
-    }
259
-
260
-
261
-
262
-    /**
263
-     * localize_i18n_js_strings
264
-     *
265
-     * @return string
266
-     */
267
-    public static function localize_i18n_js_strings()
268
-    {
269
-        $i18n_js_strings = (array)self::$i18n_js_strings;
270
-        foreach ($i18n_js_strings as $key => $value) {
271
-            if (is_scalar($value)) {
272
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
273
-            }
274
-        }
275
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
276
-    }
277
-
278
-
279
-
280
-    /**
281
-     * @param mixed string | EED_Module $module
282
-     * @throws EE_Error
283
-     * @throws ReflectionException
284
-     */
285
-    public function add_module($module)
286
-    {
287
-        if ($module instanceof EED_Module) {
288
-            $module_class = get_class($module);
289
-            $this->modules->{$module_class} = $module;
290
-        } else {
291
-            if (! class_exists('EE_Module_Request_Router')) {
292
-                $this->load_core('Module_Request_Router');
293
-            }
294
-            EE_Module_Request_Router::module_factory($module);
295
-        }
296
-    }
297
-
298
-
299
-
300
-    /**
301
-     * @param string $module_name
302
-     * @return mixed EED_Module | NULL
303
-     */
304
-    public function get_module($module_name = '')
305
-    {
306
-        return isset($this->modules->{$module_name})
307
-            ? $this->modules->{$module_name}
308
-            : null;
309
-    }
310
-
311
-
312
-
313
-    /**
314
-     * loads core classes - must be singletons
315
-     *
316
-     * @param string $class_name - simple class name ie: session
317
-     * @param mixed  $arguments
318
-     * @param bool   $load_only
319
-     * @return mixed
320
-     * @throws EE_Error
321
-     * @throws ReflectionException
322
-     */
323
-    public function load_core($class_name, $arguments = array(), $load_only = false)
324
-    {
325
-        $core_paths = apply_filters(
326
-            'FHEE__EE_Registry__load_core__core_paths',
327
-            array(
328
-                EE_CORE,
329
-                EE_ADMIN,
330
-                EE_CPTS,
331
-                EE_CORE . 'data_migration_scripts' . DS,
332
-                EE_CORE . 'capabilities' . DS,
333
-                EE_CORE . 'request_stack' . DS,
334
-                EE_CORE . 'middleware' . DS,
335
-            )
336
-        );
337
-        // retrieve instantiated class
338
-        return $this->_load(
339
-            $core_paths,
340
-            'EE_',
341
-            $class_name,
342
-            'core',
343
-            $arguments,
344
-            false,
345
-            true,
346
-            $load_only
347
-        );
348
-    }
349
-
350
-
351
-
352
-    /**
353
-     * loads service classes
354
-     *
355
-     * @param string $class_name - simple class name ie: session
356
-     * @param mixed  $arguments
357
-     * @param bool   $load_only
358
-     * @return mixed
359
-     * @throws EE_Error
360
-     * @throws ReflectionException
361
-     */
362
-    public function load_service($class_name, $arguments = array(), $load_only = false)
363
-    {
364
-        $service_paths = apply_filters(
365
-            'FHEE__EE_Registry__load_service__service_paths',
366
-            array(
367
-                EE_CORE . 'services' . DS,
368
-            )
369
-        );
370
-        // retrieve instantiated class
371
-        return $this->_load(
372
-            $service_paths,
373
-            'EE_',
374
-            $class_name,
375
-            'class',
376
-            $arguments,
377
-            false,
378
-            true,
379
-            $load_only
380
-        );
381
-    }
382
-
383
-
384
-
385
-    /**
386
-     * loads data_migration_scripts
387
-     *
388
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
389
-     * @param mixed  $arguments
390
-     * @return EE_Data_Migration_Script_Base|mixed
391
-     * @throws EE_Error
392
-     * @throws ReflectionException
393
-     */
394
-    public function load_dms($class_name, $arguments = array())
395
-    {
396
-        // retrieve instantiated class
397
-        return $this->_load(
398
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
399
-            'EE_DMS_',
400
-            $class_name,
401
-            'dms',
402
-            $arguments,
403
-            false,
404
-            false
405
-        );
406
-    }
407
-
408
-
409
-
410
-    /**
411
-     * loads object creating classes - must be singletons
412
-     *
413
-     * @param string $class_name - simple class name ie: attendee
414
-     * @param mixed  $arguments  - an array of arguments to pass to the class
415
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
416
-     *                           instantiate
417
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
418
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
419
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
420
-     *                           (default)
421
-     * @return EE_Base_Class | bool
422
-     * @throws EE_Error
423
-     * @throws ReflectionException
424
-     */
425
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
426
-    {
427
-        $paths = apply_filters(
428
-            'FHEE__EE_Registry__load_class__paths', array(
429
-            EE_CORE,
430
-            EE_CLASSES,
431
-            EE_BUSINESS,
432
-        )
433
-        );
434
-        // retrieve instantiated class
435
-        return $this->_load(
436
-            $paths,
437
-            'EE_',
438
-            $class_name,
439
-            'class',
440
-            $arguments,
441
-            $from_db,
442
-            $cache,
443
-            $load_only
444
-        );
445
-    }
446
-
447
-
448
-
449
-    /**
450
-     * loads helper classes - must be singletons
451
-     *
452
-     * @param string $class_name - simple class name ie: price
453
-     * @param mixed  $arguments
454
-     * @param bool   $load_only
455
-     * @return EEH_Base | bool
456
-     * @throws EE_Error
457
-     * @throws ReflectionException
458
-     */
459
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
460
-    {
461
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
462
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
463
-        // retrieve instantiated class
464
-        return $this->_load(
465
-            $helper_paths,
466
-            'EEH_',
467
-            $class_name,
468
-            'helper',
469
-            $arguments,
470
-            false,
471
-            true,
472
-            $load_only
473
-        );
474
-    }
475
-
476
-
477
-
478
-    /**
479
-     * loads core classes - must be singletons
480
-     *
481
-     * @param string $class_name - simple class name ie: session
482
-     * @param mixed  $arguments
483
-     * @param bool   $load_only
484
-     * @param bool   $cache      whether to cache the object or not.
485
-     * @return mixed
486
-     * @throws EE_Error
487
-     * @throws ReflectionException
488
-     */
489
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
490
-    {
491
-        $paths = array(
492
-            EE_LIBRARIES,
493
-            EE_LIBRARIES . 'messages' . DS,
494
-            EE_LIBRARIES . 'shortcodes' . DS,
495
-            EE_LIBRARIES . 'qtips' . DS,
496
-            EE_LIBRARIES . 'payment_methods' . DS,
497
-        );
498
-        // retrieve instantiated class
499
-        return $this->_load(
500
-            $paths,
501
-            'EE_',
502
-            $class_name,
503
-            'lib',
504
-            $arguments,
505
-            false,
506
-            $cache,
507
-            $load_only
508
-        );
509
-    }
510
-
511
-
512
-
513
-    /**
514
-     * loads model classes - must be singletons
515
-     *
516
-     * @param string $class_name - simple class name ie: price
517
-     * @param mixed  $arguments
518
-     * @param bool   $load_only
519
-     * @return EEM_Base | bool
520
-     * @throws EE_Error
521
-     * @throws ReflectionException
522
-     */
523
-    public function load_model($class_name, $arguments = array(), $load_only = false)
524
-    {
525
-        $paths = apply_filters(
526
-            'FHEE__EE_Registry__load_model__paths', array(
527
-            EE_MODELS,
528
-            EE_CORE,
529
-        )
530
-        );
531
-        // retrieve instantiated class
532
-        return $this->_load(
533
-            $paths,
534
-            'EEM_',
535
-            $class_name,
536
-            'model',
537
-            $arguments,
538
-            false,
539
-            true,
540
-            $load_only
541
-        );
542
-    }
543
-
544
-
545
-
546
-    /**
547
-     * loads model classes - must be singletons
548
-     *
549
-     * @param string $class_name - simple class name ie: price
550
-     * @param mixed  $arguments
551
-     * @param bool   $load_only
552
-     * @return mixed | bool
553
-     * @throws EE_Error
554
-     * @throws ReflectionException
555
-     */
556
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
557
-    {
558
-        $paths = array(
559
-            EE_MODELS . 'fields' . DS,
560
-            EE_MODELS . 'helpers' . DS,
561
-            EE_MODELS . 'relations' . DS,
562
-            EE_MODELS . 'strategies' . DS,
563
-        );
564
-        // retrieve instantiated class
565
-        return $this->_load(
566
-            $paths,
567
-            'EE_',
568
-            $class_name,
569
-            '',
570
-            $arguments,
571
-            false,
572
-            true,
573
-            $load_only
574
-        );
575
-    }
576
-
577
-
578
-
579
-    /**
580
-     * Determines if $model_name is the name of an actual EE model.
581
-     *
582
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
583
-     * @return boolean
584
-     */
585
-    public function is_model_name($model_name)
586
-    {
587
-        return isset($this->models[$model_name]);
588
-    }
589
-
590
-
591
-
592
-    /**
593
-     * generic class loader
594
-     *
595
-     * @param string $path_to_file - directory path to file location, not including filename
596
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
597
-     * @param string $type         - file type - core? class? helper? model?
598
-     * @param mixed  $arguments
599
-     * @param bool   $load_only
600
-     * @return mixed
601
-     * @throws EE_Error
602
-     * @throws ReflectionException
603
-     */
604
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
605
-    {
606
-        // retrieve instantiated class
607
-        return $this->_load(
608
-            $path_to_file,
609
-            '',
610
-            $file_name,
611
-            $type,
612
-            $arguments,
613
-            false,
614
-            true,
615
-            $load_only
616
-        );
617
-    }
618
-
619
-
620
-
621
-    /**
622
-     * @param string $path_to_file - directory path to file location, not including filename
623
-     * @param string $class_name   - full class name  ie:  My_Class
624
-     * @param string $type         - file type - core? class? helper? model?
625
-     * @param mixed  $arguments
626
-     * @param bool   $load_only
627
-     * @return bool|EE_Addon|object
628
-     * @throws EE_Error
629
-     * @throws ReflectionException
630
-     */
631
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
632
-    {
633
-        // retrieve instantiated class
634
-        return $this->_load(
635
-            $path_to_file,
636
-            'addon',
637
-            $class_name,
638
-            $type,
639
-            $arguments,
640
-            false,
641
-            true,
642
-            $load_only
643
-        );
644
-    }
645
-
646
-
647
-
648
-    /**
649
-     * instantiates, caches, and automatically resolves dependencies
650
-     * for classes that use a Fully Qualified Class Name.
651
-     * if the class is not capable of being loaded using PSR-4 autoloading,
652
-     * then you need to use one of the existing load_*() methods
653
-     * which can resolve the classname and filepath from the passed arguments
654
-     *
655
-     * @param bool|string $class_name   Fully Qualified Class Name
656
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
657
-     * @param bool        $cache        whether to cache the instantiated object for reuse
658
-     * @param bool        $from_db      some classes are instantiated from the db
659
-     *                                  and thus call a different method to instantiate
660
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
661
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
662
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
663
-     *                                  object = class loaded and instantiated successfully.
664
-     *                                  bool = fail or success when $load_only is true
665
-     * @throws EE_Error
666
-     * @throws ReflectionException
667
-     */
668
-    public function create(
669
-        $class_name = false,
670
-        $arguments = array(),
671
-        $cache = false,
672
-        $from_db = false,
673
-        $load_only = false,
674
-        $addon = false
675
-    ) {
676
-        $class_name = ltrim($class_name, '\\');
677
-        $class_name = $this->_dependency_map->get_alias($class_name);
678
-        if (! class_exists($class_name)) {
679
-            // maybe the class is registered with a preceding \
680
-            $class_name = strpos($class_name, '\\') !== 0
681
-                ? '\\' . $class_name
682
-                : $class_name;
683
-            // still doesn't exist ?
684
-            if (! class_exists($class_name)) {
685
-                return null;
686
-            }
687
-        }
688
-        // if we're only loading the class and it already exists, then let's just return true immediately
689
-        if ($load_only) {
690
-            return true;
691
-        }
692
-        $addon = $addon
693
-            ? 'addon'
694
-            : '';
695
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
696
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
697
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
698
-        if ($this->_cache_on && $cache && ! $load_only) {
699
-            // return object if it's already cached
700
-            $cached_class = $this->_get_cached_class($class_name, $addon);
701
-            if ($cached_class !== null) {
702
-                return $cached_class;
703
-            }
704
-        }
705
-        // obtain the loader method from the dependency map
706
-        $loader = $this->_dependency_map->class_loader($class_name);
707
-        // instantiate the requested object
708
-        if ($loader instanceof Closure) {
709
-            $class_obj = $loader($arguments);
710
-        } else if ($loader && method_exists($this, $loader)) {
711
-            $class_obj = $this->{$loader}($class_name, $arguments);
712
-        } else {
713
-            $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
714
-        }
715
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
716
-            // save it for later... kinda like gum  { : $
717
-            $this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
718
-        }
719
-        $this->_cache_on = true;
720
-        return $class_obj;
721
-    }
722
-
723
-
724
-
725
-    /**
726
-     * instantiates, caches, and injects dependencies for classes
727
-     *
728
-     * @param array       $file_paths   an array of paths to folders to look in
729
-     * @param string      $class_prefix EE  or EEM or... ???
730
-     * @param bool|string $class_name   $class name
731
-     * @param string      $type         file type - core? class? helper? model?
732
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
733
-     * @param bool        $from_db      some classes are instantiated from the db
734
-     *                                  and thus call a different method to instantiate
735
-     * @param bool        $cache        whether to cache the instantiated object for reuse
736
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
737
-     * @return bool|null|object null = failure to load or instantiate class object.
738
-     *                                  object = class loaded and instantiated successfully.
739
-     *                                  bool = fail or success when $load_only is true
740
-     * @throws EE_Error
741
-     * @throws ReflectionException
742
-     */
743
-    protected function _load(
744
-        $file_paths = array(),
745
-        $class_prefix = 'EE_',
746
-        $class_name = false,
747
-        $type = 'class',
748
-        $arguments = array(),
749
-        $from_db = false,
750
-        $cache = true,
751
-        $load_only = false
752
-    ) {
753
-        $class_name = ltrim($class_name, '\\');
754
-        // strip php file extension
755
-        $class_name = str_replace('.php', '', trim($class_name));
756
-        // does the class have a prefix ?
757
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
758
-            // make sure $class_prefix is uppercase
759
-            $class_prefix = strtoupper(trim($class_prefix));
760
-            // add class prefix ONCE!!!
761
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
762
-        }
763
-        $class_name = $this->_dependency_map->get_alias($class_name);
764
-        $class_exists = class_exists($class_name);
765
-        // if we're only loading the class and it already exists, then let's just return true immediately
766
-        if ($load_only && $class_exists) {
767
-            return true;
768
-        }
769
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
770
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
771
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
772
-        if ($this->_cache_on && $cache && ! $load_only) {
773
-            // return object if it's already cached
774
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix);
775
-            if ($cached_class !== null) {
776
-                return $cached_class;
777
-            }
778
-        }
779
-        // if the class doesn't already exist.. then we need to try and find the file and load it
780
-        if (! $class_exists) {
781
-            // get full path to file
782
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
783
-            // load the file
784
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
785
-            // if loading failed, or we are only loading a file but NOT instantiating an object
786
-            if (! $loaded || $load_only) {
787
-                // return boolean if only loading, or null if an object was expected
788
-                return $load_only
789
-                    ? $loaded
790
-                    : null;
791
-            }
792
-        }
793
-        // instantiate the requested object
794
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
795
-        if ($this->_cache_on && $cache) {
796
-            // save it for later... kinda like gum  { : $
797
-            $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
798
-        }
799
-        $this->_cache_on = true;
800
-        return $class_obj;
801
-    }
802
-
803
-
804
-
805
-    /**
806
-     * @param string $class_name
807
-     * @param string $default have to specify something, but not anything that will conflict
808
-     * @return mixed|string
809
-     */
810
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
811
-    {
812
-        return isset($this->_class_abbreviations[$class_name])
813
-            ? $this->_class_abbreviations[$class_name]
814
-            : $default;
815
-    }
816
-
817
-    /**
818
-     * attempts to find a cached version of the requested class
819
-     * by looking in the following places:
820
-     *        $this->{$class_abbreviation}            ie:    $this->CART
821
-     *        $this->{$class_name}                        ie:    $this->Some_Class
822
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
823
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
824
-     *
825
-     * @param string $class_name
826
-     * @param string $class_prefix
827
-     * @return mixed
828
-     */
829
-    protected function _get_cached_class($class_name, $class_prefix = '')
830
-    {
831
-        if ($class_name === 'EE_Registry') {
832
-            return $this;
833
-        }
834
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
835
-        $class_name = str_replace('\\', '_', $class_name);
836
-        // check if class has already been loaded, and return it if it has been
837
-        if (isset($this->{$class_abbreviation})) {
838
-            return $this->{$class_abbreviation};
839
-        }
840
-        if (isset ($this->{$class_name})) {
841
-            return $this->{$class_name};
842
-        }
843
-        if (isset ($this->LIB->{$class_name})) {
844
-            return $this->LIB->{$class_name};
845
-        }
846
-        if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
847
-            return $this->addons->{$class_name};
848
-        }
849
-        return null;
850
-    }
851
-
852
-
853
-
854
-    /**
855
-     * removes a cached version of the requested class
856
-     *
857
-     * @param string  $class_name
858
-     * @param boolean $addon
859
-     * @return boolean
860
-     */
861
-    public function clear_cached_class($class_name, $addon = false)
862
-    {
863
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
864
-        $class_name = str_replace('\\', '_', $class_name);
865
-        // check if class has already been loaded, and return it if it has been
866
-        if (isset($this->{$class_abbreviation})) {
867
-            $this->{$class_abbreviation} = null;
868
-            return true;
869
-        }
870
-        if (isset($this->{$class_name})) {
871
-            $this->{$class_name} = null;
872
-            return true;
873
-        }
874
-        if (isset($this->LIB->{$class_name})) {
875
-            unset($this->LIB->{$class_name});
876
-            return true;
877
-        }
878
-        if ($addon && isset($this->addons->{$class_name})) {
879
-            unset($this->addons->{$class_name});
880
-            return true;
881
-        }
882
-        return false;
883
-    }
884
-
885
-
886
-
887
-    /**
888
-     * attempts to find a full valid filepath for the requested class.
889
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
890
-     * then returns that path if the target file has been found and is readable
891
-     *
892
-     * @param string $class_name
893
-     * @param string $type
894
-     * @param array  $file_paths
895
-     * @return string | bool
896
-     */
897
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
898
-    {
899
-        // make sure $file_paths is an array
900
-        $file_paths = is_array($file_paths)
901
-            ? $file_paths
902
-            : array($file_paths);
903
-        // cycle thru paths
904
-        foreach ($file_paths as $key => $file_path) {
905
-            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
906
-            $file_path = $file_path
907
-                ? str_replace(array('/', '\\'), DS, $file_path)
908
-                : EE_CLASSES;
909
-            // prep file type
910
-            $type = ! empty($type)
911
-                ? trim($type, '.') . '.'
912
-                : '';
913
-            // build full file path
914
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
915
-            //does the file exist and can be read ?
916
-            if (is_readable($file_paths[$key])) {
917
-                return $file_paths[$key];
918
-            }
919
-        }
920
-        return false;
921
-    }
922
-
923
-
924
-
925
-    /**
926
-     * basically just performs a require_once()
927
-     * but with some error handling
928
-     *
929
-     * @param  string $path
930
-     * @param  string $class_name
931
-     * @param  string $type
932
-     * @param  array  $file_paths
933
-     * @return bool
934
-     * @throws EE_Error
935
-     * @throws ReflectionException
936
-     */
937
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
938
-    {
939
-        // don't give up! you gotta...
940
-        try {
941
-            //does the file exist and can it be read ?
942
-            if (! $path) {
943
-                // so sorry, can't find the file
944
-                throw new EE_Error (
945
-                    sprintf(
946
-                        esc_html__(
947
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
948
-                            'event_espresso'
949
-                        ),
950
-                        trim($type, '.'),
951
-                        $class_name,
952
-                        '<br />' . implode(',<br />', $file_paths)
953
-                    )
954
-                );
955
-            }
956
-            // get the file
957
-            require_once($path);
958
-            // if the class isn't already declared somewhere
959
-            if (class_exists($class_name, false) === false) {
960
-                // so sorry, not a class
961
-                throw new EE_Error(
962
-                    sprintf(
963
-                        esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
964
-                        $type,
965
-                        $path,
966
-                        $class_name
967
-                    )
968
-                );
969
-            }
970
-        } catch (EE_Error $e) {
971
-            $e->get_error();
972
-            return false;
973
-        }
974
-        return true;
975
-    }
976
-
977
-
978
-
979
-    /**
980
-     * _create_object
981
-     * Attempts to instantiate the requested class via any of the
982
-     * commonly used instantiation methods employed throughout EE.
983
-     * The priority for instantiation is as follows:
984
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
985
-     *        - model objects via their 'new_instance_from_db' method
986
-     *        - model objects via their 'new_instance' method
987
-     *        - "singleton" classes" via their 'instance' method
988
-     *    - standard instantiable classes via their __constructor
989
-     * Prior to instantiation, if the classname exists in the dependency_map,
990
-     * then the constructor for the requested class will be examined to determine
991
-     * if any dependencies exist, and if they can be injected.
992
-     * If so, then those classes will be added to the array of arguments passed to the constructor
993
-     *
994
-     * @param string $class_name
995
-     * @param array  $arguments
996
-     * @param string $type
997
-     * @param bool   $from_db
998
-     * @return null|object
999
-     * @throws EE_Error
1000
-     * @throws ReflectionException
1001
-     */
1002
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1003
-    {
1004
-        $class_obj = null;
1005
-        $instantiation_mode = '0) none';
1006
-        // don't give up! you gotta...
1007
-        try {
1008
-            // create reflection
1009
-            $reflector = $this->get_ReflectionClass($class_name);
1010
-            // make sure arguments are an array
1011
-            $arguments = is_array($arguments)
1012
-                ? $arguments
1013
-                : array($arguments);
1014
-            // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1015
-            // else wrap it in an additional array so that it doesn't get split into multiple parameters
1016
-            $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1017
-                ? $arguments
1018
-                : array($arguments);
1019
-            // attempt to inject dependencies ?
1020
-            if ($this->_dependency_map->has($class_name)) {
1021
-                $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1022
-            }
1023
-            // instantiate the class if possible
1024
-            if ($reflector->isAbstract()) {
1025
-                // nothing to instantiate, loading file was enough
1026
-                // does not throw an exception so $instantiation_mode is unused
1027
-                // $instantiation_mode = "1) no constructor abstract class";
1028
-                $class_obj = true;
1029
-            } else if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1030
-                // no constructor = static methods only... nothing to instantiate, loading file was enough
1031
-                $instantiation_mode = '2) no constructor but instantiable';
1032
-                $class_obj = $reflector->newInstance();
1033
-            } else if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1034
-                $instantiation_mode = '3) new_instance_from_db()';
1035
-                $class_obj = call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1036
-            } else if (method_exists($class_name, 'new_instance')) {
1037
-                $instantiation_mode = '4) new_instance()';
1038
-                $class_obj = call_user_func_array(array($class_name, 'new_instance'), $arguments);
1039
-            } else if (method_exists($class_name, 'instance')) {
1040
-                $instantiation_mode = '5) instance()';
1041
-                $class_obj = call_user_func_array(array($class_name, 'instance'), $arguments);
1042
-            } else if ($reflector->isInstantiable()) {
1043
-                $instantiation_mode = '6) constructor';
1044
-                $class_obj = $reflector->newInstanceArgs($arguments);
1045
-            } else {
1046
-                // heh ? something's not right !
1047
-                throw new EE_Error(
1048
-                    sprintf(
1049
-                        esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1050
-                        $type,
1051
-                        $class_name
1052
-                    )
1053
-                );
1054
-            }
1055
-        } catch (Exception $e) {
1056
-            if (! $e instanceof EE_Error) {
1057
-                $e = new EE_Error(
1058
-                    sprintf(
1059
-                        esc_html__(
1060
-                            'The following error occurred while attempting to instantiate "%1$s": %2$s %3$s %2$s instantiation mode : %4$s',
1061
-                            'event_espresso'
1062
-                        ),
1063
-                        $class_name,
1064
-                        '<br />',
1065
-                        $e->getMessage(),
1066
-                        $instantiation_mode
1067
-                    )
1068
-                );
1069
-            }
1070
-            $e->get_error();
1071
-        }
1072
-        return $class_obj;
1073
-    }
1074
-
1075
-
1076
-
1077
-    /**
1078
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1079
-     * @param array $array
1080
-     * @return bool
1081
-     */
1082
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1083
-    {
1084
-        return ! empty($array)
1085
-            ? array_keys($array) === range(0, count($array) - 1)
1086
-            : true;
1087
-    }
1088
-
1089
-
1090
-
1091
-    /**
1092
-     * getReflectionClass
1093
-     * checks if a ReflectionClass object has already been generated for a class
1094
-     * and returns that instead of creating a new one
1095
-     *
1096
-     * @param string $class_name
1097
-     * @return ReflectionClass
1098
-     * @throws ReflectionException
1099
-     */
1100
-    public function get_ReflectionClass($class_name)
1101
-    {
1102
-        if (
1103
-            ! isset($this->_reflectors[$class_name])
1104
-            || ! $this->_reflectors[$class_name] instanceof ReflectionClass
1105
-        ) {
1106
-            $this->_reflectors[$class_name] = new ReflectionClass($class_name);
1107
-        }
1108
-        return $this->_reflectors[$class_name];
1109
-    }
1110
-
1111
-
1112
-
1113
-    /**
1114
-     * _resolve_dependencies
1115
-     * examines the constructor for the requested class to determine
1116
-     * if any dependencies exist, and if they can be injected.
1117
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1118
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1119
-     * For example:
1120
-     *        if attempting to load a class "Foo" with the following constructor:
1121
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1122
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1123
-     *        but only IF they are NOT already present in the incoming arguments array,
1124
-     *        and the correct classes can be loaded
1125
-     *
1126
-     * @param ReflectionClass $reflector
1127
-     * @param string          $class_name
1128
-     * @param array           $arguments
1129
-     * @return array
1130
-     * @throws EE_Error
1131
-     * @throws ReflectionException
1132
-     */
1133
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1134
-    {
1135
-        // let's examine the constructor
1136
-        $constructor = $reflector->getConstructor();
1137
-        // whu? huh? nothing?
1138
-        if (! $constructor) {
1139
-            return $arguments;
1140
-        }
1141
-        // get constructor parameters
1142
-        $params = $constructor->getParameters();
1143
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1144
-        $argument_keys = array_keys($arguments);
1145
-        // now loop thru all of the constructors expected parameters
1146
-        foreach ($params as $index => $param) {
1147
-            // is this a dependency for a specific class ?
1148
-            $param_class = $param->getClass()
1149
-                ? $param->getClass()->name
1150
-                : null;
1151
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1152
-            $param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1153
-                ? $this->_dependency_map->get_alias($param_class, $class_name)
1154
-                : $param_class;
1155
-            if (
1156
-                // param is not even a class
1157
-                $param_class === null
1158
-                // and something already exists in the incoming arguments for this param
1159
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1160
-            ) {
1161
-                // so let's skip this argument and move on to the next
1162
-                continue;
1163
-            }
1164
-            if (
1165
-                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1166
-                $param_class !== null
1167
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1168
-                && $arguments[$argument_keys[$index]] instanceof $param_class
1169
-            ) {
1170
-                // skip this argument and move on to the next
1171
-                continue;
1172
-            }
1173
-            if (
1174
-                // parameter is type hinted as a class, and should be injected
1175
-                $param_class !== null
1176
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1177
-            ) {
1178
-                $arguments = $this->_resolve_dependency(
1179
-                    $class_name,
1180
-                    $param_class,
1181
-                    $arguments,
1182
-                    $index,
1183
-                    $argument_keys
1184
-                );
1185
-            } else {
1186
-                try {
1187
-                    $arguments[$index] = $param->isDefaultValueAvailable()
1188
-                        ? $param->getDefaultValue()
1189
-                        : null;
1190
-                } catch (ReflectionException $e) {
1191
-                    throw new ReflectionException(
1192
-                        sprintf(
1193
-                            esc_html__('%1$s for parameter "$%2$s"', 'event_espresso'),
1194
-                            $e->getMessage(),
1195
-                            $param->getName()
1196
-                        )
1197
-                    );
1198
-                }
1199
-            }
1200
-        }
1201
-        return $arguments;
1202
-    }
1203
-
1204
-
1205
-
1206
-    /**
1207
-     * @param string $class_name
1208
-     * @param string $param_class
1209
-     * @param array  $arguments
1210
-     * @param mixed  $index
1211
-     * @param array  $argument_keys
1212
-     * @return array
1213
-     * @throws EE_Error
1214
-     * @throws ReflectionException
1215
-     * @throws InvalidArgumentException
1216
-     * @throws InvalidInterfaceException
1217
-     * @throws InvalidDataTypeException
1218
-     */
1219
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1220
-    {
1221
-        $dependency = null;
1222
-        // should dependency be loaded from cache ?
1223
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1224
-            $class_name,
1225
-            $param_class
1226
-        );
1227
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1228
-        // we might have a dependency...
1229
-        // let's MAYBE try and find it in our cache if that's what's been requested
1230
-        $cached_class = $cache_on
1231
-            ? $this->_get_cached_class($param_class)
1232
-            : null;
1233
-        // and grab it if it exists
1234
-        if ($cached_class instanceof $param_class) {
1235
-            $dependency = $cached_class;
1236
-        } else if ($param_class !== $class_name) {
1237
-            // obtain the loader method from the dependency map
1238
-            $loader = $this->_dependency_map->class_loader($param_class);
1239
-            // is loader a custom closure ?
1240
-            if ($loader instanceof Closure) {
1241
-                $dependency = $loader($arguments);
1242
-            } else {
1243
-                // set the cache on property for the recursive loading call
1244
-                $this->_cache_on = $cache_on;
1245
-                // if not, then let's try and load it via the registry
1246
-                if ($loader && method_exists($this, $loader)) {
1247
-                    $dependency = $this->{$loader}($param_class);
1248
-                } else {
1249
-                    $dependency = LoaderFactory::getLoader()->load(
1250
-                        $param_class,
1251
-                        array(),
1252
-                        $cache_on
1253
-                    );
1254
-                }
1255
-            }
1256
-        }
1257
-        // did we successfully find the correct dependency ?
1258
-        if ($dependency instanceof $param_class) {
1259
-            // then let's inject it into the incoming array of arguments at the correct location
1260
-            $arguments[$index] = $dependency;
1261
-        }
1262
-        return $arguments;
1263
-    }
1264
-
1265
-
1266
-
1267
-    /**
1268
-     * _set_cached_class
1269
-     * attempts to cache the instantiated class locally
1270
-     * in one of the following places, in the following order:
1271
-     *        $this->{class_abbreviation}   ie:    $this->CART
1272
-     *        $this->{$class_name}          ie:    $this->Some_Class
1273
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1274
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1275
-     *
1276
-     * @param object $class_obj
1277
-     * @param string $class_name
1278
-     * @param string $class_prefix
1279
-     * @param bool   $from_db
1280
-     * @return void
1281
-     */
1282
-    protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1283
-    {
1284
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1285
-            return;
1286
-        }
1287
-        // return newly instantiated class
1288
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1289
-        if ($class_abbreviation) {
1290
-            $this->{$class_abbreviation} = $class_obj;
1291
-            return;
1292
-        }
1293
-        $class_name = str_replace('\\', '_', $class_name);
1294
-        if (property_exists($this, $class_name)) {
1295
-            $this->{$class_name} = $class_obj;
1296
-            return;
1297
-        }
1298
-        if ($class_prefix === 'addon') {
1299
-            $this->addons->{$class_name} = $class_obj;
1300
-            return;
1301
-        }
1302
-        if (! $from_db) {
1303
-            $this->LIB->{$class_name} = $class_obj;
1304
-        }
1305
-    }
1306
-
1307
-
1308
-
1309
-    /**
1310
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1311
-     *
1312
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1313
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1314
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1315
-     * @param array  $arguments
1316
-     * @return object
1317
-     */
1318
-    public static function factory($classname, $arguments = array())
1319
-    {
1320
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1321
-        if ($loader instanceof Closure) {
1322
-            return $loader($arguments);
1323
-        }
1324
-        if (method_exists(self::instance(), $loader)) {
1325
-            return self::instance()->{$loader}($classname, $arguments);
1326
-        }
1327
-        return null;
1328
-    }
1329
-
1330
-
1331
-
1332
-    /**
1333
-     * Gets the addon by its name/slug (not classname. For that, just
1334
-     * use the classname as the property name on EE_Config::instance()->addons)
1335
-     *
1336
-     * @param string $name
1337
-     * @return EE_Addon
1338
-     */
1339
-    public function get_addon_by_name($name)
1340
-    {
1341
-        foreach ($this->addons as $addon) {
1342
-            if ($addon->name() === $name) {
1343
-                return $addon;
1344
-            }
1345
-        }
1346
-        return null;
1347
-    }
1348
-
1349
-
1350
-
1351
-    /**
1352
-     * Gets an array of all the registered addons, where the keys are their names. (ie, what each returns for their
1353
-     * name() function) They're already available on EE_Config::instance()->addons as properties, where each property's
1354
-     * name is the addon's classname. So if you just want to get the addon by classname, use
1355
-     * EE_Config::instance()->addons->{classname}
1356
-     *
1357
-     * @return EE_Addon[] where the KEYS are the addon's name()
1358
-     */
1359
-    public function get_addons_by_name()
1360
-    {
1361
-        $addons = array();
1362
-        foreach ($this->addons as $addon) {
1363
-            $addons[$addon->name()] = $addon;
1364
-        }
1365
-        return $addons;
1366
-    }
1367
-
1368
-
1369
-
1370
-    /**
1371
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1372
-     * a stale copy of it around
1373
-     *
1374
-     * @param string $model_name
1375
-     * @return \EEM_Base
1376
-     * @throws \EE_Error
1377
-     */
1378
-    public function reset_model($model_name)
1379
-    {
1380
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1381
-            ? "EEM_{$model_name}"
1382
-            : $model_name;
1383
-        if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1384
-            return null;
1385
-        }
1386
-        //get that model reset it and make sure we nuke the old reference to it
1387
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name
1388
-            && is_callable(
1389
-                array($model_class_name, 'reset')
1390
-            )) {
1391
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1392
-        } else {
1393
-            throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1394
-        }
1395
-        return $this->LIB->{$model_class_name};
1396
-    }
1397
-
1398
-
1399
-
1400
-    /**
1401
-     * Resets the registry.
1402
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1403
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1404
-     * - $_dependency_map
1405
-     * - $_class_abbreviations
1406
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1407
-     * - $REQ:  Still on the same request so no need to change.
1408
-     * - $CAP: There is no site specific state in the EE_Capability class.
1409
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1410
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1411
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1412
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1413
-     *             switch or on the restore.
1414
-     * - $modules
1415
-     * - $shortcodes
1416
-     * - $widgets
1417
-     *
1418
-     * @param boolean $hard             [deprecated]
1419
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1420
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1421
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1422
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1423
-     *                                  client
1424
-     *                                  code instead can just change the model context to a different blog id if
1425
-     *                                  necessary
1426
-     * @return EE_Registry
1427
-     * @throws EE_Error
1428
-     * @throws ReflectionException
1429
-     */
1430
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1431
-    {
1432
-        $instance = self::instance();
1433
-        $instance->_cache_on = true;
1434
-        // reset some "special" classes
1435
-        EEH_Activation::reset();
1436
-        $hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1437
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1438
-        $instance->CART = null;
1439
-        $instance->MRM = null;
1440
-        $instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1441
-        //messages reset
1442
-        EED_Messages::reset();
1443
-        //handle of objects cached on LIB
1444
-        foreach (array('LIB', 'modules') as $cache) {
1445
-            foreach ($instance->{$cache} as $class_name => $class) {
1446
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1447
-                    unset($instance->{$cache}->{$class_name});
1448
-                }
1449
-            }
1450
-        }
1451
-        return $instance;
1452
-    }
1453
-
1454
-
1455
-
1456
-    /**
1457
-     * if passed object implements ResettableInterface, then call it's reset() method
1458
-     * if passed object implements InterminableInterface, then return false,
1459
-     * to indicate that it should NOT be cleared from the Registry cache
1460
-     *
1461
-     * @param      $object
1462
-     * @param bool $reset_models
1463
-     * @return bool returns true if cached object should be unset
1464
-     */
1465
-    private static function _reset_and_unset_object($object, $reset_models)
1466
-    {
1467
-        if (! is_object($object)) {
1468
-            // don't unset anything that's not an object
1469
-            return false;
1470
-        }
1471
-        if ($object instanceof EED_Module) {
1472
-            $object::reset();
1473
-            // don't unset modules
1474
-            return false;
1475
-        }
1476
-        if ($object instanceof ResettableInterface) {
1477
-            if ($object instanceof EEM_Base) {
1478
-                if ($reset_models) {
1479
-                    $object->reset();
1480
-                    return true;
1481
-                }
1482
-                return false;
1483
-            }
1484
-            $object->reset();
1485
-            return true;
1486
-        }
1487
-        if (! $object instanceof InterminableInterface) {
1488
-            return true;
1489
-        }
1490
-        return false;
1491
-    }
1492
-
1493
-
1494
-
1495
-    /**
1496
-     * Gets all the custom post type models defined
1497
-     *
1498
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1499
-     */
1500
-    public function cpt_models()
1501
-    {
1502
-        $cpt_models = array();
1503
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1504
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1505
-                $cpt_models[$short_name] = $classname;
1506
-            }
1507
-        }
1508
-        return $cpt_models;
1509
-    }
1510
-
1511
-
1512
-
1513
-    /**
1514
-     * @return \EE_Config
1515
-     */
1516
-    public static function CFG()
1517
-    {
1518
-        return self::instance()->CFG;
1519
-    }
25
+	/**
26
+	 * @var EE_Registry $_instance
27
+	 */
28
+	private static $_instance;
29
+
30
+	/**
31
+	 * @var EE_Dependency_Map $_dependency_map
32
+	 */
33
+	protected $_dependency_map;
34
+
35
+	/**
36
+	 * @var array $_class_abbreviations
37
+	 */
38
+	protected $_class_abbreviations = array();
39
+
40
+	/**
41
+	 * @var CommandBusInterface $BUS
42
+	 */
43
+	public $BUS;
44
+
45
+	/**
46
+	 * @var EE_Cart $CART
47
+	 */
48
+	public $CART;
49
+
50
+	/**
51
+	 * @var EE_Config $CFG
52
+	 */
53
+	public $CFG;
54
+
55
+	/**
56
+	 * @var EE_Network_Config $NET_CFG
57
+	 */
58
+	public $NET_CFG;
59
+
60
+	/**
61
+	 * StdClass object for storing library classes in
62
+	 *
63
+	 * @var StdClass $LIB
64
+	 */
65
+	public $LIB;
66
+
67
+	/**
68
+	 * @var EE_Request_Handler $REQ
69
+	 */
70
+	public $REQ;
71
+
72
+	/**
73
+	 * @var EE_Session $SSN
74
+	 */
75
+	public $SSN;
76
+
77
+	/**
78
+	 * @since 4.5.0
79
+	 * @var EE_Capabilities $CAP
80
+	 */
81
+	public $CAP;
82
+
83
+	/**
84
+	 * @since 4.9.0
85
+	 * @var EE_Message_Resource_Manager $MRM
86
+	 */
87
+	public $MRM;
88
+
89
+
90
+	/**
91
+	 * @var Registry $AssetsRegistry
92
+	 */
93
+	public $AssetsRegistry;
94
+
95
+	/**
96
+	 * StdClass object for holding addons which have registered themselves to work with EE core
97
+	 *
98
+	 * @var EE_Addon[] $addons
99
+	 */
100
+	public $addons;
101
+
102
+	/**
103
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
104
+	 *
105
+	 * @var EEM_Base[] $models
106
+	 */
107
+	public $models = array();
108
+
109
+	/**
110
+	 * @var EED_Module[] $modules
111
+	 */
112
+	public $modules;
113
+
114
+	/**
115
+	 * @var EES_Shortcode[] $shortcodes
116
+	 */
117
+	public $shortcodes;
118
+
119
+	/**
120
+	 * @var WP_Widget[] $widgets
121
+	 */
122
+	public $widgets;
123
+
124
+	/**
125
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
126
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
127
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
128
+	 * classnames (eg "EEM_Event")
129
+	 *
130
+	 * @var array $non_abstract_db_models
131
+	 */
132
+	public $non_abstract_db_models = array();
133
+
134
+
135
+	/**
136
+	 * internationalization for JS strings
137
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
138
+	 *    in js file:  var translatedString = eei18n.string_key;
139
+	 *
140
+	 * @var array $i18n_js_strings
141
+	 */
142
+	public static $i18n_js_strings = array();
143
+
144
+
145
+	/**
146
+	 * $main_file - path to espresso.php
147
+	 *
148
+	 * @var array $main_file
149
+	 */
150
+	public $main_file;
151
+
152
+	/**
153
+	 * array of ReflectionClass objects where the key is the class name
154
+	 *
155
+	 * @var ReflectionClass[] $_reflectors
156
+	 */
157
+	public $_reflectors;
158
+
159
+	/**
160
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
161
+	 *
162
+	 * @var boolean $_cache_on
163
+	 */
164
+	protected $_cache_on = true;
165
+
166
+
167
+
168
+	/**
169
+	 * @singleton method used to instantiate class object
170
+	 * @param  EE_Dependency_Map $dependency_map
171
+	 * @return EE_Registry instance
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidInterfaceException
174
+	 * @throws InvalidDataTypeException
175
+	 */
176
+	public static function instance(EE_Dependency_Map $dependency_map = null)
177
+	{
178
+		// check if class object is instantiated
179
+		if (! self::$_instance instanceof EE_Registry) {
180
+			self::$_instance = new self($dependency_map);
181
+		}
182
+		return self::$_instance;
183
+	}
184
+
185
+
186
+
187
+	/**
188
+	 * protected constructor to prevent direct creation
189
+	 *
190
+	 * @Constructor
191
+	 * @param  EE_Dependency_Map $dependency_map
192
+	 * @throws InvalidDataTypeException
193
+	 * @throws InvalidInterfaceException
194
+	 * @throws InvalidArgumentException
195
+	 */
196
+	protected function __construct(EE_Dependency_Map $dependency_map)
197
+	{
198
+		$this->_dependency_map = $dependency_map;
199
+		$this->LIB = new stdClass();
200
+		$this->addons = new stdClass();
201
+		$this->modules = new stdClass();
202
+		$this->shortcodes = new stdClass();
203
+		$this->widgets = new stdClass();
204
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
205
+	}
206
+
207
+
208
+
209
+	/**
210
+	 * initialize
211
+	 *
212
+	 * @throws EE_Error
213
+	 * @throws ReflectionException
214
+	 */
215
+	public function initialize()
216
+	{
217
+		$this->_class_abbreviations = apply_filters(
218
+			'FHEE__EE_Registry____construct___class_abbreviations',
219
+			array(
220
+				'EE_Config'                                       => 'CFG',
221
+				'EE_Session'                                      => 'SSN',
222
+				'EE_Capabilities'                                 => 'CAP',
223
+				'EE_Cart'                                         => 'CART',
224
+				'EE_Network_Config'                               => 'NET_CFG',
225
+				'EE_Request_Handler'                              => 'REQ',
226
+				'EE_Message_Resource_Manager'                     => 'MRM',
227
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
228
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
229
+			)
230
+		);
231
+		$this->load_core('Base', array(), true);
232
+		// add our request and response objects to the cache
233
+		$request_loader = $this->_dependency_map->class_loader('EE_Request');
234
+		$this->_set_cached_class(
235
+			$request_loader(),
236
+			'EE_Request'
237
+		);
238
+		$response_loader = $this->_dependency_map->class_loader('EE_Response');
239
+		$this->_set_cached_class(
240
+			$response_loader(),
241
+			'EE_Response'
242
+		);
243
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
244
+	}
245
+
246
+
247
+
248
+	/**
249
+	 * @return void
250
+	 */
251
+	public function init()
252
+	{
253
+		// Get current page protocol
254
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
255
+		// Output admin-ajax.php URL with same protocol as current page
256
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
257
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
258
+	}
259
+
260
+
261
+
262
+	/**
263
+	 * localize_i18n_js_strings
264
+	 *
265
+	 * @return string
266
+	 */
267
+	public static function localize_i18n_js_strings()
268
+	{
269
+		$i18n_js_strings = (array)self::$i18n_js_strings;
270
+		foreach ($i18n_js_strings as $key => $value) {
271
+			if (is_scalar($value)) {
272
+				$i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
273
+			}
274
+		}
275
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
276
+	}
277
+
278
+
279
+
280
+	/**
281
+	 * @param mixed string | EED_Module $module
282
+	 * @throws EE_Error
283
+	 * @throws ReflectionException
284
+	 */
285
+	public function add_module($module)
286
+	{
287
+		if ($module instanceof EED_Module) {
288
+			$module_class = get_class($module);
289
+			$this->modules->{$module_class} = $module;
290
+		} else {
291
+			if (! class_exists('EE_Module_Request_Router')) {
292
+				$this->load_core('Module_Request_Router');
293
+			}
294
+			EE_Module_Request_Router::module_factory($module);
295
+		}
296
+	}
297
+
298
+
299
+
300
+	/**
301
+	 * @param string $module_name
302
+	 * @return mixed EED_Module | NULL
303
+	 */
304
+	public function get_module($module_name = '')
305
+	{
306
+		return isset($this->modules->{$module_name})
307
+			? $this->modules->{$module_name}
308
+			: null;
309
+	}
310
+
311
+
312
+
313
+	/**
314
+	 * loads core classes - must be singletons
315
+	 *
316
+	 * @param string $class_name - simple class name ie: session
317
+	 * @param mixed  $arguments
318
+	 * @param bool   $load_only
319
+	 * @return mixed
320
+	 * @throws EE_Error
321
+	 * @throws ReflectionException
322
+	 */
323
+	public function load_core($class_name, $arguments = array(), $load_only = false)
324
+	{
325
+		$core_paths = apply_filters(
326
+			'FHEE__EE_Registry__load_core__core_paths',
327
+			array(
328
+				EE_CORE,
329
+				EE_ADMIN,
330
+				EE_CPTS,
331
+				EE_CORE . 'data_migration_scripts' . DS,
332
+				EE_CORE . 'capabilities' . DS,
333
+				EE_CORE . 'request_stack' . DS,
334
+				EE_CORE . 'middleware' . DS,
335
+			)
336
+		);
337
+		// retrieve instantiated class
338
+		return $this->_load(
339
+			$core_paths,
340
+			'EE_',
341
+			$class_name,
342
+			'core',
343
+			$arguments,
344
+			false,
345
+			true,
346
+			$load_only
347
+		);
348
+	}
349
+
350
+
351
+
352
+	/**
353
+	 * loads service classes
354
+	 *
355
+	 * @param string $class_name - simple class name ie: session
356
+	 * @param mixed  $arguments
357
+	 * @param bool   $load_only
358
+	 * @return mixed
359
+	 * @throws EE_Error
360
+	 * @throws ReflectionException
361
+	 */
362
+	public function load_service($class_name, $arguments = array(), $load_only = false)
363
+	{
364
+		$service_paths = apply_filters(
365
+			'FHEE__EE_Registry__load_service__service_paths',
366
+			array(
367
+				EE_CORE . 'services' . DS,
368
+			)
369
+		);
370
+		// retrieve instantiated class
371
+		return $this->_load(
372
+			$service_paths,
373
+			'EE_',
374
+			$class_name,
375
+			'class',
376
+			$arguments,
377
+			false,
378
+			true,
379
+			$load_only
380
+		);
381
+	}
382
+
383
+
384
+
385
+	/**
386
+	 * loads data_migration_scripts
387
+	 *
388
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
389
+	 * @param mixed  $arguments
390
+	 * @return EE_Data_Migration_Script_Base|mixed
391
+	 * @throws EE_Error
392
+	 * @throws ReflectionException
393
+	 */
394
+	public function load_dms($class_name, $arguments = array())
395
+	{
396
+		// retrieve instantiated class
397
+		return $this->_load(
398
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
399
+			'EE_DMS_',
400
+			$class_name,
401
+			'dms',
402
+			$arguments,
403
+			false,
404
+			false
405
+		);
406
+	}
407
+
408
+
409
+
410
+	/**
411
+	 * loads object creating classes - must be singletons
412
+	 *
413
+	 * @param string $class_name - simple class name ie: attendee
414
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
415
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
416
+	 *                           instantiate
417
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
418
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
419
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
420
+	 *                           (default)
421
+	 * @return EE_Base_Class | bool
422
+	 * @throws EE_Error
423
+	 * @throws ReflectionException
424
+	 */
425
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
426
+	{
427
+		$paths = apply_filters(
428
+			'FHEE__EE_Registry__load_class__paths', array(
429
+			EE_CORE,
430
+			EE_CLASSES,
431
+			EE_BUSINESS,
432
+		)
433
+		);
434
+		// retrieve instantiated class
435
+		return $this->_load(
436
+			$paths,
437
+			'EE_',
438
+			$class_name,
439
+			'class',
440
+			$arguments,
441
+			$from_db,
442
+			$cache,
443
+			$load_only
444
+		);
445
+	}
446
+
447
+
448
+
449
+	/**
450
+	 * loads helper classes - must be singletons
451
+	 *
452
+	 * @param string $class_name - simple class name ie: price
453
+	 * @param mixed  $arguments
454
+	 * @param bool   $load_only
455
+	 * @return EEH_Base | bool
456
+	 * @throws EE_Error
457
+	 * @throws ReflectionException
458
+	 */
459
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
460
+	{
461
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
462
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
463
+		// retrieve instantiated class
464
+		return $this->_load(
465
+			$helper_paths,
466
+			'EEH_',
467
+			$class_name,
468
+			'helper',
469
+			$arguments,
470
+			false,
471
+			true,
472
+			$load_only
473
+		);
474
+	}
475
+
476
+
477
+
478
+	/**
479
+	 * loads core classes - must be singletons
480
+	 *
481
+	 * @param string $class_name - simple class name ie: session
482
+	 * @param mixed  $arguments
483
+	 * @param bool   $load_only
484
+	 * @param bool   $cache      whether to cache the object or not.
485
+	 * @return mixed
486
+	 * @throws EE_Error
487
+	 * @throws ReflectionException
488
+	 */
489
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
490
+	{
491
+		$paths = array(
492
+			EE_LIBRARIES,
493
+			EE_LIBRARIES . 'messages' . DS,
494
+			EE_LIBRARIES . 'shortcodes' . DS,
495
+			EE_LIBRARIES . 'qtips' . DS,
496
+			EE_LIBRARIES . 'payment_methods' . DS,
497
+		);
498
+		// retrieve instantiated class
499
+		return $this->_load(
500
+			$paths,
501
+			'EE_',
502
+			$class_name,
503
+			'lib',
504
+			$arguments,
505
+			false,
506
+			$cache,
507
+			$load_only
508
+		);
509
+	}
510
+
511
+
512
+
513
+	/**
514
+	 * loads model classes - must be singletons
515
+	 *
516
+	 * @param string $class_name - simple class name ie: price
517
+	 * @param mixed  $arguments
518
+	 * @param bool   $load_only
519
+	 * @return EEM_Base | bool
520
+	 * @throws EE_Error
521
+	 * @throws ReflectionException
522
+	 */
523
+	public function load_model($class_name, $arguments = array(), $load_only = false)
524
+	{
525
+		$paths = apply_filters(
526
+			'FHEE__EE_Registry__load_model__paths', array(
527
+			EE_MODELS,
528
+			EE_CORE,
529
+		)
530
+		);
531
+		// retrieve instantiated class
532
+		return $this->_load(
533
+			$paths,
534
+			'EEM_',
535
+			$class_name,
536
+			'model',
537
+			$arguments,
538
+			false,
539
+			true,
540
+			$load_only
541
+		);
542
+	}
543
+
544
+
545
+
546
+	/**
547
+	 * loads model classes - must be singletons
548
+	 *
549
+	 * @param string $class_name - simple class name ie: price
550
+	 * @param mixed  $arguments
551
+	 * @param bool   $load_only
552
+	 * @return mixed | bool
553
+	 * @throws EE_Error
554
+	 * @throws ReflectionException
555
+	 */
556
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
557
+	{
558
+		$paths = array(
559
+			EE_MODELS . 'fields' . DS,
560
+			EE_MODELS . 'helpers' . DS,
561
+			EE_MODELS . 'relations' . DS,
562
+			EE_MODELS . 'strategies' . DS,
563
+		);
564
+		// retrieve instantiated class
565
+		return $this->_load(
566
+			$paths,
567
+			'EE_',
568
+			$class_name,
569
+			'',
570
+			$arguments,
571
+			false,
572
+			true,
573
+			$load_only
574
+		);
575
+	}
576
+
577
+
578
+
579
+	/**
580
+	 * Determines if $model_name is the name of an actual EE model.
581
+	 *
582
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
583
+	 * @return boolean
584
+	 */
585
+	public function is_model_name($model_name)
586
+	{
587
+		return isset($this->models[$model_name]);
588
+	}
589
+
590
+
591
+
592
+	/**
593
+	 * generic class loader
594
+	 *
595
+	 * @param string $path_to_file - directory path to file location, not including filename
596
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
597
+	 * @param string $type         - file type - core? class? helper? model?
598
+	 * @param mixed  $arguments
599
+	 * @param bool   $load_only
600
+	 * @return mixed
601
+	 * @throws EE_Error
602
+	 * @throws ReflectionException
603
+	 */
604
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
605
+	{
606
+		// retrieve instantiated class
607
+		return $this->_load(
608
+			$path_to_file,
609
+			'',
610
+			$file_name,
611
+			$type,
612
+			$arguments,
613
+			false,
614
+			true,
615
+			$load_only
616
+		);
617
+	}
618
+
619
+
620
+
621
+	/**
622
+	 * @param string $path_to_file - directory path to file location, not including filename
623
+	 * @param string $class_name   - full class name  ie:  My_Class
624
+	 * @param string $type         - file type - core? class? helper? model?
625
+	 * @param mixed  $arguments
626
+	 * @param bool   $load_only
627
+	 * @return bool|EE_Addon|object
628
+	 * @throws EE_Error
629
+	 * @throws ReflectionException
630
+	 */
631
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
632
+	{
633
+		// retrieve instantiated class
634
+		return $this->_load(
635
+			$path_to_file,
636
+			'addon',
637
+			$class_name,
638
+			$type,
639
+			$arguments,
640
+			false,
641
+			true,
642
+			$load_only
643
+		);
644
+	}
645
+
646
+
647
+
648
+	/**
649
+	 * instantiates, caches, and automatically resolves dependencies
650
+	 * for classes that use a Fully Qualified Class Name.
651
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
652
+	 * then you need to use one of the existing load_*() methods
653
+	 * which can resolve the classname and filepath from the passed arguments
654
+	 *
655
+	 * @param bool|string $class_name   Fully Qualified Class Name
656
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
657
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
658
+	 * @param bool        $from_db      some classes are instantiated from the db
659
+	 *                                  and thus call a different method to instantiate
660
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
661
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
662
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
663
+	 *                                  object = class loaded and instantiated successfully.
664
+	 *                                  bool = fail or success when $load_only is true
665
+	 * @throws EE_Error
666
+	 * @throws ReflectionException
667
+	 */
668
+	public function create(
669
+		$class_name = false,
670
+		$arguments = array(),
671
+		$cache = false,
672
+		$from_db = false,
673
+		$load_only = false,
674
+		$addon = false
675
+	) {
676
+		$class_name = ltrim($class_name, '\\');
677
+		$class_name = $this->_dependency_map->get_alias($class_name);
678
+		if (! class_exists($class_name)) {
679
+			// maybe the class is registered with a preceding \
680
+			$class_name = strpos($class_name, '\\') !== 0
681
+				? '\\' . $class_name
682
+				: $class_name;
683
+			// still doesn't exist ?
684
+			if (! class_exists($class_name)) {
685
+				return null;
686
+			}
687
+		}
688
+		// if we're only loading the class and it already exists, then let's just return true immediately
689
+		if ($load_only) {
690
+			return true;
691
+		}
692
+		$addon = $addon
693
+			? 'addon'
694
+			: '';
695
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
696
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
697
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
698
+		if ($this->_cache_on && $cache && ! $load_only) {
699
+			// return object if it's already cached
700
+			$cached_class = $this->_get_cached_class($class_name, $addon);
701
+			if ($cached_class !== null) {
702
+				return $cached_class;
703
+			}
704
+		}
705
+		// obtain the loader method from the dependency map
706
+		$loader = $this->_dependency_map->class_loader($class_name);
707
+		// instantiate the requested object
708
+		if ($loader instanceof Closure) {
709
+			$class_obj = $loader($arguments);
710
+		} else if ($loader && method_exists($this, $loader)) {
711
+			$class_obj = $this->{$loader}($class_name, $arguments);
712
+		} else {
713
+			$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
714
+		}
715
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
716
+			// save it for later... kinda like gum  { : $
717
+			$this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
718
+		}
719
+		$this->_cache_on = true;
720
+		return $class_obj;
721
+	}
722
+
723
+
724
+
725
+	/**
726
+	 * instantiates, caches, and injects dependencies for classes
727
+	 *
728
+	 * @param array       $file_paths   an array of paths to folders to look in
729
+	 * @param string      $class_prefix EE  or EEM or... ???
730
+	 * @param bool|string $class_name   $class name
731
+	 * @param string      $type         file type - core? class? helper? model?
732
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
733
+	 * @param bool        $from_db      some classes are instantiated from the db
734
+	 *                                  and thus call a different method to instantiate
735
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
736
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
737
+	 * @return bool|null|object null = failure to load or instantiate class object.
738
+	 *                                  object = class loaded and instantiated successfully.
739
+	 *                                  bool = fail or success when $load_only is true
740
+	 * @throws EE_Error
741
+	 * @throws ReflectionException
742
+	 */
743
+	protected function _load(
744
+		$file_paths = array(),
745
+		$class_prefix = 'EE_',
746
+		$class_name = false,
747
+		$type = 'class',
748
+		$arguments = array(),
749
+		$from_db = false,
750
+		$cache = true,
751
+		$load_only = false
752
+	) {
753
+		$class_name = ltrim($class_name, '\\');
754
+		// strip php file extension
755
+		$class_name = str_replace('.php', '', trim($class_name));
756
+		// does the class have a prefix ?
757
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
758
+			// make sure $class_prefix is uppercase
759
+			$class_prefix = strtoupper(trim($class_prefix));
760
+			// add class prefix ONCE!!!
761
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
762
+		}
763
+		$class_name = $this->_dependency_map->get_alias($class_name);
764
+		$class_exists = class_exists($class_name);
765
+		// if we're only loading the class and it already exists, then let's just return true immediately
766
+		if ($load_only && $class_exists) {
767
+			return true;
768
+		}
769
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
770
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
771
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
772
+		if ($this->_cache_on && $cache && ! $load_only) {
773
+			// return object if it's already cached
774
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix);
775
+			if ($cached_class !== null) {
776
+				return $cached_class;
777
+			}
778
+		}
779
+		// if the class doesn't already exist.. then we need to try and find the file and load it
780
+		if (! $class_exists) {
781
+			// get full path to file
782
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
783
+			// load the file
784
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
785
+			// if loading failed, or we are only loading a file but NOT instantiating an object
786
+			if (! $loaded || $load_only) {
787
+				// return boolean if only loading, or null if an object was expected
788
+				return $load_only
789
+					? $loaded
790
+					: null;
791
+			}
792
+		}
793
+		// instantiate the requested object
794
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
795
+		if ($this->_cache_on && $cache) {
796
+			// save it for later... kinda like gum  { : $
797
+			$this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
798
+		}
799
+		$this->_cache_on = true;
800
+		return $class_obj;
801
+	}
802
+
803
+
804
+
805
+	/**
806
+	 * @param string $class_name
807
+	 * @param string $default have to specify something, but not anything that will conflict
808
+	 * @return mixed|string
809
+	 */
810
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
811
+	{
812
+		return isset($this->_class_abbreviations[$class_name])
813
+			? $this->_class_abbreviations[$class_name]
814
+			: $default;
815
+	}
816
+
817
+	/**
818
+	 * attempts to find a cached version of the requested class
819
+	 * by looking in the following places:
820
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
821
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
822
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
823
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
824
+	 *
825
+	 * @param string $class_name
826
+	 * @param string $class_prefix
827
+	 * @return mixed
828
+	 */
829
+	protected function _get_cached_class($class_name, $class_prefix = '')
830
+	{
831
+		if ($class_name === 'EE_Registry') {
832
+			return $this;
833
+		}
834
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
835
+		$class_name = str_replace('\\', '_', $class_name);
836
+		// check if class has already been loaded, and return it if it has been
837
+		if (isset($this->{$class_abbreviation})) {
838
+			return $this->{$class_abbreviation};
839
+		}
840
+		if (isset ($this->{$class_name})) {
841
+			return $this->{$class_name};
842
+		}
843
+		if (isset ($this->LIB->{$class_name})) {
844
+			return $this->LIB->{$class_name};
845
+		}
846
+		if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
847
+			return $this->addons->{$class_name};
848
+		}
849
+		return null;
850
+	}
851
+
852
+
853
+
854
+	/**
855
+	 * removes a cached version of the requested class
856
+	 *
857
+	 * @param string  $class_name
858
+	 * @param boolean $addon
859
+	 * @return boolean
860
+	 */
861
+	public function clear_cached_class($class_name, $addon = false)
862
+	{
863
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
864
+		$class_name = str_replace('\\', '_', $class_name);
865
+		// check if class has already been loaded, and return it if it has been
866
+		if (isset($this->{$class_abbreviation})) {
867
+			$this->{$class_abbreviation} = null;
868
+			return true;
869
+		}
870
+		if (isset($this->{$class_name})) {
871
+			$this->{$class_name} = null;
872
+			return true;
873
+		}
874
+		if (isset($this->LIB->{$class_name})) {
875
+			unset($this->LIB->{$class_name});
876
+			return true;
877
+		}
878
+		if ($addon && isset($this->addons->{$class_name})) {
879
+			unset($this->addons->{$class_name});
880
+			return true;
881
+		}
882
+		return false;
883
+	}
884
+
885
+
886
+
887
+	/**
888
+	 * attempts to find a full valid filepath for the requested class.
889
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
890
+	 * then returns that path if the target file has been found and is readable
891
+	 *
892
+	 * @param string $class_name
893
+	 * @param string $type
894
+	 * @param array  $file_paths
895
+	 * @return string | bool
896
+	 */
897
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
898
+	{
899
+		// make sure $file_paths is an array
900
+		$file_paths = is_array($file_paths)
901
+			? $file_paths
902
+			: array($file_paths);
903
+		// cycle thru paths
904
+		foreach ($file_paths as $key => $file_path) {
905
+			// convert all separators to proper DS, if no filepath, then use EE_CLASSES
906
+			$file_path = $file_path
907
+				? str_replace(array('/', '\\'), DS, $file_path)
908
+				: EE_CLASSES;
909
+			// prep file type
910
+			$type = ! empty($type)
911
+				? trim($type, '.') . '.'
912
+				: '';
913
+			// build full file path
914
+			$file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
915
+			//does the file exist and can be read ?
916
+			if (is_readable($file_paths[$key])) {
917
+				return $file_paths[$key];
918
+			}
919
+		}
920
+		return false;
921
+	}
922
+
923
+
924
+
925
+	/**
926
+	 * basically just performs a require_once()
927
+	 * but with some error handling
928
+	 *
929
+	 * @param  string $path
930
+	 * @param  string $class_name
931
+	 * @param  string $type
932
+	 * @param  array  $file_paths
933
+	 * @return bool
934
+	 * @throws EE_Error
935
+	 * @throws ReflectionException
936
+	 */
937
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
938
+	{
939
+		// don't give up! you gotta...
940
+		try {
941
+			//does the file exist and can it be read ?
942
+			if (! $path) {
943
+				// so sorry, can't find the file
944
+				throw new EE_Error (
945
+					sprintf(
946
+						esc_html__(
947
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
948
+							'event_espresso'
949
+						),
950
+						trim($type, '.'),
951
+						$class_name,
952
+						'<br />' . implode(',<br />', $file_paths)
953
+					)
954
+				);
955
+			}
956
+			// get the file
957
+			require_once($path);
958
+			// if the class isn't already declared somewhere
959
+			if (class_exists($class_name, false) === false) {
960
+				// so sorry, not a class
961
+				throw new EE_Error(
962
+					sprintf(
963
+						esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
964
+						$type,
965
+						$path,
966
+						$class_name
967
+					)
968
+				);
969
+			}
970
+		} catch (EE_Error $e) {
971
+			$e->get_error();
972
+			return false;
973
+		}
974
+		return true;
975
+	}
976
+
977
+
978
+
979
+	/**
980
+	 * _create_object
981
+	 * Attempts to instantiate the requested class via any of the
982
+	 * commonly used instantiation methods employed throughout EE.
983
+	 * The priority for instantiation is as follows:
984
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
985
+	 *        - model objects via their 'new_instance_from_db' method
986
+	 *        - model objects via their 'new_instance' method
987
+	 *        - "singleton" classes" via their 'instance' method
988
+	 *    - standard instantiable classes via their __constructor
989
+	 * Prior to instantiation, if the classname exists in the dependency_map,
990
+	 * then the constructor for the requested class will be examined to determine
991
+	 * if any dependencies exist, and if they can be injected.
992
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
993
+	 *
994
+	 * @param string $class_name
995
+	 * @param array  $arguments
996
+	 * @param string $type
997
+	 * @param bool   $from_db
998
+	 * @return null|object
999
+	 * @throws EE_Error
1000
+	 * @throws ReflectionException
1001
+	 */
1002
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1003
+	{
1004
+		$class_obj = null;
1005
+		$instantiation_mode = '0) none';
1006
+		// don't give up! you gotta...
1007
+		try {
1008
+			// create reflection
1009
+			$reflector = $this->get_ReflectionClass($class_name);
1010
+			// make sure arguments are an array
1011
+			$arguments = is_array($arguments)
1012
+				? $arguments
1013
+				: array($arguments);
1014
+			// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1015
+			// else wrap it in an additional array so that it doesn't get split into multiple parameters
1016
+			$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1017
+				? $arguments
1018
+				: array($arguments);
1019
+			// attempt to inject dependencies ?
1020
+			if ($this->_dependency_map->has($class_name)) {
1021
+				$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1022
+			}
1023
+			// instantiate the class if possible
1024
+			if ($reflector->isAbstract()) {
1025
+				// nothing to instantiate, loading file was enough
1026
+				// does not throw an exception so $instantiation_mode is unused
1027
+				// $instantiation_mode = "1) no constructor abstract class";
1028
+				$class_obj = true;
1029
+			} else if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1030
+				// no constructor = static methods only... nothing to instantiate, loading file was enough
1031
+				$instantiation_mode = '2) no constructor but instantiable';
1032
+				$class_obj = $reflector->newInstance();
1033
+			} else if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1034
+				$instantiation_mode = '3) new_instance_from_db()';
1035
+				$class_obj = call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1036
+			} else if (method_exists($class_name, 'new_instance')) {
1037
+				$instantiation_mode = '4) new_instance()';
1038
+				$class_obj = call_user_func_array(array($class_name, 'new_instance'), $arguments);
1039
+			} else if (method_exists($class_name, 'instance')) {
1040
+				$instantiation_mode = '5) instance()';
1041
+				$class_obj = call_user_func_array(array($class_name, 'instance'), $arguments);
1042
+			} else if ($reflector->isInstantiable()) {
1043
+				$instantiation_mode = '6) constructor';
1044
+				$class_obj = $reflector->newInstanceArgs($arguments);
1045
+			} else {
1046
+				// heh ? something's not right !
1047
+				throw new EE_Error(
1048
+					sprintf(
1049
+						esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1050
+						$type,
1051
+						$class_name
1052
+					)
1053
+				);
1054
+			}
1055
+		} catch (Exception $e) {
1056
+			if (! $e instanceof EE_Error) {
1057
+				$e = new EE_Error(
1058
+					sprintf(
1059
+						esc_html__(
1060
+							'The following error occurred while attempting to instantiate "%1$s": %2$s %3$s %2$s instantiation mode : %4$s',
1061
+							'event_espresso'
1062
+						),
1063
+						$class_name,
1064
+						'<br />',
1065
+						$e->getMessage(),
1066
+						$instantiation_mode
1067
+					)
1068
+				);
1069
+			}
1070
+			$e->get_error();
1071
+		}
1072
+		return $class_obj;
1073
+	}
1074
+
1075
+
1076
+
1077
+	/**
1078
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1079
+	 * @param array $array
1080
+	 * @return bool
1081
+	 */
1082
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1083
+	{
1084
+		return ! empty($array)
1085
+			? array_keys($array) === range(0, count($array) - 1)
1086
+			: true;
1087
+	}
1088
+
1089
+
1090
+
1091
+	/**
1092
+	 * getReflectionClass
1093
+	 * checks if a ReflectionClass object has already been generated for a class
1094
+	 * and returns that instead of creating a new one
1095
+	 *
1096
+	 * @param string $class_name
1097
+	 * @return ReflectionClass
1098
+	 * @throws ReflectionException
1099
+	 */
1100
+	public function get_ReflectionClass($class_name)
1101
+	{
1102
+		if (
1103
+			! isset($this->_reflectors[$class_name])
1104
+			|| ! $this->_reflectors[$class_name] instanceof ReflectionClass
1105
+		) {
1106
+			$this->_reflectors[$class_name] = new ReflectionClass($class_name);
1107
+		}
1108
+		return $this->_reflectors[$class_name];
1109
+	}
1110
+
1111
+
1112
+
1113
+	/**
1114
+	 * _resolve_dependencies
1115
+	 * examines the constructor for the requested class to determine
1116
+	 * if any dependencies exist, and if they can be injected.
1117
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1118
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1119
+	 * For example:
1120
+	 *        if attempting to load a class "Foo" with the following constructor:
1121
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1122
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1123
+	 *        but only IF they are NOT already present in the incoming arguments array,
1124
+	 *        and the correct classes can be loaded
1125
+	 *
1126
+	 * @param ReflectionClass $reflector
1127
+	 * @param string          $class_name
1128
+	 * @param array           $arguments
1129
+	 * @return array
1130
+	 * @throws EE_Error
1131
+	 * @throws ReflectionException
1132
+	 */
1133
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1134
+	{
1135
+		// let's examine the constructor
1136
+		$constructor = $reflector->getConstructor();
1137
+		// whu? huh? nothing?
1138
+		if (! $constructor) {
1139
+			return $arguments;
1140
+		}
1141
+		// get constructor parameters
1142
+		$params = $constructor->getParameters();
1143
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1144
+		$argument_keys = array_keys($arguments);
1145
+		// now loop thru all of the constructors expected parameters
1146
+		foreach ($params as $index => $param) {
1147
+			// is this a dependency for a specific class ?
1148
+			$param_class = $param->getClass()
1149
+				? $param->getClass()->name
1150
+				: null;
1151
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1152
+			$param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1153
+				? $this->_dependency_map->get_alias($param_class, $class_name)
1154
+				: $param_class;
1155
+			if (
1156
+				// param is not even a class
1157
+				$param_class === null
1158
+				// and something already exists in the incoming arguments for this param
1159
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1160
+			) {
1161
+				// so let's skip this argument and move on to the next
1162
+				continue;
1163
+			}
1164
+			if (
1165
+				// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1166
+				$param_class !== null
1167
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1168
+				&& $arguments[$argument_keys[$index]] instanceof $param_class
1169
+			) {
1170
+				// skip this argument and move on to the next
1171
+				continue;
1172
+			}
1173
+			if (
1174
+				// parameter is type hinted as a class, and should be injected
1175
+				$param_class !== null
1176
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1177
+			) {
1178
+				$arguments = $this->_resolve_dependency(
1179
+					$class_name,
1180
+					$param_class,
1181
+					$arguments,
1182
+					$index,
1183
+					$argument_keys
1184
+				);
1185
+			} else {
1186
+				try {
1187
+					$arguments[$index] = $param->isDefaultValueAvailable()
1188
+						? $param->getDefaultValue()
1189
+						: null;
1190
+				} catch (ReflectionException $e) {
1191
+					throw new ReflectionException(
1192
+						sprintf(
1193
+							esc_html__('%1$s for parameter "$%2$s"', 'event_espresso'),
1194
+							$e->getMessage(),
1195
+							$param->getName()
1196
+						)
1197
+					);
1198
+				}
1199
+			}
1200
+		}
1201
+		return $arguments;
1202
+	}
1203
+
1204
+
1205
+
1206
+	/**
1207
+	 * @param string $class_name
1208
+	 * @param string $param_class
1209
+	 * @param array  $arguments
1210
+	 * @param mixed  $index
1211
+	 * @param array  $argument_keys
1212
+	 * @return array
1213
+	 * @throws EE_Error
1214
+	 * @throws ReflectionException
1215
+	 * @throws InvalidArgumentException
1216
+	 * @throws InvalidInterfaceException
1217
+	 * @throws InvalidDataTypeException
1218
+	 */
1219
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1220
+	{
1221
+		$dependency = null;
1222
+		// should dependency be loaded from cache ?
1223
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1224
+			$class_name,
1225
+			$param_class
1226
+		);
1227
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1228
+		// we might have a dependency...
1229
+		// let's MAYBE try and find it in our cache if that's what's been requested
1230
+		$cached_class = $cache_on
1231
+			? $this->_get_cached_class($param_class)
1232
+			: null;
1233
+		// and grab it if it exists
1234
+		if ($cached_class instanceof $param_class) {
1235
+			$dependency = $cached_class;
1236
+		} else if ($param_class !== $class_name) {
1237
+			// obtain the loader method from the dependency map
1238
+			$loader = $this->_dependency_map->class_loader($param_class);
1239
+			// is loader a custom closure ?
1240
+			if ($loader instanceof Closure) {
1241
+				$dependency = $loader($arguments);
1242
+			} else {
1243
+				// set the cache on property for the recursive loading call
1244
+				$this->_cache_on = $cache_on;
1245
+				// if not, then let's try and load it via the registry
1246
+				if ($loader && method_exists($this, $loader)) {
1247
+					$dependency = $this->{$loader}($param_class);
1248
+				} else {
1249
+					$dependency = LoaderFactory::getLoader()->load(
1250
+						$param_class,
1251
+						array(),
1252
+						$cache_on
1253
+					);
1254
+				}
1255
+			}
1256
+		}
1257
+		// did we successfully find the correct dependency ?
1258
+		if ($dependency instanceof $param_class) {
1259
+			// then let's inject it into the incoming array of arguments at the correct location
1260
+			$arguments[$index] = $dependency;
1261
+		}
1262
+		return $arguments;
1263
+	}
1264
+
1265
+
1266
+
1267
+	/**
1268
+	 * _set_cached_class
1269
+	 * attempts to cache the instantiated class locally
1270
+	 * in one of the following places, in the following order:
1271
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1272
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1273
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1274
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1275
+	 *
1276
+	 * @param object $class_obj
1277
+	 * @param string $class_name
1278
+	 * @param string $class_prefix
1279
+	 * @param bool   $from_db
1280
+	 * @return void
1281
+	 */
1282
+	protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1283
+	{
1284
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1285
+			return;
1286
+		}
1287
+		// return newly instantiated class
1288
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1289
+		if ($class_abbreviation) {
1290
+			$this->{$class_abbreviation} = $class_obj;
1291
+			return;
1292
+		}
1293
+		$class_name = str_replace('\\', '_', $class_name);
1294
+		if (property_exists($this, $class_name)) {
1295
+			$this->{$class_name} = $class_obj;
1296
+			return;
1297
+		}
1298
+		if ($class_prefix === 'addon') {
1299
+			$this->addons->{$class_name} = $class_obj;
1300
+			return;
1301
+		}
1302
+		if (! $from_db) {
1303
+			$this->LIB->{$class_name} = $class_obj;
1304
+		}
1305
+	}
1306
+
1307
+
1308
+
1309
+	/**
1310
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1311
+	 *
1312
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1313
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1314
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1315
+	 * @param array  $arguments
1316
+	 * @return object
1317
+	 */
1318
+	public static function factory($classname, $arguments = array())
1319
+	{
1320
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1321
+		if ($loader instanceof Closure) {
1322
+			return $loader($arguments);
1323
+		}
1324
+		if (method_exists(self::instance(), $loader)) {
1325
+			return self::instance()->{$loader}($classname, $arguments);
1326
+		}
1327
+		return null;
1328
+	}
1329
+
1330
+
1331
+
1332
+	/**
1333
+	 * Gets the addon by its name/slug (not classname. For that, just
1334
+	 * use the classname as the property name on EE_Config::instance()->addons)
1335
+	 *
1336
+	 * @param string $name
1337
+	 * @return EE_Addon
1338
+	 */
1339
+	public function get_addon_by_name($name)
1340
+	{
1341
+		foreach ($this->addons as $addon) {
1342
+			if ($addon->name() === $name) {
1343
+				return $addon;
1344
+			}
1345
+		}
1346
+		return null;
1347
+	}
1348
+
1349
+
1350
+
1351
+	/**
1352
+	 * Gets an array of all the registered addons, where the keys are their names. (ie, what each returns for their
1353
+	 * name() function) They're already available on EE_Config::instance()->addons as properties, where each property's
1354
+	 * name is the addon's classname. So if you just want to get the addon by classname, use
1355
+	 * EE_Config::instance()->addons->{classname}
1356
+	 *
1357
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1358
+	 */
1359
+	public function get_addons_by_name()
1360
+	{
1361
+		$addons = array();
1362
+		foreach ($this->addons as $addon) {
1363
+			$addons[$addon->name()] = $addon;
1364
+		}
1365
+		return $addons;
1366
+	}
1367
+
1368
+
1369
+
1370
+	/**
1371
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1372
+	 * a stale copy of it around
1373
+	 *
1374
+	 * @param string $model_name
1375
+	 * @return \EEM_Base
1376
+	 * @throws \EE_Error
1377
+	 */
1378
+	public function reset_model($model_name)
1379
+	{
1380
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1381
+			? "EEM_{$model_name}"
1382
+			: $model_name;
1383
+		if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1384
+			return null;
1385
+		}
1386
+		//get that model reset it and make sure we nuke the old reference to it
1387
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name
1388
+			&& is_callable(
1389
+				array($model_class_name, 'reset')
1390
+			)) {
1391
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1392
+		} else {
1393
+			throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1394
+		}
1395
+		return $this->LIB->{$model_class_name};
1396
+	}
1397
+
1398
+
1399
+
1400
+	/**
1401
+	 * Resets the registry.
1402
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1403
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1404
+	 * - $_dependency_map
1405
+	 * - $_class_abbreviations
1406
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1407
+	 * - $REQ:  Still on the same request so no need to change.
1408
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1409
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1410
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1411
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1412
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1413
+	 *             switch or on the restore.
1414
+	 * - $modules
1415
+	 * - $shortcodes
1416
+	 * - $widgets
1417
+	 *
1418
+	 * @param boolean $hard             [deprecated]
1419
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1420
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1421
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1422
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1423
+	 *                                  client
1424
+	 *                                  code instead can just change the model context to a different blog id if
1425
+	 *                                  necessary
1426
+	 * @return EE_Registry
1427
+	 * @throws EE_Error
1428
+	 * @throws ReflectionException
1429
+	 */
1430
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1431
+	{
1432
+		$instance = self::instance();
1433
+		$instance->_cache_on = true;
1434
+		// reset some "special" classes
1435
+		EEH_Activation::reset();
1436
+		$hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1437
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1438
+		$instance->CART = null;
1439
+		$instance->MRM = null;
1440
+		$instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1441
+		//messages reset
1442
+		EED_Messages::reset();
1443
+		//handle of objects cached on LIB
1444
+		foreach (array('LIB', 'modules') as $cache) {
1445
+			foreach ($instance->{$cache} as $class_name => $class) {
1446
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1447
+					unset($instance->{$cache}->{$class_name});
1448
+				}
1449
+			}
1450
+		}
1451
+		return $instance;
1452
+	}
1453
+
1454
+
1455
+
1456
+	/**
1457
+	 * if passed object implements ResettableInterface, then call it's reset() method
1458
+	 * if passed object implements InterminableInterface, then return false,
1459
+	 * to indicate that it should NOT be cleared from the Registry cache
1460
+	 *
1461
+	 * @param      $object
1462
+	 * @param bool $reset_models
1463
+	 * @return bool returns true if cached object should be unset
1464
+	 */
1465
+	private static function _reset_and_unset_object($object, $reset_models)
1466
+	{
1467
+		if (! is_object($object)) {
1468
+			// don't unset anything that's not an object
1469
+			return false;
1470
+		}
1471
+		if ($object instanceof EED_Module) {
1472
+			$object::reset();
1473
+			// don't unset modules
1474
+			return false;
1475
+		}
1476
+		if ($object instanceof ResettableInterface) {
1477
+			if ($object instanceof EEM_Base) {
1478
+				if ($reset_models) {
1479
+					$object->reset();
1480
+					return true;
1481
+				}
1482
+				return false;
1483
+			}
1484
+			$object->reset();
1485
+			return true;
1486
+		}
1487
+		if (! $object instanceof InterminableInterface) {
1488
+			return true;
1489
+		}
1490
+		return false;
1491
+	}
1492
+
1493
+
1494
+
1495
+	/**
1496
+	 * Gets all the custom post type models defined
1497
+	 *
1498
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1499
+	 */
1500
+	public function cpt_models()
1501
+	{
1502
+		$cpt_models = array();
1503
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1504
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1505
+				$cpt_models[$short_name] = $classname;
1506
+			}
1507
+		}
1508
+		return $cpt_models;
1509
+	}
1510
+
1511
+
1512
+
1513
+	/**
1514
+	 * @return \EE_Config
1515
+	 */
1516
+	public static function CFG()
1517
+	{
1518
+		return self::instance()->CFG;
1519
+	}
1520 1520
 
1521 1521
 
1522 1522
 }
Please login to merge, or discard this patch.
Spacing   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
     public static function instance(EE_Dependency_Map $dependency_map = null)
177 177
     {
178 178
         // check if class object is instantiated
179
-        if (! self::$_instance instanceof EE_Registry) {
179
+        if ( ! self::$_instance instanceof EE_Registry) {
180 180
             self::$_instance = new self($dependency_map);
181 181
         }
182 182
         return self::$_instance;
@@ -266,13 +266,13 @@  discard block
 block discarded – undo
266 266
      */
267 267
     public static function localize_i18n_js_strings()
268 268
     {
269
-        $i18n_js_strings = (array)self::$i18n_js_strings;
269
+        $i18n_js_strings = (array) self::$i18n_js_strings;
270 270
         foreach ($i18n_js_strings as $key => $value) {
271 271
             if (is_scalar($value)) {
272
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
272
+                $i18n_js_strings[$key] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
273 273
             }
274 274
         }
275
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
275
+        return '/* <![CDATA[ */ var eei18n = '.wp_json_encode($i18n_js_strings).'; /* ]]> */';
276 276
     }
277 277
 
278 278
 
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
             $module_class = get_class($module);
289 289
             $this->modules->{$module_class} = $module;
290 290
         } else {
291
-            if (! class_exists('EE_Module_Request_Router')) {
291
+            if ( ! class_exists('EE_Module_Request_Router')) {
292 292
                 $this->load_core('Module_Request_Router');
293 293
             }
294 294
             EE_Module_Request_Router::module_factory($module);
@@ -328,10 +328,10 @@  discard block
 block discarded – undo
328 328
                 EE_CORE,
329 329
                 EE_ADMIN,
330 330
                 EE_CPTS,
331
-                EE_CORE . 'data_migration_scripts' . DS,
332
-                EE_CORE . 'capabilities' . DS,
333
-                EE_CORE . 'request_stack' . DS,
334
-                EE_CORE . 'middleware' . DS,
331
+                EE_CORE.'data_migration_scripts'.DS,
332
+                EE_CORE.'capabilities'.DS,
333
+                EE_CORE.'request_stack'.DS,
334
+                EE_CORE.'middleware'.DS,
335 335
             )
336 336
         );
337 337
         // retrieve instantiated class
@@ -364,7 +364,7 @@  discard block
 block discarded – undo
364 364
         $service_paths = apply_filters(
365 365
             'FHEE__EE_Registry__load_service__service_paths',
366 366
             array(
367
-                EE_CORE . 'services' . DS,
367
+                EE_CORE.'services'.DS,
368 368
             )
369 369
         );
370 370
         // retrieve instantiated class
@@ -490,10 +490,10 @@  discard block
 block discarded – undo
490 490
     {
491 491
         $paths = array(
492 492
             EE_LIBRARIES,
493
-            EE_LIBRARIES . 'messages' . DS,
494
-            EE_LIBRARIES . 'shortcodes' . DS,
495
-            EE_LIBRARIES . 'qtips' . DS,
496
-            EE_LIBRARIES . 'payment_methods' . DS,
493
+            EE_LIBRARIES.'messages'.DS,
494
+            EE_LIBRARIES.'shortcodes'.DS,
495
+            EE_LIBRARIES.'qtips'.DS,
496
+            EE_LIBRARIES.'payment_methods'.DS,
497 497
         );
498 498
         // retrieve instantiated class
499 499
         return $this->_load(
@@ -556,10 +556,10 @@  discard block
 block discarded – undo
556 556
     public function load_model_class($class_name, $arguments = array(), $load_only = true)
557 557
     {
558 558
         $paths = array(
559
-            EE_MODELS . 'fields' . DS,
560
-            EE_MODELS . 'helpers' . DS,
561
-            EE_MODELS . 'relations' . DS,
562
-            EE_MODELS . 'strategies' . DS,
559
+            EE_MODELS.'fields'.DS,
560
+            EE_MODELS.'helpers'.DS,
561
+            EE_MODELS.'relations'.DS,
562
+            EE_MODELS.'strategies'.DS,
563 563
         );
564 564
         // retrieve instantiated class
565 565
         return $this->_load(
@@ -675,13 +675,13 @@  discard block
 block discarded – undo
675 675
     ) {
676 676
         $class_name = ltrim($class_name, '\\');
677 677
         $class_name = $this->_dependency_map->get_alias($class_name);
678
-        if (! class_exists($class_name)) {
678
+        if ( ! class_exists($class_name)) {
679 679
             // maybe the class is registered with a preceding \
680 680
             $class_name = strpos($class_name, '\\') !== 0
681
-                ? '\\' . $class_name
681
+                ? '\\'.$class_name
682 682
                 : $class_name;
683 683
             // still doesn't exist ?
684
-            if (! class_exists($class_name)) {
684
+            if ( ! class_exists($class_name)) {
685 685
                 return null;
686 686
             }
687 687
         }
@@ -754,11 +754,11 @@  discard block
 block discarded – undo
754 754
         // strip php file extension
755 755
         $class_name = str_replace('.php', '', trim($class_name));
756 756
         // does the class have a prefix ?
757
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
757
+        if ( ! empty($class_prefix) && $class_prefix !== 'addon') {
758 758
             // make sure $class_prefix is uppercase
759 759
             $class_prefix = strtoupper(trim($class_prefix));
760 760
             // add class prefix ONCE!!!
761
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
761
+            $class_name = $class_prefix.str_replace($class_prefix, '', $class_name);
762 762
         }
763 763
         $class_name = $this->_dependency_map->get_alias($class_name);
764 764
         $class_exists = class_exists($class_name);
@@ -777,13 +777,13 @@  discard block
 block discarded – undo
777 777
             }
778 778
         }
779 779
         // if the class doesn't already exist.. then we need to try and find the file and load it
780
-        if (! $class_exists) {
780
+        if ( ! $class_exists) {
781 781
             // get full path to file
782 782
             $path = $this->_resolve_path($class_name, $type, $file_paths);
783 783
             // load the file
784 784
             $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
785 785
             // if loading failed, or we are only loading a file but NOT instantiating an object
786
-            if (! $loaded || $load_only) {
786
+            if ( ! $loaded || $load_only) {
787 787
                 // return boolean if only loading, or null if an object was expected
788 788
                 return $load_only
789 789
                     ? $loaded
@@ -908,10 +908,10 @@  discard block
 block discarded – undo
908 908
                 : EE_CLASSES;
909 909
             // prep file type
910 910
             $type = ! empty($type)
911
-                ? trim($type, '.') . '.'
911
+                ? trim($type, '.').'.'
912 912
                 : '';
913 913
             // build full file path
914
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
914
+            $file_paths[$key] = rtrim($file_path, DS).DS.$class_name.'.'.$type.'php';
915 915
             //does the file exist and can be read ?
916 916
             if (is_readable($file_paths[$key])) {
917 917
                 return $file_paths[$key];
@@ -939,9 +939,9 @@  discard block
 block discarded – undo
939 939
         // don't give up! you gotta...
940 940
         try {
941 941
             //does the file exist and can it be read ?
942
-            if (! $path) {
942
+            if ( ! $path) {
943 943
                 // so sorry, can't find the file
944
-                throw new EE_Error (
944
+                throw new EE_Error(
945 945
                     sprintf(
946 946
                         esc_html__(
947 947
                             'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
@@ -949,7 +949,7 @@  discard block
 block discarded – undo
949 949
                         ),
950 950
                         trim($type, '.'),
951 951
                         $class_name,
952
-                        '<br />' . implode(',<br />', $file_paths)
952
+                        '<br />'.implode(',<br />', $file_paths)
953 953
                     )
954 954
                 );
955 955
             }
@@ -1053,7 +1053,7 @@  discard block
 block discarded – undo
1053 1053
                 );
1054 1054
             }
1055 1055
         } catch (Exception $e) {
1056
-            if (! $e instanceof EE_Error) {
1056
+            if ( ! $e instanceof EE_Error) {
1057 1057
                 $e = new EE_Error(
1058 1058
                     sprintf(
1059 1059
                         esc_html__(
@@ -1135,7 +1135,7 @@  discard block
 block discarded – undo
1135 1135
         // let's examine the constructor
1136 1136
         $constructor = $reflector->getConstructor();
1137 1137
         // whu? huh? nothing?
1138
-        if (! $constructor) {
1138
+        if ( ! $constructor) {
1139 1139
             return $arguments;
1140 1140
         }
1141 1141
         // get constructor parameters
@@ -1299,7 +1299,7 @@  discard block
 block discarded – undo
1299 1299
             $this->addons->{$class_name} = $class_obj;
1300 1300
             return;
1301 1301
         }
1302
-        if (! $from_db) {
1302
+        if ( ! $from_db) {
1303 1303
             $this->LIB->{$class_name} = $class_obj;
1304 1304
         }
1305 1305
     }
@@ -1380,7 +1380,7 @@  discard block
 block discarded – undo
1380 1380
         $model_class_name = strpos($model_name, 'EEM_') !== 0
1381 1381
             ? "EEM_{$model_name}"
1382 1382
             : $model_name;
1383
-        if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1383
+        if ( ! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1384 1384
             return null;
1385 1385
         }
1386 1386
         //get that model reset it and make sure we nuke the old reference to it
@@ -1433,7 +1433,7 @@  discard block
 block discarded – undo
1433 1433
         $instance->_cache_on = true;
1434 1434
         // reset some "special" classes
1435 1435
         EEH_Activation::reset();
1436
-        $hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1436
+        $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1437 1437
         $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1438 1438
         $instance->CART = null;
1439 1439
         $instance->MRM = null;
@@ -1464,7 +1464,7 @@  discard block
 block discarded – undo
1464 1464
      */
1465 1465
     private static function _reset_and_unset_object($object, $reset_models)
1466 1466
     {
1467
-        if (! is_object($object)) {
1467
+        if ( ! is_object($object)) {
1468 1468
             // don't unset anything that's not an object
1469 1469
             return false;
1470 1470
         }
@@ -1484,7 +1484,7 @@  discard block
 block discarded – undo
1484 1484
             $object->reset();
1485 1485
             return true;
1486 1486
         }
1487
-        if (! $object instanceof InterminableInterface) {
1487
+        if ( ! $object instanceof InterminableInterface) {
1488 1488
             return true;
1489 1489
         }
1490 1490
         return false;
Please login to merge, or discard this patch.