Completed
Branch FET-10325-remove-caffeinated-m... (bd231b)
by
unknown
173:44 queued 162:57
created
core/helpers/EEH_Activation.helper.php 3 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   +1694 added lines, -1694 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
 
@@ -14,231 +14,231 @@  discard block
 block discarded – undo
14 14
 class EEH_Activation
15 15
 {
16 16
 
17
-    /**
18
-     * constant used to indicate a cron task is no longer in use
19
-     */
20
-    const cron_task_no_longer_in_use = 'no_longer_in_use';
21
-
22
-    /**
23
-     * option name that will indicate whether or not we still
24
-     * need to create EE's folders in the uploads directory
25
-     * (because if EE was installed without file system access,
26
-     * we need to request credentials before we can create them)
27
-     */
28
-    const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
29
-
30
-    /**
31
-     * WP_User->ID
32
-     *
33
-     * @var int
34
-     */
35
-    private static $_default_creator_id;
36
-
37
-    /**
38
-     * indicates whether or not we've already verified core's default data during this request,
39
-     * because after migrations are done, any addons activated while in maintenance mode
40
-     * will want to setup their own default data, and they might hook into core's default data
41
-     * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
42
-     * This prevents doing that for EVERY single addon.
43
-     *
44
-     * @var boolean
45
-     */
46
-    protected static $_initialized_db_content_already_in_this_request = false;
47
-
48
-    /**
49
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
50
-     */
51
-    private static $table_analysis;
52
-
53
-    /**
54
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
55
-     */
56
-    private static $table_manager;
57
-
58
-
59
-    /**
60
-     * @return \EventEspresso\core\services\database\TableAnalysis
61
-     */
62
-    public static function getTableAnalysis()
63
-    {
64
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
65
-            self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
66
-        }
67
-        return self::$table_analysis;
68
-    }
69
-
70
-
71
-    /**
72
-     * @return \EventEspresso\core\services\database\TableManager
73
-     */
74
-    public static function getTableManager()
75
-    {
76
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
77
-            self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
78
-        }
79
-        return self::$table_manager;
80
-    }
81
-
82
-
83
-    /**
84
-     *    _ensure_table_name_has_prefix
85
-     *
86
-     * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
87
-     * @access     public
88
-     * @static
89
-     * @param $table_name
90
-     * @return string
91
-     */
92
-    public static function ensure_table_name_has_prefix($table_name)
93
-    {
94
-        return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
95
-    }
96
-
97
-
98
-    /**
99
-     *    system_initialization
100
-     *    ensures the EE configuration settings are loaded with at least default options set
101
-     *    and that all critical EE pages have been generated with the appropriate shortcodes in place
102
-     *
103
-     * @access public
104
-     * @static
105
-     * @return void
106
-     */
107
-    public static function system_initialization()
108
-    {
109
-        EEH_Activation::reset_and_update_config();
110
-        //which is fired BEFORE activation of plugin anyways
111
-        EEH_Activation::verify_default_pages_exist();
112
-    }
113
-
114
-
115
-    /**
116
-     * Sets the database schema and creates folders. This should
117
-     * be called on plugin activation and reactivation
118
-     *
119
-     * @return boolean success, whether the database and folders are setup properly
120
-     * @throws \EE_Error
121
-     */
122
-    public static function initialize_db_and_folders()
123
-    {
124
-        $good_filesystem = EEH_Activation::create_upload_directories();
125
-        $good_db         = EEH_Activation::create_database_tables();
126
-        return $good_filesystem && $good_db;
127
-    }
128
-
129
-
130
-    /**
131
-     * assuming we have an up-to-date database schema, this will populate it
132
-     * with default and initial data. This should be called
133
-     * upon activation of a new plugin, reactivation, and at the end
134
-     * of running migration scripts
135
-     *
136
-     * @throws \EE_Error
137
-     */
138
-    public static function initialize_db_content()
139
-    {
140
-        //let's avoid doing all this logic repeatedly, especially when addons are requesting it
141
-        if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
142
-            return;
143
-        }
144
-        EEH_Activation::$_initialized_db_content_already_in_this_request = true;
145
-
146
-        EEH_Activation::initialize_system_questions();
147
-        EEH_Activation::insert_default_status_codes();
148
-        EEH_Activation::generate_default_message_templates();
149
-        EEH_Activation::create_no_ticket_prices_array();
150
-        EE_Registry::instance()->CAP->init_caps();
151
-
152
-        EEH_Activation::validate_messages_system();
153
-        EEH_Activation::insert_default_payment_methods();
154
-        //in case we've
155
-        EEH_Activation::remove_cron_tasks();
156
-        EEH_Activation::create_cron_tasks();
157
-        // remove all TXN locks since that is being done via extra meta now
158
-        delete_option('ee_locked_transactions');
159
-        //also, check for CAF default db content
160
-        do_action('AHEE__EEH_Activation__initialize_db_content');
161
-        //also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
162
-        //which users really won't care about on initial activation
163
-        EE_Error::overwrite_success();
164
-    }
165
-
166
-
167
-    /**
168
-     * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
169
-     * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
170
-     * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
171
-     * (null)
172
-     *
173
-     * @param string $which_to_include can be 'current' (ones that are currently in use),
174
-     *                                 'old' (only returns ones that should no longer be used),or 'all',
175
-     * @return array
176
-     * @throws \EE_Error
177
-     */
178
-    public static function get_cron_tasks($which_to_include)
179
-    {
180
-        $cron_tasks = apply_filters(
181
-            'FHEE__EEH_Activation__get_cron_tasks',
182
-            array(
183
-                'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
17
+	/**
18
+	 * constant used to indicate a cron task is no longer in use
19
+	 */
20
+	const cron_task_no_longer_in_use = 'no_longer_in_use';
21
+
22
+	/**
23
+	 * option name that will indicate whether or not we still
24
+	 * need to create EE's folders in the uploads directory
25
+	 * (because if EE was installed without file system access,
26
+	 * we need to request credentials before we can create them)
27
+	 */
28
+	const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
29
+
30
+	/**
31
+	 * WP_User->ID
32
+	 *
33
+	 * @var int
34
+	 */
35
+	private static $_default_creator_id;
36
+
37
+	/**
38
+	 * indicates whether or not we've already verified core's default data during this request,
39
+	 * because after migrations are done, any addons activated while in maintenance mode
40
+	 * will want to setup their own default data, and they might hook into core's default data
41
+	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
42
+	 * This prevents doing that for EVERY single addon.
43
+	 *
44
+	 * @var boolean
45
+	 */
46
+	protected static $_initialized_db_content_already_in_this_request = false;
47
+
48
+	/**
49
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
50
+	 */
51
+	private static $table_analysis;
52
+
53
+	/**
54
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
55
+	 */
56
+	private static $table_manager;
57
+
58
+
59
+	/**
60
+	 * @return \EventEspresso\core\services\database\TableAnalysis
61
+	 */
62
+	public static function getTableAnalysis()
63
+	{
64
+		if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
65
+			self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
66
+		}
67
+		return self::$table_analysis;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @return \EventEspresso\core\services\database\TableManager
73
+	 */
74
+	public static function getTableManager()
75
+	{
76
+		if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
77
+			self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
78
+		}
79
+		return self::$table_manager;
80
+	}
81
+
82
+
83
+	/**
84
+	 *    _ensure_table_name_has_prefix
85
+	 *
86
+	 * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
87
+	 * @access     public
88
+	 * @static
89
+	 * @param $table_name
90
+	 * @return string
91
+	 */
92
+	public static function ensure_table_name_has_prefix($table_name)
93
+	{
94
+		return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
95
+	}
96
+
97
+
98
+	/**
99
+	 *    system_initialization
100
+	 *    ensures the EE configuration settings are loaded with at least default options set
101
+	 *    and that all critical EE pages have been generated with the appropriate shortcodes in place
102
+	 *
103
+	 * @access public
104
+	 * @static
105
+	 * @return void
106
+	 */
107
+	public static function system_initialization()
108
+	{
109
+		EEH_Activation::reset_and_update_config();
110
+		//which is fired BEFORE activation of plugin anyways
111
+		EEH_Activation::verify_default_pages_exist();
112
+	}
113
+
114
+
115
+	/**
116
+	 * Sets the database schema and creates folders. This should
117
+	 * be called on plugin activation and reactivation
118
+	 *
119
+	 * @return boolean success, whether the database and folders are setup properly
120
+	 * @throws \EE_Error
121
+	 */
122
+	public static function initialize_db_and_folders()
123
+	{
124
+		$good_filesystem = EEH_Activation::create_upload_directories();
125
+		$good_db         = EEH_Activation::create_database_tables();
126
+		return $good_filesystem && $good_db;
127
+	}
128
+
129
+
130
+	/**
131
+	 * assuming we have an up-to-date database schema, this will populate it
132
+	 * with default and initial data. This should be called
133
+	 * upon activation of a new plugin, reactivation, and at the end
134
+	 * of running migration scripts
135
+	 *
136
+	 * @throws \EE_Error
137
+	 */
138
+	public static function initialize_db_content()
139
+	{
140
+		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
141
+		if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
142
+			return;
143
+		}
144
+		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
145
+
146
+		EEH_Activation::initialize_system_questions();
147
+		EEH_Activation::insert_default_status_codes();
148
+		EEH_Activation::generate_default_message_templates();
149
+		EEH_Activation::create_no_ticket_prices_array();
150
+		EE_Registry::instance()->CAP->init_caps();
151
+
152
+		EEH_Activation::validate_messages_system();
153
+		EEH_Activation::insert_default_payment_methods();
154
+		//in case we've
155
+		EEH_Activation::remove_cron_tasks();
156
+		EEH_Activation::create_cron_tasks();
157
+		// remove all TXN locks since that is being done via extra meta now
158
+		delete_option('ee_locked_transactions');
159
+		//also, check for CAF default db content
160
+		do_action('AHEE__EEH_Activation__initialize_db_content');
161
+		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
162
+		//which users really won't care about on initial activation
163
+		EE_Error::overwrite_success();
164
+	}
165
+
166
+
167
+	/**
168
+	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
169
+	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
170
+	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
171
+	 * (null)
172
+	 *
173
+	 * @param string $which_to_include can be 'current' (ones that are currently in use),
174
+	 *                                 'old' (only returns ones that should no longer be used),or 'all',
175
+	 * @return array
176
+	 * @throws \EE_Error
177
+	 */
178
+	public static function get_cron_tasks($which_to_include)
179
+	{
180
+		$cron_tasks = apply_filters(
181
+			'FHEE__EEH_Activation__get_cron_tasks',
182
+			array(
183
+				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
184 184
 //				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
185
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
186
-                //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
187
-            )
188
-        );
189
-        if ($which_to_include === 'old') {
190
-            $cron_tasks = array_filter(
191
-                $cron_tasks,
192
-                function ($value) {
193
-                    return $value === EEH_Activation::cron_task_no_longer_in_use;
194
-                }
195
-            );
196
-        } elseif ($which_to_include === 'current') {
197
-            $cron_tasks = array_filter($cron_tasks);
198
-        } elseif (WP_DEBUG && $which_to_include !== 'all') {
199
-            throw new EE_Error(
200
-                sprintf(
201
-                    __(
202
-                        'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
203
-                        'event_espresso'
204
-                    ),
205
-                    $which_to_include
206
-                )
207
-            );
208
-        }
209
-        return $cron_tasks;
210
-    }
211
-
212
-
213
-    /**
214
-     * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
215
-     *
216
-     * @throws \EE_Error
217
-     */
218
-    public static function create_cron_tasks()
219
-    {
220
-
221
-        foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
222
-            if (! wp_next_scheduled($hook_name)) {
223
-                wp_schedule_event(time(), $frequency, $hook_name);
224
-            }
225
-        }
226
-
227
-    }
228
-
229
-
230
-    /**
231
-     * Remove the currently-existing and now-removed cron tasks.
232
-     *
233
-     * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
234
-     * @throws \EE_Error
235
-     */
236
-    public static function remove_cron_tasks($remove_all = true)
237
-    {
238
-        $cron_tasks_to_remove = $remove_all ? 'all' : 'old';
239
-        $crons                = _get_cron_array();
240
-        $crons                = is_array($crons) ? $crons : array();
241
-        /* reminder of what $crons look like:
185
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
186
+				//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
187
+			)
188
+		);
189
+		if ($which_to_include === 'old') {
190
+			$cron_tasks = array_filter(
191
+				$cron_tasks,
192
+				function ($value) {
193
+					return $value === EEH_Activation::cron_task_no_longer_in_use;
194
+				}
195
+			);
196
+		} elseif ($which_to_include === 'current') {
197
+			$cron_tasks = array_filter($cron_tasks);
198
+		} elseif (WP_DEBUG && $which_to_include !== 'all') {
199
+			throw new EE_Error(
200
+				sprintf(
201
+					__(
202
+						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
203
+						'event_espresso'
204
+					),
205
+					$which_to_include
206
+				)
207
+			);
208
+		}
209
+		return $cron_tasks;
210
+	}
211
+
212
+
213
+	/**
214
+	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
215
+	 *
216
+	 * @throws \EE_Error
217
+	 */
218
+	public static function create_cron_tasks()
219
+	{
220
+
221
+		foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
222
+			if (! wp_next_scheduled($hook_name)) {
223
+				wp_schedule_event(time(), $frequency, $hook_name);
224
+			}
225
+		}
226
+
227
+	}
228
+
229
+
230
+	/**
231
+	 * Remove the currently-existing and now-removed cron tasks.
232
+	 *
233
+	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
234
+	 * @throws \EE_Error
235
+	 */
236
+	public static function remove_cron_tasks($remove_all = true)
237
+	{
238
+		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
239
+		$crons                = _get_cron_array();
240
+		$crons                = is_array($crons) ? $crons : array();
241
+		/* reminder of what $crons look like:
242 242
          * Top-level keys are timestamps, and their values are arrays.
243 243
          * The 2nd level arrays have keys with each of the cron task hook names to run at that time
244 244
          * and their values are arrays.
@@ -255,966 +255,966 @@  discard block
 block discarded – undo
255 255
          *					...
256 256
          *      ...
257 257
          */
258
-        $ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
259
-        foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
260
-            if (is_array($hooks_to_fire_at_time)) {
261
-                foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
262
-                    if (isset($ee_cron_tasks_to_remove[$hook_name])
263
-                        && is_array($ee_cron_tasks_to_remove[$hook_name])
264
-                    ) {
265
-                        unset($crons[$timestamp][$hook_name]);
266
-                    }
267
-                }
268
-                //also take care of any empty cron timestamps.
269
-                if (empty($hooks_to_fire_at_time)) {
270
-                    unset($crons[$timestamp]);
271
-                }
272
-            }
273
-        }
274
-        _set_cron_array($crons);
275
-    }
276
-
277
-
278
-    /**
279
-     *    CPT_initialization
280
-     *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
281
-     *
282
-     * @access public
283
-     * @static
284
-     * @return void
285
-     */
286
-    public static function CPT_initialization()
287
-    {
288
-        // register Custom Post Types
289
-        EE_Registry::instance()->load_core('Register_CPTs');
290
-        flush_rewrite_rules();
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     *    reset_and_update_config
297
-     * The following code was moved over from EE_Config so that it will no longer run on every request.
298
-     * If there is old calendar config data saved, then it will get converted on activation.
299
-     * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
300
-     *
301
-     * @access public
302
-     * @static
303
-     * @return void
304
-     */
305
-    public static function reset_and_update_config()
306
-    {
307
-        do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
308
-        add_filter(
309
-            'FHEE__EE_Config___load_core_config__config_settings',
310
-            array('EEH_Activation', 'migrate_old_config_data'),
311
-            10,
312
-            3
313
-        );
314
-        //EE_Config::reset();
315
-        if (! EE_Config::logging_enabled()) {
316
-            delete_option(EE_Config::LOG_NAME);
317
-        }
318
-    }
319
-
320
-
321
-    /**
322
-     *    load_calendar_config
323
-     *
324
-     * @access    public
325
-     * @return    void
326
-     */
327
-    public static function load_calendar_config()
328
-    {
329
-        // grab array of all plugin folders and loop thru it
330
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
331
-        if (empty($plugins)) {
332
-            return;
333
-        }
334
-        foreach ($plugins as $plugin_path) {
335
-            // grab plugin folder name from path
336
-            $plugin = basename($plugin_path);
337
-            // drill down to Espresso plugins
338
-            // then to calendar related plugins
339
-            if (
340
-                strpos($plugin, 'espresso') !== false
341
-                || strpos($plugin, 'Espresso') !== false
342
-                || strpos($plugin, 'ee4') !== false
343
-                || strpos($plugin, 'EE4') !== false
344
-                || strpos($plugin, 'calendar') !== false
345
-            ) {
346
-                // this is what we are looking for
347
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
348
-                // does it exist in this folder ?
349
-                if (is_readable($calendar_config)) {
350
-                    // YEAH! let's load it
351
-                    require_once($calendar_config);
352
-                }
353
-            }
354
-        }
355
-    }
356
-
357
-
358
-
359
-    /**
360
-     *    _migrate_old_config_data
361
-     *
362
-     * @access    public
363
-     * @param array|stdClass $settings
364
-     * @param string         $config
365
-     * @param \EE_Config     $EE_Config
366
-     * @return \stdClass
367
-     */
368
-    public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
369
-    {
370
-        $convert_from_array = array('addons');
371
-        // in case old settings were saved as an array
372
-        if (is_array($settings) && in_array($config, $convert_from_array)) {
373
-            // convert existing settings to an object
374
-            $config_array = $settings;
375
-            $settings = new stdClass();
376
-            foreach ($config_array as $key => $value) {
377
-                if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
378
-                    $EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
379
-                } else {
380
-                    $settings->{$key} = $value;
381
-                }
382
-            }
383
-            add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
384
-        }
385
-        return $settings;
386
-    }
387
-
388
-
389
-    /**
390
-     * deactivate_event_espresso
391
-     *
392
-     * @access public
393
-     * @static
394
-     * @return void
395
-     */
396
-    public static function deactivate_event_espresso()
397
-    {
398
-        // check permissions
399
-        if (current_user_can('activate_plugins')) {
400
-            deactivate_plugins(EE_PLUGIN_BASENAME, true);
401
-        }
402
-    }
403
-
404
-
405
-
406
-
407
-
408
-    /**
409
-     * verify_default_pages_exist
410
-     *
411
-     * @access public
412
-     * @static
413
-     * @return void
414
-     */
415
-    public static function verify_default_pages_exist()
416
-    {
417
-        $critical_page_problem = false;
418
-        $critical_pages = array(
419
-            array(
420
-                'id'   => 'reg_page_id',
421
-                'name' => __('Registration Checkout', 'event_espresso'),
422
-                'post' => null,
423
-                'code' => 'ESPRESSO_CHECKOUT',
424
-            ),
425
-            array(
426
-                'id'   => 'txn_page_id',
427
-                'name' => __('Transactions', 'event_espresso'),
428
-                'post' => null,
429
-                'code' => 'ESPRESSO_TXN_PAGE',
430
-            ),
431
-            array(
432
-                'id'   => 'thank_you_page_id',
433
-                'name' => __('Thank You', 'event_espresso'),
434
-                'post' => null,
435
-                'code' => 'ESPRESSO_THANK_YOU',
436
-            ),
437
-            array(
438
-                'id'   => 'cancel_page_id',
439
-                'name' => __('Registration Cancelled', 'event_espresso'),
440
-                'post' => null,
441
-                'code' => 'ESPRESSO_CANCELLED',
442
-            ),
443
-        );
444
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
445
-        foreach ($critical_pages as $critical_page) {
446
-            // is critical page ID set in config ?
447
-            if ($EE_Core_Config->{$critical_page['id']} !== false) {
448
-                // attempt to find post by ID
449
-                $critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
450
-            }
451
-            // no dice?
452
-            if ($critical_page['post'] === null) {
453
-                // attempt to find post by title
454
-                $critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
455
-                // still nothing?
456
-                if ($critical_page['post'] === null) {
457
-                    $critical_page = EEH_Activation::create_critical_page($critical_page);
458
-                    // REALLY? Still nothing ??!?!?
459
-                    if ($critical_page['post'] === null) {
460
-                        $msg = __(
461
-                            'The Event Espresso critical page configuration settings could not be updated.',
462
-                            'event_espresso'
463
-                        );
464
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
465
-                        break;
466
-                    }
467
-                }
468
-            }
469
-            // track post_shortcodes
470
-            if ($critical_page['post']) {
471
-                EEH_Activation::_track_critical_page_post_shortcodes($critical_page);
472
-            }
473
-            // check that Post ID matches critical page ID in config
474
-            if (
475
-                isset($critical_page['post']->ID)
476
-                && $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
477
-            ) {
478
-                //update Config with post ID
479
-                $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
480
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
481
-                    $msg = __(
482
-                        'The Event Espresso critical page configuration settings could not be updated.',
483
-                        'event_espresso'
484
-                    );
485
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
486
-                }
487
-            }
488
-            $critical_page_problem =
489
-                ! isset($critical_page['post']->post_status)
490
-                || $critical_page['post']->post_status !== 'publish'
491
-                || strpos($critical_page['post']->post_content, $critical_page['code']) === false
492
-                    ? true
493
-                    : $critical_page_problem;
494
-        }
495
-        if ($critical_page_problem) {
496
-            $msg = sprintf(
497
-                __(
498
-                    'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
499
-                    'event_espresso'
500
-                ),
501
-                '<a href="'
502
-                . admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
503
-                . '">'
504
-                . __('Event Espresso Critical Pages Settings', 'event_espresso')
505
-                . '</a>'
506
-            );
507
-            EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
508
-        }
509
-        if (EE_Error::has_notices()) {
510
-            EE_Error::get_notices(false, true, true);
511
-        }
512
-    }
513
-
514
-
515
-
516
-    /**
517
-     * Returns the first post which uses the specified shortcode
518
-     *
519
-     * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
520
-     *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
521
-     *                             "[ESPRESSO_THANK_YOU"
522
-     *                             (we don't search for the closing shortcode bracket because they might have added
523
-     *                             parameter to the shortcode
524
-     * @return WP_Post or NULl
525
-     */
526
-    public static function get_page_by_ee_shortcode($ee_shortcode)
527
-    {
528
-        global $wpdb;
529
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
530
-        $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
531
-        if ($post_id) {
532
-            return get_post($post_id);
533
-        } else {
534
-            return null;
535
-        }
536
-    }
537
-
538
-
539
-    /**
540
-     *    This function generates a post for critical espresso pages
541
-     *
542
-     * @access public
543
-     * @static
544
-     * @param array $critical_page
545
-     * @return array
546
-     */
547
-    public static function create_critical_page($critical_page)
548
-    {
549
-
550
-        $post_args = array(
551
-            'post_title'     => $critical_page['name'],
552
-            'post_status'    => 'publish',
553
-            'post_type'      => 'page',
554
-            'comment_status' => 'closed',
555
-            'post_content'   => '[' . $critical_page['code'] . ']',
556
-        );
557
-
558
-        $post_id = wp_insert_post($post_args);
559
-        if (! $post_id) {
560
-            $msg = sprintf(
561
-                __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
562
-                $critical_page['name']
563
-            );
564
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
565
-            return $critical_page;
566
-        }
567
-        // get newly created post's details
568
-        if (! $critical_page['post'] = get_post($post_id)) {
569
-            $msg = sprintf(
570
-                __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
571
-                $critical_page['name']
572
-            );
573
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
574
-        }
575
-
576
-        return $critical_page;
577
-
578
-    }
579
-
580
-
581
-
582
-
583
-
584
-    /**
585
-     *    This function adds a critical page's shortcode to the post_shortcodes array
586
-     *
587
-     * @access private
588
-     * @static
589
-     * @param array $critical_page
590
-     * @return void
591
-     */
592
-    private static function _track_critical_page_post_shortcodes($critical_page = array())
593
-    {
594
-        // check the goods
595
-        if ( ! $critical_page['post'] instanceof WP_Post) {
596
-            $msg = sprintf(
597
-                __(
598
-                    'The Event Espresso critical page shortcode for the page %s can not be tracked because it is not a WP_Post object.',
599
-                    'event_espresso'
600
-                ),
601
-                $critical_page['name']
602
-            );
603
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
604
-            return;
605
-        }
606
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
607
-        // map shortcode to post
608
-        $EE_Core_Config->post_shortcodes[$critical_page['post']->post_name][$critical_page['code']] = $critical_page['post']->ID;
609
-        // and make sure it's NOT added to the WP "Posts Page"
610
-        // name of the WP Posts Page
611
-        $posts_page = EE_Config::get_page_for_posts();
612
-        if (isset($EE_Core_Config->post_shortcodes[$posts_page])) {
613
-            unset($EE_Core_Config->post_shortcodes[$posts_page][$critical_page['code']]);
614
-        }
615
-        if ($posts_page !== 'posts' && isset($EE_Core_Config->post_shortcodes['posts'])) {
616
-            unset($EE_Core_Config->post_shortcodes['posts'][$critical_page['code']]);
617
-        }
618
-        // update post_shortcode CFG
619
-        if ( ! EE_Config::instance()->update_espresso_config(false, false)) {
620
-            $msg = sprintf(
621
-                __(
622
-                    'The Event Espresso critical page shortcode for the %s page could not be configured properly.',
623
-                    'event_espresso'
624
-                ),
625
-                $critical_page['name']
626
-            );
627
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
628
-        }
629
-    }
630
-
631
-
632
-
633
-    /**
634
-     * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
635
-     * The role being used to check is filterable.
636
-     *
637
-     * @since  4.6.0
638
-     * @global WPDB $wpdb
639
-     * @return mixed null|int WP_user ID or NULL
640
-     */
641
-    public static function get_default_creator_id()
642
-    {
643
-        global $wpdb;
644
-        if ( ! empty(self::$_default_creator_id)) {
645
-            return self::$_default_creator_id;
646
-        }/**/
647
-        $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
648
-        //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.
649
-        $pre_filtered_id = apply_filters(
650
-            'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
651
-            false,
652
-            $role_to_check
653
-        );
654
-        if ($pre_filtered_id !== false) {
655
-            return (int)$pre_filtered_id;
656
-        }
657
-        $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
658
-        $query = $wpdb->prepare(
659
-            "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
660
-            '%' . $role_to_check . '%'
661
-        );
662
-        $user_id = $wpdb->get_var($query);
663
-        $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
664
-        if ($user_id && (int)$user_id) {
665
-            self::$_default_creator_id = (int)$user_id;
666
-            return self::$_default_creator_id;
667
-        } else {
668
-            return null;
669
-        }
670
-    }
671
-
672
-
673
-
674
-    /**
675
-     * used by EE and EE addons during plugin activation to create tables.
676
-     * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
677
-     * but includes extra logic regarding activations.
678
-     *
679
-     * @access public
680
-     * @static
681
-     * @param string  $table_name              without the $wpdb->prefix
682
-     * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
683
-     *                                         table query)
684
-     * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
685
-     * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
686
-     *                                         and new once this function is done (ie, you really do want to CREATE a
687
-     *                                         table, and expect it to be empty once you're done) leave as FALSE when
688
-     *                                         you just want to verify the table exists and matches this definition
689
-     *                                         (and if it HAS data in it you want to leave it be)
690
-     * @return void
691
-     * @throws EE_Error if there are database errors
692
-     */
693
-    public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
694
-    {
695
-        if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
696
-            return;
697
-        }
698
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
699
-        if ( ! function_exists('dbDelta')) {
700
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
701
-        }
702
-        $tableAnalysis = \EEH_Activation::getTableAnalysis();
703
-        $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
704
-        // do we need to first delete an existing version of this table ?
705
-        if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
706
-            // ok, delete the table... but ONLY if it's empty
707
-            $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
708
-            // table is NOT empty, are you SURE you want to delete this table ???
709
-            if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
710
-                \EEH_Activation::getTableManager()->dropTable($wp_table_name);
711
-            } else if ( ! $deleted_safely) {
712
-                // so we should be more cautious rather than just dropping tables so easily
713
-                error_log(
714
-                    sprintf(
715
-                        __(
716
-                            '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.',
717
-                            'event_espresso'
718
-                        ),
719
-                        $wp_table_name,
720
-                        '<br/>',
721
-                        'espresso_db_update'
722
-                    )
723
-                );
724
-            }
725
-        }
726
-        $engine = str_replace('ENGINE=', '', $engine);
727
-        \EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
728
-    }
729
-
730
-
731
-
732
-    /**
733
-     *    add_column_if_it_doesn't_exist
734
-     *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
735
-     *
736
-     * @access     public
737
-     * @static
738
-     * @deprecated instead use TableManager::addColumn()
739
-     * @param string $table_name  (without "wp_", eg "esp_attendee"
740
-     * @param string $column_name
741
-     * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
742
-     *                            'VARCHAR(10)'
743
-     * @return bool|int
744
-     */
745
-    public static function add_column_if_it_doesnt_exist(
746
-        $table_name,
747
-        $column_name,
748
-        $column_info = 'INT UNSIGNED NOT NULL'
749
-    ) {
750
-        return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
751
-    }
752
-
753
-
754
-    /**
755
-     * get_fields_on_table
756
-     * Gets all the fields on the database table.
757
-     *
758
-     * @access     public
759
-     * @deprecated instead use TableManager::getTableColumns()
760
-     * @static
761
-     * @param string $table_name , without prefixed $wpdb->prefix
762
-     * @return array of database column names
763
-     */
764
-    public static function get_fields_on_table($table_name = null)
765
-    {
766
-        return \EEH_Activation::getTableManager()->getTableColumns($table_name);
767
-    }
768
-
769
-
770
-    /**
771
-     * db_table_is_empty
772
-     *
773
-     * @access     public\
774
-     * @deprecated instead use TableAnalysis::tableIsEmpty()
775
-     * @static
776
-     * @param string $table_name
777
-     * @return bool
778
-     */
779
-    public static function db_table_is_empty($table_name)
780
-    {
781
-        return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
782
-    }
783
-
784
-
785
-    /**
786
-     * delete_db_table_if_empty
787
-     *
788
-     * @access public
789
-     * @static
790
-     * @param string $table_name
791
-     * @return bool | int
792
-     */
793
-    public static function delete_db_table_if_empty($table_name)
794
-    {
795
-        if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
796
-            return \EEH_Activation::getTableManager()->dropTable($table_name);
797
-        }
798
-        return false;
799
-    }
800
-
801
-
802
-    /**
803
-     * delete_unused_db_table
804
-     *
805
-     * @access     public
806
-     * @static
807
-     * @deprecated instead use TableManager::dropTable()
808
-     * @param string $table_name
809
-     * @return bool | int
810
-     */
811
-    public static function delete_unused_db_table($table_name)
812
-    {
813
-        return \EEH_Activation::getTableManager()->dropTable($table_name);
814
-    }
815
-
816
-
817
-    /**
818
-     * drop_index
819
-     *
820
-     * @access     public
821
-     * @static
822
-     * @deprecated instead use TableManager::dropIndex()
823
-     * @param string $table_name
824
-     * @param string $index_name
825
-     * @return bool | int
826
-     */
827
-    public static function drop_index($table_name, $index_name)
828
-    {
829
-        return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
830
-    }
831
-
832
-
833
-
834
-    /**
835
-     * create_database_tables
836
-     *
837
-     * @access public
838
-     * @static
839
-     * @throws EE_Error
840
-     * @return boolean success (whether database is setup properly or not)
841
-     */
842
-    public static function create_database_tables()
843
-    {
844
-        EE_Registry::instance()->load_core('Data_Migration_Manager');
845
-        //find the migration script that sets the database to be compatible with the code
846
-        $dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
847
-        if ($dms_name) {
848
-            $current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
849
-            $current_data_migration_script->set_migrating(false);
850
-            $current_data_migration_script->schema_changes_before_migration();
851
-            $current_data_migration_script->schema_changes_after_migration();
852
-            if ($current_data_migration_script->get_errors()) {
853
-                if (WP_DEBUG) {
854
-                    foreach ($current_data_migration_script->get_errors() as $error) {
855
-                        EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
856
-                    }
857
-                } else {
858
-                    EE_Error::add_error(
859
-                        __(
860
-                            'There were errors creating the Event Espresso database tables and Event Espresso has been 
258
+		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
259
+		foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
260
+			if (is_array($hooks_to_fire_at_time)) {
261
+				foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
262
+					if (isset($ee_cron_tasks_to_remove[$hook_name])
263
+						&& is_array($ee_cron_tasks_to_remove[$hook_name])
264
+					) {
265
+						unset($crons[$timestamp][$hook_name]);
266
+					}
267
+				}
268
+				//also take care of any empty cron timestamps.
269
+				if (empty($hooks_to_fire_at_time)) {
270
+					unset($crons[$timestamp]);
271
+				}
272
+			}
273
+		}
274
+		_set_cron_array($crons);
275
+	}
276
+
277
+
278
+	/**
279
+	 *    CPT_initialization
280
+	 *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
281
+	 *
282
+	 * @access public
283
+	 * @static
284
+	 * @return void
285
+	 */
286
+	public static function CPT_initialization()
287
+	{
288
+		// register Custom Post Types
289
+		EE_Registry::instance()->load_core('Register_CPTs');
290
+		flush_rewrite_rules();
291
+	}
292
+
293
+
294
+
295
+	/**
296
+	 *    reset_and_update_config
297
+	 * The following code was moved over from EE_Config so that it will no longer run on every request.
298
+	 * If there is old calendar config data saved, then it will get converted on activation.
299
+	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
300
+	 *
301
+	 * @access public
302
+	 * @static
303
+	 * @return void
304
+	 */
305
+	public static function reset_and_update_config()
306
+	{
307
+		do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
308
+		add_filter(
309
+			'FHEE__EE_Config___load_core_config__config_settings',
310
+			array('EEH_Activation', 'migrate_old_config_data'),
311
+			10,
312
+			3
313
+		);
314
+		//EE_Config::reset();
315
+		if (! EE_Config::logging_enabled()) {
316
+			delete_option(EE_Config::LOG_NAME);
317
+		}
318
+	}
319
+
320
+
321
+	/**
322
+	 *    load_calendar_config
323
+	 *
324
+	 * @access    public
325
+	 * @return    void
326
+	 */
327
+	public static function load_calendar_config()
328
+	{
329
+		// grab array of all plugin folders and loop thru it
330
+		$plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
331
+		if (empty($plugins)) {
332
+			return;
333
+		}
334
+		foreach ($plugins as $plugin_path) {
335
+			// grab plugin folder name from path
336
+			$plugin = basename($plugin_path);
337
+			// drill down to Espresso plugins
338
+			// then to calendar related plugins
339
+			if (
340
+				strpos($plugin, 'espresso') !== false
341
+				|| strpos($plugin, 'Espresso') !== false
342
+				|| strpos($plugin, 'ee4') !== false
343
+				|| strpos($plugin, 'EE4') !== false
344
+				|| strpos($plugin, 'calendar') !== false
345
+			) {
346
+				// this is what we are looking for
347
+				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
348
+				// does it exist in this folder ?
349
+				if (is_readable($calendar_config)) {
350
+					// YEAH! let's load it
351
+					require_once($calendar_config);
352
+				}
353
+			}
354
+		}
355
+	}
356
+
357
+
358
+
359
+	/**
360
+	 *    _migrate_old_config_data
361
+	 *
362
+	 * @access    public
363
+	 * @param array|stdClass $settings
364
+	 * @param string         $config
365
+	 * @param \EE_Config     $EE_Config
366
+	 * @return \stdClass
367
+	 */
368
+	public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
369
+	{
370
+		$convert_from_array = array('addons');
371
+		// in case old settings were saved as an array
372
+		if (is_array($settings) && in_array($config, $convert_from_array)) {
373
+			// convert existing settings to an object
374
+			$config_array = $settings;
375
+			$settings = new stdClass();
376
+			foreach ($config_array as $key => $value) {
377
+				if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
378
+					$EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
379
+				} else {
380
+					$settings->{$key} = $value;
381
+				}
382
+			}
383
+			add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
384
+		}
385
+		return $settings;
386
+	}
387
+
388
+
389
+	/**
390
+	 * deactivate_event_espresso
391
+	 *
392
+	 * @access public
393
+	 * @static
394
+	 * @return void
395
+	 */
396
+	public static function deactivate_event_espresso()
397
+	{
398
+		// check permissions
399
+		if (current_user_can('activate_plugins')) {
400
+			deactivate_plugins(EE_PLUGIN_BASENAME, true);
401
+		}
402
+	}
403
+
404
+
405
+
406
+
407
+
408
+	/**
409
+	 * verify_default_pages_exist
410
+	 *
411
+	 * @access public
412
+	 * @static
413
+	 * @return void
414
+	 */
415
+	public static function verify_default_pages_exist()
416
+	{
417
+		$critical_page_problem = false;
418
+		$critical_pages = array(
419
+			array(
420
+				'id'   => 'reg_page_id',
421
+				'name' => __('Registration Checkout', 'event_espresso'),
422
+				'post' => null,
423
+				'code' => 'ESPRESSO_CHECKOUT',
424
+			),
425
+			array(
426
+				'id'   => 'txn_page_id',
427
+				'name' => __('Transactions', 'event_espresso'),
428
+				'post' => null,
429
+				'code' => 'ESPRESSO_TXN_PAGE',
430
+			),
431
+			array(
432
+				'id'   => 'thank_you_page_id',
433
+				'name' => __('Thank You', 'event_espresso'),
434
+				'post' => null,
435
+				'code' => 'ESPRESSO_THANK_YOU',
436
+			),
437
+			array(
438
+				'id'   => 'cancel_page_id',
439
+				'name' => __('Registration Cancelled', 'event_espresso'),
440
+				'post' => null,
441
+				'code' => 'ESPRESSO_CANCELLED',
442
+			),
443
+		);
444
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
445
+		foreach ($critical_pages as $critical_page) {
446
+			// is critical page ID set in config ?
447
+			if ($EE_Core_Config->{$critical_page['id']} !== false) {
448
+				// attempt to find post by ID
449
+				$critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
450
+			}
451
+			// no dice?
452
+			if ($critical_page['post'] === null) {
453
+				// attempt to find post by title
454
+				$critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
455
+				// still nothing?
456
+				if ($critical_page['post'] === null) {
457
+					$critical_page = EEH_Activation::create_critical_page($critical_page);
458
+					// REALLY? Still nothing ??!?!?
459
+					if ($critical_page['post'] === null) {
460
+						$msg = __(
461
+							'The Event Espresso critical page configuration settings could not be updated.',
462
+							'event_espresso'
463
+						);
464
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
465
+						break;
466
+					}
467
+				}
468
+			}
469
+			// track post_shortcodes
470
+			if ($critical_page['post']) {
471
+				EEH_Activation::_track_critical_page_post_shortcodes($critical_page);
472
+			}
473
+			// check that Post ID matches critical page ID in config
474
+			if (
475
+				isset($critical_page['post']->ID)
476
+				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
477
+			) {
478
+				//update Config with post ID
479
+				$EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
480
+				if (! EE_Config::instance()->update_espresso_config(false, false)) {
481
+					$msg = __(
482
+						'The Event Espresso critical page configuration settings could not be updated.',
483
+						'event_espresso'
484
+					);
485
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
486
+				}
487
+			}
488
+			$critical_page_problem =
489
+				! isset($critical_page['post']->post_status)
490
+				|| $critical_page['post']->post_status !== 'publish'
491
+				|| strpos($critical_page['post']->post_content, $critical_page['code']) === false
492
+					? true
493
+					: $critical_page_problem;
494
+		}
495
+		if ($critical_page_problem) {
496
+			$msg = sprintf(
497
+				__(
498
+					'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
499
+					'event_espresso'
500
+				),
501
+				'<a href="'
502
+				. admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
503
+				. '">'
504
+				. __('Event Espresso Critical Pages Settings', 'event_espresso')
505
+				. '</a>'
506
+			);
507
+			EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
508
+		}
509
+		if (EE_Error::has_notices()) {
510
+			EE_Error::get_notices(false, true, true);
511
+		}
512
+	}
513
+
514
+
515
+
516
+	/**
517
+	 * Returns the first post which uses the specified shortcode
518
+	 *
519
+	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
520
+	 *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
521
+	 *                             "[ESPRESSO_THANK_YOU"
522
+	 *                             (we don't search for the closing shortcode bracket because they might have added
523
+	 *                             parameter to the shortcode
524
+	 * @return WP_Post or NULl
525
+	 */
526
+	public static function get_page_by_ee_shortcode($ee_shortcode)
527
+	{
528
+		global $wpdb;
529
+		$shortcode_and_opening_bracket = '[' . $ee_shortcode;
530
+		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
531
+		if ($post_id) {
532
+			return get_post($post_id);
533
+		} else {
534
+			return null;
535
+		}
536
+	}
537
+
538
+
539
+	/**
540
+	 *    This function generates a post for critical espresso pages
541
+	 *
542
+	 * @access public
543
+	 * @static
544
+	 * @param array $critical_page
545
+	 * @return array
546
+	 */
547
+	public static function create_critical_page($critical_page)
548
+	{
549
+
550
+		$post_args = array(
551
+			'post_title'     => $critical_page['name'],
552
+			'post_status'    => 'publish',
553
+			'post_type'      => 'page',
554
+			'comment_status' => 'closed',
555
+			'post_content'   => '[' . $critical_page['code'] . ']',
556
+		);
557
+
558
+		$post_id = wp_insert_post($post_args);
559
+		if (! $post_id) {
560
+			$msg = sprintf(
561
+				__('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
562
+				$critical_page['name']
563
+			);
564
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
565
+			return $critical_page;
566
+		}
567
+		// get newly created post's details
568
+		if (! $critical_page['post'] = get_post($post_id)) {
569
+			$msg = sprintf(
570
+				__('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
571
+				$critical_page['name']
572
+			);
573
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
574
+		}
575
+
576
+		return $critical_page;
577
+
578
+	}
579
+
580
+
581
+
582
+
583
+
584
+	/**
585
+	 *    This function adds a critical page's shortcode to the post_shortcodes array
586
+	 *
587
+	 * @access private
588
+	 * @static
589
+	 * @param array $critical_page
590
+	 * @return void
591
+	 */
592
+	private static function _track_critical_page_post_shortcodes($critical_page = array())
593
+	{
594
+		// check the goods
595
+		if ( ! $critical_page['post'] instanceof WP_Post) {
596
+			$msg = sprintf(
597
+				__(
598
+					'The Event Espresso critical page shortcode for the page %s can not be tracked because it is not a WP_Post object.',
599
+					'event_espresso'
600
+				),
601
+				$critical_page['name']
602
+			);
603
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
604
+			return;
605
+		}
606
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
607
+		// map shortcode to post
608
+		$EE_Core_Config->post_shortcodes[$critical_page['post']->post_name][$critical_page['code']] = $critical_page['post']->ID;
609
+		// and make sure it's NOT added to the WP "Posts Page"
610
+		// name of the WP Posts Page
611
+		$posts_page = EE_Config::get_page_for_posts();
612
+		if (isset($EE_Core_Config->post_shortcodes[$posts_page])) {
613
+			unset($EE_Core_Config->post_shortcodes[$posts_page][$critical_page['code']]);
614
+		}
615
+		if ($posts_page !== 'posts' && isset($EE_Core_Config->post_shortcodes['posts'])) {
616
+			unset($EE_Core_Config->post_shortcodes['posts'][$critical_page['code']]);
617
+		}
618
+		// update post_shortcode CFG
619
+		if ( ! EE_Config::instance()->update_espresso_config(false, false)) {
620
+			$msg = sprintf(
621
+				__(
622
+					'The Event Espresso critical page shortcode for the %s page could not be configured properly.',
623
+					'event_espresso'
624
+				),
625
+				$critical_page['name']
626
+			);
627
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
628
+		}
629
+	}
630
+
631
+
632
+
633
+	/**
634
+	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
635
+	 * The role being used to check is filterable.
636
+	 *
637
+	 * @since  4.6.0
638
+	 * @global WPDB $wpdb
639
+	 * @return mixed null|int WP_user ID or NULL
640
+	 */
641
+	public static function get_default_creator_id()
642
+	{
643
+		global $wpdb;
644
+		if ( ! empty(self::$_default_creator_id)) {
645
+			return self::$_default_creator_id;
646
+		}/**/
647
+		$role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
648
+		//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.
649
+		$pre_filtered_id = apply_filters(
650
+			'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
651
+			false,
652
+			$role_to_check
653
+		);
654
+		if ($pre_filtered_id !== false) {
655
+			return (int)$pre_filtered_id;
656
+		}
657
+		$capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
658
+		$query = $wpdb->prepare(
659
+			"SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
660
+			'%' . $role_to_check . '%'
661
+		);
662
+		$user_id = $wpdb->get_var($query);
663
+		$user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
664
+		if ($user_id && (int)$user_id) {
665
+			self::$_default_creator_id = (int)$user_id;
666
+			return self::$_default_creator_id;
667
+		} else {
668
+			return null;
669
+		}
670
+	}
671
+
672
+
673
+
674
+	/**
675
+	 * used by EE and EE addons during plugin activation to create tables.
676
+	 * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
677
+	 * but includes extra logic regarding activations.
678
+	 *
679
+	 * @access public
680
+	 * @static
681
+	 * @param string  $table_name              without the $wpdb->prefix
682
+	 * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
683
+	 *                                         table query)
684
+	 * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
685
+	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
686
+	 *                                         and new once this function is done (ie, you really do want to CREATE a
687
+	 *                                         table, and expect it to be empty once you're done) leave as FALSE when
688
+	 *                                         you just want to verify the table exists and matches this definition
689
+	 *                                         (and if it HAS data in it you want to leave it be)
690
+	 * @return void
691
+	 * @throws EE_Error if there are database errors
692
+	 */
693
+	public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
694
+	{
695
+		if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
696
+			return;
697
+		}
698
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
699
+		if ( ! function_exists('dbDelta')) {
700
+			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
701
+		}
702
+		$tableAnalysis = \EEH_Activation::getTableAnalysis();
703
+		$wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
704
+		// do we need to first delete an existing version of this table ?
705
+		if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
706
+			// ok, delete the table... but ONLY if it's empty
707
+			$deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
708
+			// table is NOT empty, are you SURE you want to delete this table ???
709
+			if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
710
+				\EEH_Activation::getTableManager()->dropTable($wp_table_name);
711
+			} else if ( ! $deleted_safely) {
712
+				// so we should be more cautious rather than just dropping tables so easily
713
+				error_log(
714
+					sprintf(
715
+						__(
716
+							'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.',
717
+							'event_espresso'
718
+						),
719
+						$wp_table_name,
720
+						'<br/>',
721
+						'espresso_db_update'
722
+					)
723
+				);
724
+			}
725
+		}
726
+		$engine = str_replace('ENGINE=', '', $engine);
727
+		\EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
728
+	}
729
+
730
+
731
+
732
+	/**
733
+	 *    add_column_if_it_doesn't_exist
734
+	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
735
+	 *
736
+	 * @access     public
737
+	 * @static
738
+	 * @deprecated instead use TableManager::addColumn()
739
+	 * @param string $table_name  (without "wp_", eg "esp_attendee"
740
+	 * @param string $column_name
741
+	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
742
+	 *                            'VARCHAR(10)'
743
+	 * @return bool|int
744
+	 */
745
+	public static function add_column_if_it_doesnt_exist(
746
+		$table_name,
747
+		$column_name,
748
+		$column_info = 'INT UNSIGNED NOT NULL'
749
+	) {
750
+		return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
751
+	}
752
+
753
+
754
+	/**
755
+	 * get_fields_on_table
756
+	 * Gets all the fields on the database table.
757
+	 *
758
+	 * @access     public
759
+	 * @deprecated instead use TableManager::getTableColumns()
760
+	 * @static
761
+	 * @param string $table_name , without prefixed $wpdb->prefix
762
+	 * @return array of database column names
763
+	 */
764
+	public static function get_fields_on_table($table_name = null)
765
+	{
766
+		return \EEH_Activation::getTableManager()->getTableColumns($table_name);
767
+	}
768
+
769
+
770
+	/**
771
+	 * db_table_is_empty
772
+	 *
773
+	 * @access     public\
774
+	 * @deprecated instead use TableAnalysis::tableIsEmpty()
775
+	 * @static
776
+	 * @param string $table_name
777
+	 * @return bool
778
+	 */
779
+	public static function db_table_is_empty($table_name)
780
+	{
781
+		return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
782
+	}
783
+
784
+
785
+	/**
786
+	 * delete_db_table_if_empty
787
+	 *
788
+	 * @access public
789
+	 * @static
790
+	 * @param string $table_name
791
+	 * @return bool | int
792
+	 */
793
+	public static function delete_db_table_if_empty($table_name)
794
+	{
795
+		if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
796
+			return \EEH_Activation::getTableManager()->dropTable($table_name);
797
+		}
798
+		return false;
799
+	}
800
+
801
+
802
+	/**
803
+	 * delete_unused_db_table
804
+	 *
805
+	 * @access     public
806
+	 * @static
807
+	 * @deprecated instead use TableManager::dropTable()
808
+	 * @param string $table_name
809
+	 * @return bool | int
810
+	 */
811
+	public static function delete_unused_db_table($table_name)
812
+	{
813
+		return \EEH_Activation::getTableManager()->dropTable($table_name);
814
+	}
815
+
816
+
817
+	/**
818
+	 * drop_index
819
+	 *
820
+	 * @access     public
821
+	 * @static
822
+	 * @deprecated instead use TableManager::dropIndex()
823
+	 * @param string $table_name
824
+	 * @param string $index_name
825
+	 * @return bool | int
826
+	 */
827
+	public static function drop_index($table_name, $index_name)
828
+	{
829
+		return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
830
+	}
831
+
832
+
833
+
834
+	/**
835
+	 * create_database_tables
836
+	 *
837
+	 * @access public
838
+	 * @static
839
+	 * @throws EE_Error
840
+	 * @return boolean success (whether database is setup properly or not)
841
+	 */
842
+	public static function create_database_tables()
843
+	{
844
+		EE_Registry::instance()->load_core('Data_Migration_Manager');
845
+		//find the migration script that sets the database to be compatible with the code
846
+		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
847
+		if ($dms_name) {
848
+			$current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
849
+			$current_data_migration_script->set_migrating(false);
850
+			$current_data_migration_script->schema_changes_before_migration();
851
+			$current_data_migration_script->schema_changes_after_migration();
852
+			if ($current_data_migration_script->get_errors()) {
853
+				if (WP_DEBUG) {
854
+					foreach ($current_data_migration_script->get_errors() as $error) {
855
+						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
856
+					}
857
+				} else {
858
+					EE_Error::add_error(
859
+						__(
860
+							'There were errors creating the Event Espresso database tables and Event Espresso has been 
861 861
                             deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.',
862
-                            'event_espresso'
863
-                        )
864
-                    );
865
-                }
866
-                return false;
867
-            }
868
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to();
869
-        } else {
870
-            EE_Error::add_error(
871
-                __(
872
-                    'Could not determine most up-to-date data migration script from which to pull database schema
862
+							'event_espresso'
863
+						)
864
+					);
865
+				}
866
+				return false;
867
+			}
868
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
869
+		} else {
870
+			EE_Error::add_error(
871
+				__(
872
+					'Could not determine most up-to-date data migration script from which to pull database schema
873 873
                      structure. So database is probably not setup properly',
874
-                    'event_espresso'
875
-                ),
876
-                __FILE__,
877
-                __FUNCTION__,
878
-                __LINE__
879
-            );
880
-            return false;
881
-        }
882
-        return true;
883
-    }
884
-
885
-
886
-
887
-    /**
888
-     * initialize_system_questions
889
-     *
890
-     * @access public
891
-     * @static
892
-     * @return void
893
-     */
894
-    public static function initialize_system_questions()
895
-    {
896
-        // QUESTION GROUPS
897
-        global $wpdb;
898
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
899
-        $SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
900
-        // what we have
901
-        $question_groups = $wpdb->get_col($SQL);
902
-        // check the response
903
-        $question_groups = is_array($question_groups) ? $question_groups : array();
904
-        // what we should have
905
-        $QSG_systems = array(1, 2);
906
-        // loop thru what we should have and compare to what we have
907
-        foreach ($QSG_systems as $QSG_system) {
908
-            // reset values array
909
-            $QSG_values = array();
910
-            // 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)
911
-            if (! in_array("$QSG_system", $question_groups)) {
912
-                // add it
913
-                switch ($QSG_system) {
914
-                    case 1:
915
-                        $QSG_values = array(
916
-                            'QSG_name'            => __('Personal Information', 'event_espresso'),
917
-                            'QSG_identifier'      => 'personal-information-' . time(),
918
-                            'QSG_desc'            => '',
919
-                            'QSG_order'           => 1,
920
-                            'QSG_show_group_name' => 1,
921
-                            'QSG_show_group_desc' => 1,
922
-                            'QSG_system'          => EEM_Question_Group::system_personal,
923
-                            'QSG_deleted'         => 0,
924
-                        );
925
-                        break;
926
-                    case 2:
927
-                        $QSG_values = array(
928
-                            'QSG_name'            => __('Address Information', 'event_espresso'),
929
-                            'QSG_identifier'      => 'address-information-' . time(),
930
-                            'QSG_desc'            => '',
931
-                            'QSG_order'           => 2,
932
-                            'QSG_show_group_name' => 1,
933
-                            'QSG_show_group_desc' => 1,
934
-                            'QSG_system'          => EEM_Question_Group::system_address,
935
-                            'QSG_deleted'         => 0,
936
-                        );
937
-                        break;
938
-                }
939
-                // make sure we have some values before inserting them
940
-                if (! empty($QSG_values)) {
941
-                    // insert system question
942
-                    $wpdb->insert(
943
-                        $table_name,
944
-                        $QSG_values,
945
-                        array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
946
-                    );
947
-                    $QSG_IDs[$QSG_system] = $wpdb->insert_id;
948
-                }
949
-            }
950
-        }
951
-        // QUESTIONS
952
-        global $wpdb;
953
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
954
-        $SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
955
-        // what we have
956
-        $questions = $wpdb->get_col($SQL);
957
-        // what we should have
958
-        $QST_systems = array(
959
-            'fname',
960
-            'lname',
961
-            'email',
962
-            'address',
963
-            'address2',
964
-            'city',
965
-            'country',
966
-            'state',
967
-            'zip',
968
-            'phone',
969
-        );
970
-        $order_for_group_1 = 1;
971
-        $order_for_group_2 = 1;
972
-        // loop thru what we should have and compare to what we have
973
-        foreach ($QST_systems as $QST_system) {
974
-            // reset values array
975
-            $QST_values = array();
976
-            // if we don't have what we should have
977
-            if (! in_array($QST_system, $questions)) {
978
-                // add it
979
-                switch ($QST_system) {
980
-                    case 'fname':
981
-                        $QST_values = array(
982
-                            'QST_display_text'  => __('First Name', 'event_espresso'),
983
-                            'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
984
-                            'QST_system'        => 'fname',
985
-                            'QST_type'          => 'TEXT',
986
-                            'QST_required'      => 1,
987
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
988
-                            'QST_order'         => 1,
989
-                            'QST_admin_only'    => 0,
990
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
991
-                            'QST_wp_user'       => self::get_default_creator_id(),
992
-                            'QST_deleted'       => 0,
993
-                        );
994
-                        break;
995
-                    case 'lname':
996
-                        $QST_values = array(
997
-                            'QST_display_text'  => __('Last Name', 'event_espresso'),
998
-                            'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
999
-                            'QST_system'        => 'lname',
1000
-                            'QST_type'          => 'TEXT',
1001
-                            'QST_required'      => 1,
1002
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1003
-                            'QST_order'         => 2,
1004
-                            'QST_admin_only'    => 0,
1005
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1006
-                            'QST_wp_user'       => self::get_default_creator_id(),
1007
-                            'QST_deleted'       => 0,
1008
-                        );
1009
-                        break;
1010
-                    case 'email':
1011
-                        $QST_values = array(
1012
-                            'QST_display_text'  => __('Email Address', 'event_espresso'),
1013
-                            'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
1014
-                            'QST_system'        => 'email',
1015
-                            'QST_type'          => 'EMAIL',
1016
-                            'QST_required'      => 1,
1017
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1018
-                            'QST_order'         => 3,
1019
-                            'QST_admin_only'    => 0,
1020
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1021
-                            'QST_wp_user'       => self::get_default_creator_id(),
1022
-                            'QST_deleted'       => 0,
1023
-                        );
1024
-                        break;
1025
-                    case 'address':
1026
-                        $QST_values = array(
1027
-                            'QST_display_text'  => __('Address', 'event_espresso'),
1028
-                            'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
1029
-                            'QST_system'        => 'address',
1030
-                            'QST_type'          => 'TEXT',
1031
-                            'QST_required'      => 0,
1032
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1033
-                            'QST_order'         => 4,
1034
-                            'QST_admin_only'    => 0,
1035
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1036
-                            'QST_wp_user'       => self::get_default_creator_id(),
1037
-                            'QST_deleted'       => 0,
1038
-                        );
1039
-                        break;
1040
-                    case 'address2':
1041
-                        $QST_values = array(
1042
-                            'QST_display_text'  => __('Address2', 'event_espresso'),
1043
-                            'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1044
-                            'QST_system'        => 'address2',
1045
-                            'QST_type'          => 'TEXT',
1046
-                            'QST_required'      => 0,
1047
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1048
-                            'QST_order'         => 5,
1049
-                            'QST_admin_only'    => 0,
1050
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1051
-                            'QST_wp_user'       => self::get_default_creator_id(),
1052
-                            'QST_deleted'       => 0,
1053
-                        );
1054
-                        break;
1055
-                    case 'city':
1056
-                        $QST_values = array(
1057
-                            'QST_display_text'  => __('City', 'event_espresso'),
1058
-                            'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1059
-                            'QST_system'        => 'city',
1060
-                            'QST_type'          => 'TEXT',
1061
-                            'QST_required'      => 0,
1062
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1063
-                            'QST_order'         => 6,
1064
-                            'QST_admin_only'    => 0,
1065
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1066
-                            'QST_wp_user'       => self::get_default_creator_id(),
1067
-                            'QST_deleted'       => 0,
1068
-                        );
1069
-                        break;
1070
-                    case 'country':
1071
-                        $QST_values = array(
1072
-                            'QST_display_text'  => __('Country', 'event_espresso'),
1073
-                            'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1074
-                            'QST_system'        => 'country',
1075
-                            'QST_type'          => 'COUNTRY',
1076
-                            'QST_required'      => 0,
1077
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1078
-                            'QST_order'         => 7,
1079
-                            'QST_admin_only'    => 0,
1080
-                            'QST_wp_user'       => self::get_default_creator_id(),
1081
-                            'QST_deleted'       => 0,
1082
-                        );
1083
-                        break;
1084
-                    case 'state':
1085
-                        $QST_values = array(
1086
-                            'QST_display_text'  => __('State/Province', 'event_espresso'),
1087
-                            'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1088
-                            'QST_system'        => 'state',
1089
-                            'QST_type'          => 'STATE',
1090
-                            'QST_required'      => 0,
1091
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1092
-                            'QST_order'         => 8,
1093
-                            'QST_admin_only'    => 0,
1094
-                            'QST_wp_user'       => self::get_default_creator_id(),
1095
-                            'QST_deleted'       => 0,
1096
-                        );
1097
-                        break;
1098
-                    case 'zip':
1099
-                        $QST_values = array(
1100
-                            'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1101
-                            'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1102
-                            'QST_system'        => 'zip',
1103
-                            'QST_type'          => 'TEXT',
1104
-                            'QST_required'      => 0,
1105
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1106
-                            'QST_order'         => 9,
1107
-                            'QST_admin_only'    => 0,
1108
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1109
-                            'QST_wp_user'       => self::get_default_creator_id(),
1110
-                            'QST_deleted'       => 0,
1111
-                        );
1112
-                        break;
1113
-                    case 'phone':
1114
-                        $QST_values = array(
1115
-                            'QST_display_text'  => __('Phone Number', 'event_espresso'),
1116
-                            'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1117
-                            'QST_system'        => 'phone',
1118
-                            'QST_type'          => 'TEXT',
1119
-                            'QST_required'      => 0,
1120
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1121
-                            'QST_order'         => 10,
1122
-                            'QST_admin_only'    => 0,
1123
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1124
-                            'QST_wp_user'       => self::get_default_creator_id(),
1125
-                            'QST_deleted'       => 0,
1126
-                        );
1127
-                        break;
1128
-                }
1129
-                if (! empty($QST_values)) {
1130
-                    // insert system question
1131
-                    $wpdb->insert(
1132
-                        $table_name,
1133
-                        $QST_values,
1134
-                        array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1135
-                    );
1136
-                    $QST_ID = $wpdb->insert_id;
1137
-                    // QUESTION GROUP QUESTIONS
1138
-                    if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1139
-                        $system_question_we_want = EEM_Question_Group::system_personal;
1140
-                    } else {
1141
-                        $system_question_we_want = EEM_Question_Group::system_address;
1142
-                    }
1143
-                    if (isset($QSG_IDs[$system_question_we_want])) {
1144
-                        $QSG_ID = $QSG_IDs[$system_question_we_want];
1145
-                    } else {
1146
-                        $id_col = EEM_Question_Group::instance()
1147
-                                                    ->get_col(array(array('QSG_system' => $system_question_we_want)));
1148
-                        if (is_array($id_col)) {
1149
-                            $QSG_ID = reset($id_col);
1150
-                        } else {
1151
-                            //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
1152
-                            EE_Log::instance()->log(
1153
-                                __FILE__,
1154
-                                __FUNCTION__,
1155
-                                sprintf(
1156
-                                    __(
1157
-                                        'Could not associate question %1$s to a question group because no system question
874
+					'event_espresso'
875
+				),
876
+				__FILE__,
877
+				__FUNCTION__,
878
+				__LINE__
879
+			);
880
+			return false;
881
+		}
882
+		return true;
883
+	}
884
+
885
+
886
+
887
+	/**
888
+	 * initialize_system_questions
889
+	 *
890
+	 * @access public
891
+	 * @static
892
+	 * @return void
893
+	 */
894
+	public static function initialize_system_questions()
895
+	{
896
+		// QUESTION GROUPS
897
+		global $wpdb;
898
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
899
+		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
900
+		// what we have
901
+		$question_groups = $wpdb->get_col($SQL);
902
+		// check the response
903
+		$question_groups = is_array($question_groups) ? $question_groups : array();
904
+		// what we should have
905
+		$QSG_systems = array(1, 2);
906
+		// loop thru what we should have and compare to what we have
907
+		foreach ($QSG_systems as $QSG_system) {
908
+			// reset values array
909
+			$QSG_values = array();
910
+			// 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)
911
+			if (! in_array("$QSG_system", $question_groups)) {
912
+				// add it
913
+				switch ($QSG_system) {
914
+					case 1:
915
+						$QSG_values = array(
916
+							'QSG_name'            => __('Personal Information', 'event_espresso'),
917
+							'QSG_identifier'      => 'personal-information-' . time(),
918
+							'QSG_desc'            => '',
919
+							'QSG_order'           => 1,
920
+							'QSG_show_group_name' => 1,
921
+							'QSG_show_group_desc' => 1,
922
+							'QSG_system'          => EEM_Question_Group::system_personal,
923
+							'QSG_deleted'         => 0,
924
+						);
925
+						break;
926
+					case 2:
927
+						$QSG_values = array(
928
+							'QSG_name'            => __('Address Information', 'event_espresso'),
929
+							'QSG_identifier'      => 'address-information-' . time(),
930
+							'QSG_desc'            => '',
931
+							'QSG_order'           => 2,
932
+							'QSG_show_group_name' => 1,
933
+							'QSG_show_group_desc' => 1,
934
+							'QSG_system'          => EEM_Question_Group::system_address,
935
+							'QSG_deleted'         => 0,
936
+						);
937
+						break;
938
+				}
939
+				// make sure we have some values before inserting them
940
+				if (! empty($QSG_values)) {
941
+					// insert system question
942
+					$wpdb->insert(
943
+						$table_name,
944
+						$QSG_values,
945
+						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
946
+					);
947
+					$QSG_IDs[$QSG_system] = $wpdb->insert_id;
948
+				}
949
+			}
950
+		}
951
+		// QUESTIONS
952
+		global $wpdb;
953
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
954
+		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
955
+		// what we have
956
+		$questions = $wpdb->get_col($SQL);
957
+		// what we should have
958
+		$QST_systems = array(
959
+			'fname',
960
+			'lname',
961
+			'email',
962
+			'address',
963
+			'address2',
964
+			'city',
965
+			'country',
966
+			'state',
967
+			'zip',
968
+			'phone',
969
+		);
970
+		$order_for_group_1 = 1;
971
+		$order_for_group_2 = 1;
972
+		// loop thru what we should have and compare to what we have
973
+		foreach ($QST_systems as $QST_system) {
974
+			// reset values array
975
+			$QST_values = array();
976
+			// if we don't have what we should have
977
+			if (! in_array($QST_system, $questions)) {
978
+				// add it
979
+				switch ($QST_system) {
980
+					case 'fname':
981
+						$QST_values = array(
982
+							'QST_display_text'  => __('First Name', 'event_espresso'),
983
+							'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
984
+							'QST_system'        => 'fname',
985
+							'QST_type'          => 'TEXT',
986
+							'QST_required'      => 1,
987
+							'QST_required_text' => __('This field is required', 'event_espresso'),
988
+							'QST_order'         => 1,
989
+							'QST_admin_only'    => 0,
990
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
991
+							'QST_wp_user'       => self::get_default_creator_id(),
992
+							'QST_deleted'       => 0,
993
+						);
994
+						break;
995
+					case 'lname':
996
+						$QST_values = array(
997
+							'QST_display_text'  => __('Last Name', 'event_espresso'),
998
+							'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
999
+							'QST_system'        => 'lname',
1000
+							'QST_type'          => 'TEXT',
1001
+							'QST_required'      => 1,
1002
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1003
+							'QST_order'         => 2,
1004
+							'QST_admin_only'    => 0,
1005
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1006
+							'QST_wp_user'       => self::get_default_creator_id(),
1007
+							'QST_deleted'       => 0,
1008
+						);
1009
+						break;
1010
+					case 'email':
1011
+						$QST_values = array(
1012
+							'QST_display_text'  => __('Email Address', 'event_espresso'),
1013
+							'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
1014
+							'QST_system'        => 'email',
1015
+							'QST_type'          => 'EMAIL',
1016
+							'QST_required'      => 1,
1017
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1018
+							'QST_order'         => 3,
1019
+							'QST_admin_only'    => 0,
1020
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1021
+							'QST_wp_user'       => self::get_default_creator_id(),
1022
+							'QST_deleted'       => 0,
1023
+						);
1024
+						break;
1025
+					case 'address':
1026
+						$QST_values = array(
1027
+							'QST_display_text'  => __('Address', 'event_espresso'),
1028
+							'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
1029
+							'QST_system'        => 'address',
1030
+							'QST_type'          => 'TEXT',
1031
+							'QST_required'      => 0,
1032
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1033
+							'QST_order'         => 4,
1034
+							'QST_admin_only'    => 0,
1035
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1036
+							'QST_wp_user'       => self::get_default_creator_id(),
1037
+							'QST_deleted'       => 0,
1038
+						);
1039
+						break;
1040
+					case 'address2':
1041
+						$QST_values = array(
1042
+							'QST_display_text'  => __('Address2', 'event_espresso'),
1043
+							'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1044
+							'QST_system'        => 'address2',
1045
+							'QST_type'          => 'TEXT',
1046
+							'QST_required'      => 0,
1047
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1048
+							'QST_order'         => 5,
1049
+							'QST_admin_only'    => 0,
1050
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1051
+							'QST_wp_user'       => self::get_default_creator_id(),
1052
+							'QST_deleted'       => 0,
1053
+						);
1054
+						break;
1055
+					case 'city':
1056
+						$QST_values = array(
1057
+							'QST_display_text'  => __('City', 'event_espresso'),
1058
+							'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1059
+							'QST_system'        => 'city',
1060
+							'QST_type'          => 'TEXT',
1061
+							'QST_required'      => 0,
1062
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1063
+							'QST_order'         => 6,
1064
+							'QST_admin_only'    => 0,
1065
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1066
+							'QST_wp_user'       => self::get_default_creator_id(),
1067
+							'QST_deleted'       => 0,
1068
+						);
1069
+						break;
1070
+					case 'country':
1071
+						$QST_values = array(
1072
+							'QST_display_text'  => __('Country', 'event_espresso'),
1073
+							'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1074
+							'QST_system'        => 'country',
1075
+							'QST_type'          => 'COUNTRY',
1076
+							'QST_required'      => 0,
1077
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1078
+							'QST_order'         => 7,
1079
+							'QST_admin_only'    => 0,
1080
+							'QST_wp_user'       => self::get_default_creator_id(),
1081
+							'QST_deleted'       => 0,
1082
+						);
1083
+						break;
1084
+					case 'state':
1085
+						$QST_values = array(
1086
+							'QST_display_text'  => __('State/Province', 'event_espresso'),
1087
+							'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1088
+							'QST_system'        => 'state',
1089
+							'QST_type'          => 'STATE',
1090
+							'QST_required'      => 0,
1091
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1092
+							'QST_order'         => 8,
1093
+							'QST_admin_only'    => 0,
1094
+							'QST_wp_user'       => self::get_default_creator_id(),
1095
+							'QST_deleted'       => 0,
1096
+						);
1097
+						break;
1098
+					case 'zip':
1099
+						$QST_values = array(
1100
+							'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1101
+							'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1102
+							'QST_system'        => 'zip',
1103
+							'QST_type'          => 'TEXT',
1104
+							'QST_required'      => 0,
1105
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1106
+							'QST_order'         => 9,
1107
+							'QST_admin_only'    => 0,
1108
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1109
+							'QST_wp_user'       => self::get_default_creator_id(),
1110
+							'QST_deleted'       => 0,
1111
+						);
1112
+						break;
1113
+					case 'phone':
1114
+						$QST_values = array(
1115
+							'QST_display_text'  => __('Phone Number', 'event_espresso'),
1116
+							'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1117
+							'QST_system'        => 'phone',
1118
+							'QST_type'          => 'TEXT',
1119
+							'QST_required'      => 0,
1120
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1121
+							'QST_order'         => 10,
1122
+							'QST_admin_only'    => 0,
1123
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1124
+							'QST_wp_user'       => self::get_default_creator_id(),
1125
+							'QST_deleted'       => 0,
1126
+						);
1127
+						break;
1128
+				}
1129
+				if (! empty($QST_values)) {
1130
+					// insert system question
1131
+					$wpdb->insert(
1132
+						$table_name,
1133
+						$QST_values,
1134
+						array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1135
+					);
1136
+					$QST_ID = $wpdb->insert_id;
1137
+					// QUESTION GROUP QUESTIONS
1138
+					if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1139
+						$system_question_we_want = EEM_Question_Group::system_personal;
1140
+					} else {
1141
+						$system_question_we_want = EEM_Question_Group::system_address;
1142
+					}
1143
+					if (isset($QSG_IDs[$system_question_we_want])) {
1144
+						$QSG_ID = $QSG_IDs[$system_question_we_want];
1145
+					} else {
1146
+						$id_col = EEM_Question_Group::instance()
1147
+													->get_col(array(array('QSG_system' => $system_question_we_want)));
1148
+						if (is_array($id_col)) {
1149
+							$QSG_ID = reset($id_col);
1150
+						} else {
1151
+							//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
1152
+							EE_Log::instance()->log(
1153
+								__FILE__,
1154
+								__FUNCTION__,
1155
+								sprintf(
1156
+									__(
1157
+										'Could not associate question %1$s to a question group because no system question
1158 1158
                                          group existed',
1159
-                                        'event_espresso'
1160
-                                    ),
1161
-                                    $QST_ID),
1162
-                                'error');
1163
-                            continue;
1164
-                        }
1165
-                    }
1166
-                    // add system questions to groups
1167
-                    $wpdb->insert(
1168
-                        \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1169
-                        array(
1170
-                            'QSG_ID'    => $QSG_ID,
1171
-                            'QST_ID'    => $QST_ID,
1172
-                            'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1173
-                        ),
1174
-                        array('%d', '%d', '%d')
1175
-                    );
1176
-                }
1177
-            }
1178
-        }
1179
-    }
1180
-
1181
-
1182
-    /**
1183
-     * Makes sure the default payment method (Invoice) is active.
1184
-     * This used to be done automatically as part of constructing the old gateways config
1185
-     *
1186
-     * @throws \EE_Error
1187
-     */
1188
-    public static function insert_default_payment_methods()
1189
-    {
1190
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1191
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
1192
-            EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1193
-        } else {
1194
-            EEM_Payment_Method::instance()->verify_button_urls();
1195
-        }
1196
-    }
1197
-
1198
-    /**
1199
-     * insert_default_status_codes
1200
-     *
1201
-     * @access public
1202
-     * @static
1203
-     * @return void
1204
-     */
1205
-    public static function insert_default_status_codes()
1206
-    {
1207
-
1208
-        global $wpdb;
1209
-
1210
-        if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1211
-
1212
-            $table_name = EEM_Status::instance()->table();
1213
-
1214
-            $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' );";
1215
-            $wpdb->query($SQL);
1216
-
1217
-            $SQL = "INSERT INTO $table_name
1159
+										'event_espresso'
1160
+									),
1161
+									$QST_ID),
1162
+								'error');
1163
+							continue;
1164
+						}
1165
+					}
1166
+					// add system questions to groups
1167
+					$wpdb->insert(
1168
+						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1169
+						array(
1170
+							'QSG_ID'    => $QSG_ID,
1171
+							'QST_ID'    => $QST_ID,
1172
+							'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1173
+						),
1174
+						array('%d', '%d', '%d')
1175
+					);
1176
+				}
1177
+			}
1178
+		}
1179
+	}
1180
+
1181
+
1182
+	/**
1183
+	 * Makes sure the default payment method (Invoice) is active.
1184
+	 * This used to be done automatically as part of constructing the old gateways config
1185
+	 *
1186
+	 * @throws \EE_Error
1187
+	 */
1188
+	public static function insert_default_payment_methods()
1189
+	{
1190
+		if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1191
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
1192
+			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1193
+		} else {
1194
+			EEM_Payment_Method::instance()->verify_button_urls();
1195
+		}
1196
+	}
1197
+
1198
+	/**
1199
+	 * insert_default_status_codes
1200
+	 *
1201
+	 * @access public
1202
+	 * @static
1203
+	 * @return void
1204
+	 */
1205
+	public static function insert_default_status_codes()
1206
+	{
1207
+
1208
+		global $wpdb;
1209
+
1210
+		if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1211
+
1212
+			$table_name = EEM_Status::instance()->table();
1213
+
1214
+			$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' );";
1215
+			$wpdb->query($SQL);
1216
+
1217
+			$SQL = "INSERT INTO $table_name
1218 1218
 					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1219 1219
 					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1220 1220
 					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
@@ -1254,521 +1254,521 @@  discard block
 block discarded – undo
1254 1254
 					('MID', 'IDLE', 'message', 0, NULL, 1),
1255 1255
 					('MRS', 'RESEND', 'message', 0, NULL, 1),
1256 1256
 					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1257
-            $wpdb->query($SQL);
1258
-
1259
-        }
1260
-
1261
-    }
1262
-
1263
-
1264
-    /**
1265
-     * create_upload_directories
1266
-     * Creates folders in the uploads directory to facilitate addons and templates
1267
-     *
1268
-     * @access public
1269
-     * @static
1270
-     * @return boolean success of verifying upload directories exist
1271
-     */
1272
-    public static function create_upload_directories()
1273
-    {
1274
-        // Create the required folders
1275
-        $folders = array(
1276
-            EVENT_ESPRESSO_TEMPLATE_DIR,
1277
-            EVENT_ESPRESSO_GATEWAY_DIR,
1278
-            EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1279
-            EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1280
-            EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1281
-        );
1282
-        foreach ($folders as $folder) {
1283
-            try {
1284
-                EEH_File::ensure_folder_exists_and_is_writable($folder);
1285
-                @ chmod($folder, 0755);
1286
-            } catch (EE_Error $e) {
1287
-                EE_Error::add_error(
1288
-                    sprintf(
1289
-                        __('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1290
-                        $folder,
1291
-                        '<br />' . $e->getMessage()
1292
-                    ),
1293
-                    __FILE__, __FUNCTION__, __LINE__
1294
-                );
1295
-                //indicate we'll need to fix this later
1296
-                update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1297
-                return false;
1298
-            }
1299
-        }
1300
-        //just add the .htaccess file to the logs directory to begin with. Even if logging
1301
-        //is disabled, there might be activation errors recorded in there
1302
-        EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1303
-        //remember EE's folders are all good
1304
-        delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1305
-        return true;
1306
-    }
1307
-
1308
-    /**
1309
-     * Whether the upload directories need to be fixed or not.
1310
-     * If EE is installed but filesystem access isn't initially available,
1311
-     * we need to get the user's filesystem credentials and THEN create them,
1312
-     * so there might be period of time when EE is installed but its
1313
-     * upload directories aren't available. This indicates such a state
1314
-     *
1315
-     * @return boolean
1316
-     */
1317
-    public static function upload_directories_incomplete()
1318
-    {
1319
-        return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * generate_default_message_templates
1325
-     *
1326
-     * @static
1327
-     * @throws EE_Error
1328
-     * @return bool     true means new templates were created.
1329
-     *                  false means no templates were created.
1330
-     *                  This is NOT an error flag. To check for errors you will want
1331
-     *                  to use either EE_Error or a try catch for an EE_Error exception.
1332
-     */
1333
-    public static function generate_default_message_templates()
1334
-    {
1335
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1336
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1337
-        /*
1257
+			$wpdb->query($SQL);
1258
+
1259
+		}
1260
+
1261
+	}
1262
+
1263
+
1264
+	/**
1265
+	 * create_upload_directories
1266
+	 * Creates folders in the uploads directory to facilitate addons and templates
1267
+	 *
1268
+	 * @access public
1269
+	 * @static
1270
+	 * @return boolean success of verifying upload directories exist
1271
+	 */
1272
+	public static function create_upload_directories()
1273
+	{
1274
+		// Create the required folders
1275
+		$folders = array(
1276
+			EVENT_ESPRESSO_TEMPLATE_DIR,
1277
+			EVENT_ESPRESSO_GATEWAY_DIR,
1278
+			EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1279
+			EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1280
+			EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1281
+		);
1282
+		foreach ($folders as $folder) {
1283
+			try {
1284
+				EEH_File::ensure_folder_exists_and_is_writable($folder);
1285
+				@ chmod($folder, 0755);
1286
+			} catch (EE_Error $e) {
1287
+				EE_Error::add_error(
1288
+					sprintf(
1289
+						__('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1290
+						$folder,
1291
+						'<br />' . $e->getMessage()
1292
+					),
1293
+					__FILE__, __FUNCTION__, __LINE__
1294
+				);
1295
+				//indicate we'll need to fix this later
1296
+				update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1297
+				return false;
1298
+			}
1299
+		}
1300
+		//just add the .htaccess file to the logs directory to begin with. Even if logging
1301
+		//is disabled, there might be activation errors recorded in there
1302
+		EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1303
+		//remember EE's folders are all good
1304
+		delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1305
+		return true;
1306
+	}
1307
+
1308
+	/**
1309
+	 * Whether the upload directories need to be fixed or not.
1310
+	 * If EE is installed but filesystem access isn't initially available,
1311
+	 * we need to get the user's filesystem credentials and THEN create them,
1312
+	 * so there might be period of time when EE is installed but its
1313
+	 * upload directories aren't available. This indicates such a state
1314
+	 *
1315
+	 * @return boolean
1316
+	 */
1317
+	public static function upload_directories_incomplete()
1318
+	{
1319
+		return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * generate_default_message_templates
1325
+	 *
1326
+	 * @static
1327
+	 * @throws EE_Error
1328
+	 * @return bool     true means new templates were created.
1329
+	 *                  false means no templates were created.
1330
+	 *                  This is NOT an error flag. To check for errors you will want
1331
+	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1332
+	 */
1333
+	public static function generate_default_message_templates()
1334
+	{
1335
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1336
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1337
+		/*
1338 1338
          * This first method is taking care of ensuring any default messengers
1339 1339
          * that should be made active and have templates generated are done.
1340 1340
          */
1341
-        $new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1342
-            $message_resource_manager
1343
-        );
1344
-        /**
1345
-         * This method is verifying there are no NEW default message types
1346
-         * for ACTIVE messengers that need activated (and corresponding templates setup).
1347
-         */
1348
-        $new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1349
-            $message_resource_manager
1350
-        );
1351
-        //after all is done, let's persist these changes to the db.
1352
-        $message_resource_manager->update_has_activated_messengers_option();
1353
-        $message_resource_manager->update_active_messengers_option();
1354
-        // will return true if either of these are true.  Otherwise will return false.
1355
-        return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1356
-    }
1357
-
1358
-
1359
-
1360
-    /**
1361
-     * @param \EE_Message_Resource_Manager $message_resource_manager
1362
-     * @return array|bool
1363
-     * @throws \EE_Error
1364
-     */
1365
-    protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1366
-        EE_Message_Resource_Manager $message_resource_manager
1367
-    ) {
1368
-        /** @type EE_messenger[] $active_messengers */
1369
-        $active_messengers = $message_resource_manager->active_messengers();
1370
-        $installed_message_types = $message_resource_manager->installed_message_types();
1371
-        $templates_created = false;
1372
-        foreach ($active_messengers as $active_messenger) {
1373
-            $default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1374
-            $default_message_type_names_to_activate = array();
1375
-            // looping through each default message type reported by the messenger
1376
-            // and setup the actual message types to activate.
1377
-            foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1378
-                // if already active or has already been activated before we skip
1379
-                // (otherwise we might reactivate something user's intentionally deactivated.)
1380
-                // we also skip if the message type is not installed.
1381
-                if (
1382
-                    $message_resource_manager->has_message_type_been_activated_for_messenger(
1383
-                        $default_message_type_name_for_messenger,
1384
-                        $active_messenger->name
1385
-                    )
1386
-                    || $message_resource_manager->is_message_type_active_for_messenger(
1387
-                        $active_messenger->name,
1388
-                        $default_message_type_name_for_messenger
1389
-                    )
1390
-                    || ! isset($installed_message_types[$default_message_type_name_for_messenger])
1391
-                ) {
1392
-                    continue;
1393
-                }
1394
-                $default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1395
-            }
1396
-            //let's activate!
1397
-            $message_resource_manager->ensure_message_types_are_active(
1398
-                $default_message_type_names_to_activate,
1399
-                $active_messenger->name,
1400
-                false
1401
-            );
1402
-            //activate the templates for these message types
1403
-            if ( ! empty($default_message_type_names_to_activate)) {
1404
-                $templates_created = EEH_MSG_Template::generate_new_templates(
1405
-                    $active_messenger->name,
1406
-                    $default_message_type_names_for_messenger,
1407
-                    '',
1408
-                    true
1409
-                );
1410
-            }
1411
-        }
1412
-        return $templates_created;
1413
-    }
1414
-
1415
-
1416
-
1417
-    /**
1418
-     * This will activate and generate default messengers and default message types for those messengers.
1419
-     *
1420
-     * @param EE_message_Resource_Manager $message_resource_manager
1421
-     * @return array|bool  True means there were default messengers and message type templates generated.
1422
-     *                     False means that there were no templates generated
1423
-     *                     (which could simply mean there are no default message types for a messenger).
1424
-     * @throws EE_Error
1425
-     */
1426
-    protected static function _activate_and_generate_default_messengers_and_message_templates(
1427
-        EE_Message_Resource_Manager $message_resource_manager
1428
-    ) {
1429
-        /** @type EE_messenger[] $messengers_to_generate */
1430
-        $messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1431
-        $installed_message_types = $message_resource_manager->installed_message_types();
1432
-        $templates_generated = false;
1433
-        foreach ($messengers_to_generate as $messenger_to_generate) {
1434
-            $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1435
-            //verify the default message types match an installed message type.
1436
-            foreach ($default_message_type_names_for_messenger as $key => $name) {
1437
-                if (
1438
-                    ! isset($installed_message_types[$name])
1439
-                    || $message_resource_manager->has_message_type_been_activated_for_messenger(
1440
-                        $name,
1441
-                        $messenger_to_generate->name
1442
-                    )
1443
-                ) {
1444
-                    unset($default_message_type_names_for_messenger[$key]);
1445
-                }
1446
-            }
1447
-            // in previous iterations, the active_messengers option in the db
1448
-            // needed updated before calling create templates. however with the changes this may not be necessary.
1449
-            // This comment is left here just in case we discover that we _do_ need to update before
1450
-            // passing off to create templates (after the refactor is done).
1451
-            // @todo remove this comment when determined not necessary.
1452
-            $message_resource_manager->activate_messenger(
1453
-                $messenger_to_generate->name,
1454
-                $default_message_type_names_for_messenger,
1455
-                false
1456
-            );
1457
-            //create any templates needing created (or will reactivate templates already generated as necessary).
1458
-            if ( ! empty($default_message_type_names_for_messenger)) {
1459
-                $templates_generated = EEH_MSG_Template::generate_new_templates(
1460
-                    $messenger_to_generate->name,
1461
-                    $default_message_type_names_for_messenger,
1462
-                    '',
1463
-                    true
1464
-                );
1465
-            }
1466
-        }
1467
-        return $templates_generated;
1468
-    }
1469
-
1470
-
1471
-    /**
1472
-     * This returns the default messengers to generate templates for on activation of EE.
1473
-     * It considers:
1474
-     * - whether a messenger is already active in the db.
1475
-     * - whether a messenger has been made active at any time in the past.
1476
-     *
1477
-     * @static
1478
-     * @param  EE_Message_Resource_Manager $message_resource_manager
1479
-     * @return EE_messenger[]
1480
-     */
1481
-    protected static function _get_default_messengers_to_generate_on_activation(
1482
-        EE_Message_Resource_Manager $message_resource_manager
1483
-    ) {
1484
-        $active_messengers    = $message_resource_manager->active_messengers();
1485
-        $installed_messengers = $message_resource_manager->installed_messengers();
1486
-        $has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1487
-
1488
-        $messengers_to_generate = array();
1489
-        foreach ($installed_messengers as $installed_messenger) {
1490
-            //if installed messenger is a messenger that should be activated on install
1491
-            //and is not already active
1492
-            //and has never been activated
1493
-            if (
1494
-                ! $installed_messenger->activate_on_install
1495
-                || isset($active_messengers[$installed_messenger->name])
1496
-                || isset($has_activated[$installed_messenger->name])
1497
-            ) {
1498
-                continue;
1499
-            }
1500
-            $messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1501
-        }
1502
-        return $messengers_to_generate;
1503
-    }
1504
-
1505
-
1506
-    /**
1507
-     * This simply validates active message types to ensure they actually match installed
1508
-     * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1509
-     * rows are set inactive.
1510
-     * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1511
-     * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1512
-     * are still handled in here.
1513
-     *
1514
-     * @since 4.3.1
1515
-     * @return void
1516
-     */
1517
-    public static function validate_messages_system()
1518
-    {
1519
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1520
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1521
-        $message_resource_manager->validate_active_message_types_are_installed();
1522
-        do_action('AHEE__EEH_Activation__validate_messages_system');
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * create_no_ticket_prices_array
1528
-     *
1529
-     * @access public
1530
-     * @static
1531
-     * @return void
1532
-     */
1533
-    public static function create_no_ticket_prices_array()
1534
-    {
1535
-        // this creates an array for tracking events that have no active ticket prices created
1536
-        // this allows us to warn admins of the situation so that it can be corrected
1537
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1538
-        if (! $espresso_no_ticket_prices) {
1539
-            add_option('ee_no_ticket_prices', array(), '', false);
1540
-        }
1541
-    }
1542
-
1543
-
1544
-    /**
1545
-     * plugin_deactivation
1546
-     *
1547
-     * @access public
1548
-     * @static
1549
-     * @return void
1550
-     */
1551
-    public static function plugin_deactivation()
1552
-    {
1553
-    }
1554
-
1555
-
1556
-    /**
1557
-     * Finds all our EE4 custom post types, and deletes them and their associated data
1558
-     * (like post meta or term relations)
1559
-     *
1560
-     * @global wpdb $wpdb
1561
-     * @throws \EE_Error
1562
-     */
1563
-    public static function delete_all_espresso_cpt_data()
1564
-    {
1565
-        global $wpdb;
1566
-        //get all the CPT post_types
1567
-        $ee_post_types = array();
1568
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1569
-            if (method_exists($model_name, 'instance')) {
1570
-                $model_obj = call_user_func(array($model_name, 'instance'));
1571
-                if ($model_obj instanceof EEM_CPT_Base) {
1572
-                    $ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1573
-                }
1574
-            }
1575
-        }
1576
-        //get all our CPTs
1577
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1578
-        $cpt_ids = $wpdb->get_col($query);
1579
-        //delete each post meta and term relations too
1580
-        foreach ($cpt_ids as $post_id) {
1581
-            wp_delete_post($post_id, true);
1582
-        }
1583
-    }
1584
-
1585
-    /**
1586
-     * Deletes all EE custom tables
1587
-     *
1588
-     * @return array
1589
-     */
1590
-    public static function drop_espresso_tables()
1591
-    {
1592
-        $tables = array();
1593
-        // load registry
1594
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1595
-            if (method_exists($model_name, 'instance')) {
1596
-                $model_obj = call_user_func(array($model_name, 'instance'));
1597
-                if ($model_obj instanceof EEM_Base) {
1598
-                    foreach ($model_obj->get_tables() as $table) {
1599
-                        if (strpos($table->get_table_name(), 'esp_')
1600
-                            &&
1601
-                            (
1602
-                                is_main_site()//main site? nuke them all
1603
-                                || ! $table->is_global()//not main site,but not global either. nuke it
1604
-                            )
1605
-                        ) {
1606
-                            $tables[] = $table->get_table_name();
1607
-                        }
1608
-                    }
1609
-                }
1610
-            }
1611
-        }
1612
-
1613
-        //there are some tables whose models were removed.
1614
-        //they should be removed when removing all EE core's data
1615
-        $tables_without_models = array(
1616
-            'esp_promotion',
1617
-            'esp_promotion_applied',
1618
-            'esp_promotion_object',
1619
-            'esp_promotion_rule',
1620
-            'esp_rule',
1621
-        );
1622
-        foreach ($tables_without_models as $table) {
1623
-            $tables[] = $table;
1624
-        }
1625
-        return \EEH_Activation::getTableManager()->dropTables($tables);
1626
-    }
1627
-
1628
-
1629
-
1630
-    /**
1631
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
1632
-     * each table name provided has a wpdb prefix attached, and that it exists.
1633
-     * Returns the list actually deleted
1634
-     *
1635
-     * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1636
-     * @global WPDB $wpdb
1637
-     * @param array $table_names
1638
-     * @return array of table names which we deleted
1639
-     */
1640
-    public static function drop_tables($table_names)
1641
-    {
1642
-        return \EEH_Activation::getTableManager()->dropTables($table_names);
1643
-    }
1644
-
1645
-
1646
-
1647
-    /**
1648
-     * plugin_uninstall
1649
-     *
1650
-     * @access public
1651
-     * @static
1652
-     * @param bool $remove_all
1653
-     * @return void
1654
-     */
1655
-    public static function delete_all_espresso_tables_and_data($remove_all = true)
1656
-    {
1657
-        global $wpdb;
1658
-        self::drop_espresso_tables();
1659
-        $wp_options_to_delete = array(
1660
-            'ee_no_ticket_prices'                => true,
1661
-            'ee_active_messengers'               => true,
1662
-            'ee_has_activated_messenger'         => true,
1663
-            'ee_flush_rewrite_rules'             => true,
1664
-            'ee_config'                          => false,
1665
-            'ee_data_migration_current_db_state' => true,
1666
-            'ee_data_migration_mapping_'         => false,
1667
-            'ee_data_migration_script_'          => false,
1668
-            'ee_data_migrations'                 => true,
1669
-            'ee_dms_map'                         => false,
1670
-            'ee_notices'                         => true,
1671
-            'lang_file_check_'                   => false,
1672
-            'ee_maintenance_mode'                => true,
1673
-            'ee_ueip_optin'                      => true,
1674
-            'ee_ueip_has_notified'               => true,
1675
-            'ee_plugin_activation_errors'        => true,
1676
-            'ee_id_mapping_from'                 => false,
1677
-            'espresso_persistent_admin_notices'  => true,
1678
-            'ee_encryption_key'                  => true,
1679
-            'pue_force_upgrade_'                 => false,
1680
-            'pue_json_error_'                    => false,
1681
-            'pue_install_key_'                   => false,
1682
-            'pue_verification_error_'            => false,
1683
-            'pu_dismissed_upgrade_'              => false,
1684
-            'external_updates-'                  => false,
1685
-            'ee_extra_data'                      => true,
1686
-            'ee_ssn_'                            => false,
1687
-            'ee_rss_'                            => false,
1688
-            'ee_rte_n_tx_'                       => false,
1689
-            'ee_pers_admin_notices'              => true,
1690
-            'ee_job_parameters_'                 => false,
1691
-            'ee_upload_directories_incomplete'   => true,
1692
-            'ee_verified_db_collations'          => true,
1693
-        );
1694
-        if (is_main_site()) {
1695
-            $wp_options_to_delete['ee_network_config'] = true;
1696
-        }
1697
-        $undeleted_options = array();
1698
-        foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1699
-            if ($no_wildcard) {
1700
-                if ( ! delete_option($option_name)) {
1701
-                    $undeleted_options[] = $option_name;
1702
-                }
1703
-            } else {
1704
-                $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1705
-                foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1706
-                    if ( ! delete_option($option_name_from_wildcard)) {
1707
-                        $undeleted_options[] = $option_name_from_wildcard;
1708
-                    }
1709
-                }
1710
-            }
1711
-        }
1712
-        //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1713
-        remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1714
-        if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1715
-            $db_update_sans_ee4 = array();
1716
-            foreach ($espresso_db_update as $version => $times_activated) {
1717
-                if ((string)$version[0] === '3') {//if its NON EE4
1718
-                    $db_update_sans_ee4[$version] = $times_activated;
1719
-                }
1720
-            }
1721
-            update_option('espresso_db_update', $db_update_sans_ee4);
1722
-        }
1723
-        $errors = '';
1724
-        if ( ! empty($undeleted_options)) {
1725
-            $errors .= sprintf(
1726
-                __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1727
-                '<br/>',
1728
-                implode(',<br/>', $undeleted_options)
1729
-            );
1730
-        }
1731
-        if ( ! empty($errors)) {
1732
-            EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1733
-        }
1734
-    }
1735
-
1736
-    /**
1737
-     * Gets the mysql error code from the last used query by wpdb
1738
-     *
1739
-     * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1740
-     */
1741
-    public static function last_wpdb_error_code()
1742
-    {
1743
-        global $wpdb;
1744
-        if ($wpdb->use_mysqli) {
1745
-            return mysqli_errno($wpdb->dbh);
1746
-        } else {
1747
-            return mysql_errno($wpdb->dbh);
1748
-        }
1749
-    }
1750
-
1751
-    /**
1752
-     * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1753
-     *
1754
-     * @global wpdb  $wpdb
1755
-     * @deprecated instead use TableAnalysis::tableExists()
1756
-     * @param string $table_name with or without $wpdb->prefix
1757
-     * @return boolean
1758
-     */
1759
-    public static function table_exists($table_name)
1760
-    {
1761
-        return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1762
-    }
1763
-
1764
-    /**
1765
-     * Resets the cache on EEH_Activation
1766
-     */
1767
-    public static function reset()
1768
-    {
1769
-        self::$_default_creator_id                             = null;
1770
-        self::$_initialized_db_content_already_in_this_request = false;
1771
-    }
1341
+		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1342
+			$message_resource_manager
1343
+		);
1344
+		/**
1345
+		 * This method is verifying there are no NEW default message types
1346
+		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1347
+		 */
1348
+		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1349
+			$message_resource_manager
1350
+		);
1351
+		//after all is done, let's persist these changes to the db.
1352
+		$message_resource_manager->update_has_activated_messengers_option();
1353
+		$message_resource_manager->update_active_messengers_option();
1354
+		// will return true if either of these are true.  Otherwise will return false.
1355
+		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1356
+	}
1357
+
1358
+
1359
+
1360
+	/**
1361
+	 * @param \EE_Message_Resource_Manager $message_resource_manager
1362
+	 * @return array|bool
1363
+	 * @throws \EE_Error
1364
+	 */
1365
+	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1366
+		EE_Message_Resource_Manager $message_resource_manager
1367
+	) {
1368
+		/** @type EE_messenger[] $active_messengers */
1369
+		$active_messengers = $message_resource_manager->active_messengers();
1370
+		$installed_message_types = $message_resource_manager->installed_message_types();
1371
+		$templates_created = false;
1372
+		foreach ($active_messengers as $active_messenger) {
1373
+			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1374
+			$default_message_type_names_to_activate = array();
1375
+			// looping through each default message type reported by the messenger
1376
+			// and setup the actual message types to activate.
1377
+			foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1378
+				// if already active or has already been activated before we skip
1379
+				// (otherwise we might reactivate something user's intentionally deactivated.)
1380
+				// we also skip if the message type is not installed.
1381
+				if (
1382
+					$message_resource_manager->has_message_type_been_activated_for_messenger(
1383
+						$default_message_type_name_for_messenger,
1384
+						$active_messenger->name
1385
+					)
1386
+					|| $message_resource_manager->is_message_type_active_for_messenger(
1387
+						$active_messenger->name,
1388
+						$default_message_type_name_for_messenger
1389
+					)
1390
+					|| ! isset($installed_message_types[$default_message_type_name_for_messenger])
1391
+				) {
1392
+					continue;
1393
+				}
1394
+				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1395
+			}
1396
+			//let's activate!
1397
+			$message_resource_manager->ensure_message_types_are_active(
1398
+				$default_message_type_names_to_activate,
1399
+				$active_messenger->name,
1400
+				false
1401
+			);
1402
+			//activate the templates for these message types
1403
+			if ( ! empty($default_message_type_names_to_activate)) {
1404
+				$templates_created = EEH_MSG_Template::generate_new_templates(
1405
+					$active_messenger->name,
1406
+					$default_message_type_names_for_messenger,
1407
+					'',
1408
+					true
1409
+				);
1410
+			}
1411
+		}
1412
+		return $templates_created;
1413
+	}
1414
+
1415
+
1416
+
1417
+	/**
1418
+	 * This will activate and generate default messengers and default message types for those messengers.
1419
+	 *
1420
+	 * @param EE_message_Resource_Manager $message_resource_manager
1421
+	 * @return array|bool  True means there were default messengers and message type templates generated.
1422
+	 *                     False means that there were no templates generated
1423
+	 *                     (which could simply mean there are no default message types for a messenger).
1424
+	 * @throws EE_Error
1425
+	 */
1426
+	protected static function _activate_and_generate_default_messengers_and_message_templates(
1427
+		EE_Message_Resource_Manager $message_resource_manager
1428
+	) {
1429
+		/** @type EE_messenger[] $messengers_to_generate */
1430
+		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1431
+		$installed_message_types = $message_resource_manager->installed_message_types();
1432
+		$templates_generated = false;
1433
+		foreach ($messengers_to_generate as $messenger_to_generate) {
1434
+			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1435
+			//verify the default message types match an installed message type.
1436
+			foreach ($default_message_type_names_for_messenger as $key => $name) {
1437
+				if (
1438
+					! isset($installed_message_types[$name])
1439
+					|| $message_resource_manager->has_message_type_been_activated_for_messenger(
1440
+						$name,
1441
+						$messenger_to_generate->name
1442
+					)
1443
+				) {
1444
+					unset($default_message_type_names_for_messenger[$key]);
1445
+				}
1446
+			}
1447
+			// in previous iterations, the active_messengers option in the db
1448
+			// needed updated before calling create templates. however with the changes this may not be necessary.
1449
+			// This comment is left here just in case we discover that we _do_ need to update before
1450
+			// passing off to create templates (after the refactor is done).
1451
+			// @todo remove this comment when determined not necessary.
1452
+			$message_resource_manager->activate_messenger(
1453
+				$messenger_to_generate->name,
1454
+				$default_message_type_names_for_messenger,
1455
+				false
1456
+			);
1457
+			//create any templates needing created (or will reactivate templates already generated as necessary).
1458
+			if ( ! empty($default_message_type_names_for_messenger)) {
1459
+				$templates_generated = EEH_MSG_Template::generate_new_templates(
1460
+					$messenger_to_generate->name,
1461
+					$default_message_type_names_for_messenger,
1462
+					'',
1463
+					true
1464
+				);
1465
+			}
1466
+		}
1467
+		return $templates_generated;
1468
+	}
1469
+
1470
+
1471
+	/**
1472
+	 * This returns the default messengers to generate templates for on activation of EE.
1473
+	 * It considers:
1474
+	 * - whether a messenger is already active in the db.
1475
+	 * - whether a messenger has been made active at any time in the past.
1476
+	 *
1477
+	 * @static
1478
+	 * @param  EE_Message_Resource_Manager $message_resource_manager
1479
+	 * @return EE_messenger[]
1480
+	 */
1481
+	protected static function _get_default_messengers_to_generate_on_activation(
1482
+		EE_Message_Resource_Manager $message_resource_manager
1483
+	) {
1484
+		$active_messengers    = $message_resource_manager->active_messengers();
1485
+		$installed_messengers = $message_resource_manager->installed_messengers();
1486
+		$has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1487
+
1488
+		$messengers_to_generate = array();
1489
+		foreach ($installed_messengers as $installed_messenger) {
1490
+			//if installed messenger is a messenger that should be activated on install
1491
+			//and is not already active
1492
+			//and has never been activated
1493
+			if (
1494
+				! $installed_messenger->activate_on_install
1495
+				|| isset($active_messengers[$installed_messenger->name])
1496
+				|| isset($has_activated[$installed_messenger->name])
1497
+			) {
1498
+				continue;
1499
+			}
1500
+			$messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1501
+		}
1502
+		return $messengers_to_generate;
1503
+	}
1504
+
1505
+
1506
+	/**
1507
+	 * This simply validates active message types to ensure they actually match installed
1508
+	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1509
+	 * rows are set inactive.
1510
+	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1511
+	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1512
+	 * are still handled in here.
1513
+	 *
1514
+	 * @since 4.3.1
1515
+	 * @return void
1516
+	 */
1517
+	public static function validate_messages_system()
1518
+	{
1519
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1520
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1521
+		$message_resource_manager->validate_active_message_types_are_installed();
1522
+		do_action('AHEE__EEH_Activation__validate_messages_system');
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * create_no_ticket_prices_array
1528
+	 *
1529
+	 * @access public
1530
+	 * @static
1531
+	 * @return void
1532
+	 */
1533
+	public static function create_no_ticket_prices_array()
1534
+	{
1535
+		// this creates an array for tracking events that have no active ticket prices created
1536
+		// this allows us to warn admins of the situation so that it can be corrected
1537
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1538
+		if (! $espresso_no_ticket_prices) {
1539
+			add_option('ee_no_ticket_prices', array(), '', false);
1540
+		}
1541
+	}
1542
+
1543
+
1544
+	/**
1545
+	 * plugin_deactivation
1546
+	 *
1547
+	 * @access public
1548
+	 * @static
1549
+	 * @return void
1550
+	 */
1551
+	public static function plugin_deactivation()
1552
+	{
1553
+	}
1554
+
1555
+
1556
+	/**
1557
+	 * Finds all our EE4 custom post types, and deletes them and their associated data
1558
+	 * (like post meta or term relations)
1559
+	 *
1560
+	 * @global wpdb $wpdb
1561
+	 * @throws \EE_Error
1562
+	 */
1563
+	public static function delete_all_espresso_cpt_data()
1564
+	{
1565
+		global $wpdb;
1566
+		//get all the CPT post_types
1567
+		$ee_post_types = array();
1568
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1569
+			if (method_exists($model_name, 'instance')) {
1570
+				$model_obj = call_user_func(array($model_name, 'instance'));
1571
+				if ($model_obj instanceof EEM_CPT_Base) {
1572
+					$ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1573
+				}
1574
+			}
1575
+		}
1576
+		//get all our CPTs
1577
+		$query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1578
+		$cpt_ids = $wpdb->get_col($query);
1579
+		//delete each post meta and term relations too
1580
+		foreach ($cpt_ids as $post_id) {
1581
+			wp_delete_post($post_id, true);
1582
+		}
1583
+	}
1584
+
1585
+	/**
1586
+	 * Deletes all EE custom tables
1587
+	 *
1588
+	 * @return array
1589
+	 */
1590
+	public static function drop_espresso_tables()
1591
+	{
1592
+		$tables = array();
1593
+		// load registry
1594
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1595
+			if (method_exists($model_name, 'instance')) {
1596
+				$model_obj = call_user_func(array($model_name, 'instance'));
1597
+				if ($model_obj instanceof EEM_Base) {
1598
+					foreach ($model_obj->get_tables() as $table) {
1599
+						if (strpos($table->get_table_name(), 'esp_')
1600
+							&&
1601
+							(
1602
+								is_main_site()//main site? nuke them all
1603
+								|| ! $table->is_global()//not main site,but not global either. nuke it
1604
+							)
1605
+						) {
1606
+							$tables[] = $table->get_table_name();
1607
+						}
1608
+					}
1609
+				}
1610
+			}
1611
+		}
1612
+
1613
+		//there are some tables whose models were removed.
1614
+		//they should be removed when removing all EE core's data
1615
+		$tables_without_models = array(
1616
+			'esp_promotion',
1617
+			'esp_promotion_applied',
1618
+			'esp_promotion_object',
1619
+			'esp_promotion_rule',
1620
+			'esp_rule',
1621
+		);
1622
+		foreach ($tables_without_models as $table) {
1623
+			$tables[] = $table;
1624
+		}
1625
+		return \EEH_Activation::getTableManager()->dropTables($tables);
1626
+	}
1627
+
1628
+
1629
+
1630
+	/**
1631
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1632
+	 * each table name provided has a wpdb prefix attached, and that it exists.
1633
+	 * Returns the list actually deleted
1634
+	 *
1635
+	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1636
+	 * @global WPDB $wpdb
1637
+	 * @param array $table_names
1638
+	 * @return array of table names which we deleted
1639
+	 */
1640
+	public static function drop_tables($table_names)
1641
+	{
1642
+		return \EEH_Activation::getTableManager()->dropTables($table_names);
1643
+	}
1644
+
1645
+
1646
+
1647
+	/**
1648
+	 * plugin_uninstall
1649
+	 *
1650
+	 * @access public
1651
+	 * @static
1652
+	 * @param bool $remove_all
1653
+	 * @return void
1654
+	 */
1655
+	public static function delete_all_espresso_tables_and_data($remove_all = true)
1656
+	{
1657
+		global $wpdb;
1658
+		self::drop_espresso_tables();
1659
+		$wp_options_to_delete = array(
1660
+			'ee_no_ticket_prices'                => true,
1661
+			'ee_active_messengers'               => true,
1662
+			'ee_has_activated_messenger'         => true,
1663
+			'ee_flush_rewrite_rules'             => true,
1664
+			'ee_config'                          => false,
1665
+			'ee_data_migration_current_db_state' => true,
1666
+			'ee_data_migration_mapping_'         => false,
1667
+			'ee_data_migration_script_'          => false,
1668
+			'ee_data_migrations'                 => true,
1669
+			'ee_dms_map'                         => false,
1670
+			'ee_notices'                         => true,
1671
+			'lang_file_check_'                   => false,
1672
+			'ee_maintenance_mode'                => true,
1673
+			'ee_ueip_optin'                      => true,
1674
+			'ee_ueip_has_notified'               => true,
1675
+			'ee_plugin_activation_errors'        => true,
1676
+			'ee_id_mapping_from'                 => false,
1677
+			'espresso_persistent_admin_notices'  => true,
1678
+			'ee_encryption_key'                  => true,
1679
+			'pue_force_upgrade_'                 => false,
1680
+			'pue_json_error_'                    => false,
1681
+			'pue_install_key_'                   => false,
1682
+			'pue_verification_error_'            => false,
1683
+			'pu_dismissed_upgrade_'              => false,
1684
+			'external_updates-'                  => false,
1685
+			'ee_extra_data'                      => true,
1686
+			'ee_ssn_'                            => false,
1687
+			'ee_rss_'                            => false,
1688
+			'ee_rte_n_tx_'                       => false,
1689
+			'ee_pers_admin_notices'              => true,
1690
+			'ee_job_parameters_'                 => false,
1691
+			'ee_upload_directories_incomplete'   => true,
1692
+			'ee_verified_db_collations'          => true,
1693
+		);
1694
+		if (is_main_site()) {
1695
+			$wp_options_to_delete['ee_network_config'] = true;
1696
+		}
1697
+		$undeleted_options = array();
1698
+		foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1699
+			if ($no_wildcard) {
1700
+				if ( ! delete_option($option_name)) {
1701
+					$undeleted_options[] = $option_name;
1702
+				}
1703
+			} else {
1704
+				$option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1705
+				foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1706
+					if ( ! delete_option($option_name_from_wildcard)) {
1707
+						$undeleted_options[] = $option_name_from_wildcard;
1708
+					}
1709
+				}
1710
+			}
1711
+		}
1712
+		//also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1713
+		remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1714
+		if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1715
+			$db_update_sans_ee4 = array();
1716
+			foreach ($espresso_db_update as $version => $times_activated) {
1717
+				if ((string)$version[0] === '3') {//if its NON EE4
1718
+					$db_update_sans_ee4[$version] = $times_activated;
1719
+				}
1720
+			}
1721
+			update_option('espresso_db_update', $db_update_sans_ee4);
1722
+		}
1723
+		$errors = '';
1724
+		if ( ! empty($undeleted_options)) {
1725
+			$errors .= sprintf(
1726
+				__('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1727
+				'<br/>',
1728
+				implode(',<br/>', $undeleted_options)
1729
+			);
1730
+		}
1731
+		if ( ! empty($errors)) {
1732
+			EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1733
+		}
1734
+	}
1735
+
1736
+	/**
1737
+	 * Gets the mysql error code from the last used query by wpdb
1738
+	 *
1739
+	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1740
+	 */
1741
+	public static function last_wpdb_error_code()
1742
+	{
1743
+		global $wpdb;
1744
+		if ($wpdb->use_mysqli) {
1745
+			return mysqli_errno($wpdb->dbh);
1746
+		} else {
1747
+			return mysql_errno($wpdb->dbh);
1748
+		}
1749
+	}
1750
+
1751
+	/**
1752
+	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1753
+	 *
1754
+	 * @global wpdb  $wpdb
1755
+	 * @deprecated instead use TableAnalysis::tableExists()
1756
+	 * @param string $table_name with or without $wpdb->prefix
1757
+	 * @return boolean
1758
+	 */
1759
+	public static function table_exists($table_name)
1760
+	{
1761
+		return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1762
+	}
1763
+
1764
+	/**
1765
+	 * Resets the cache on EEH_Activation
1766
+	 */
1767
+	public static function reset()
1768
+	{
1769
+		self::$_default_creator_id                             = null;
1770
+		self::$_initialized_db_content_already_in_this_request = false;
1771
+	}
1772 1772
 }
1773 1773
 // End of file EEH_Activation.helper.php
1774 1774
 // Location: /helpers/EEH_Activation.core.php
Please login to merge, or discard this patch.
Spacing   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -61,7 +61,7 @@  discard block
 block discarded – undo
61 61
      */
62 62
     public static function getTableAnalysis()
63 63
     {
64
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
64
+        if ( ! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
65 65
             self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
66 66
         }
67 67
         return self::$table_analysis;
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
      */
74 74
     public static function getTableManager()
75 75
     {
76
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
76
+        if ( ! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
77 77
             self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
78 78
         }
79 79
         return self::$table_manager;
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
         if ($which_to_include === 'old') {
190 190
             $cron_tasks = array_filter(
191 191
                 $cron_tasks,
192
-                function ($value) {
192
+                function($value) {
193 193
                     return $value === EEH_Activation::cron_task_no_longer_in_use;
194 194
                 }
195 195
             );
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
     {
220 220
 
221 221
         foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
222
-            if (! wp_next_scheduled($hook_name)) {
222
+            if ( ! wp_next_scheduled($hook_name)) {
223 223
                 wp_schedule_event(time(), $frequency, $hook_name);
224 224
             }
225 225
         }
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
             3
313 313
         );
314 314
         //EE_Config::reset();
315
-        if (! EE_Config::logging_enabled()) {
315
+        if ( ! EE_Config::logging_enabled()) {
316 316
             delete_option(EE_Config::LOG_NAME);
317 317
         }
318 318
     }
@@ -327,7 +327,7 @@  discard block
 block discarded – undo
327 327
     public static function load_calendar_config()
328 328
     {
329 329
         // grab array of all plugin folders and loop thru it
330
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
330
+        $plugins = glob(WP_PLUGIN_DIR.DS.'*', GLOB_ONLYDIR);
331 331
         if (empty($plugins)) {
332 332
             return;
333 333
         }
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
                 || strpos($plugin, 'calendar') !== false
345 345
             ) {
346 346
                 // this is what we are looking for
347
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
347
+                $calendar_config = $plugin_path.DS.'EE_Calendar_Config.php';
348 348
                 // does it exist in this folder ?
349 349
                 if (is_readable($calendar_config)) {
350 350
                     // YEAH! let's load it
@@ -477,7 +477,7 @@  discard block
 block discarded – undo
477 477
             ) {
478 478
                 //update Config with post ID
479 479
                 $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
480
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
480
+                if ( ! EE_Config::instance()->update_espresso_config(false, false)) {
481 481
                     $msg = __(
482 482
                         'The Event Espresso critical page configuration settings could not be updated.',
483 483
                         'event_espresso'
@@ -526,7 +526,7 @@  discard block
 block discarded – undo
526 526
     public static function get_page_by_ee_shortcode($ee_shortcode)
527 527
     {
528 528
         global $wpdb;
529
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
529
+        $shortcode_and_opening_bracket = '['.$ee_shortcode;
530 530
         $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
531 531
         if ($post_id) {
532 532
             return get_post($post_id);
@@ -552,11 +552,11 @@  discard block
 block discarded – undo
552 552
             'post_status'    => 'publish',
553 553
             'post_type'      => 'page',
554 554
             'comment_status' => 'closed',
555
-            'post_content'   => '[' . $critical_page['code'] . ']',
555
+            'post_content'   => '['.$critical_page['code'].']',
556 556
         );
557 557
 
558 558
         $post_id = wp_insert_post($post_args);
559
-        if (! $post_id) {
559
+        if ( ! $post_id) {
560 560
             $msg = sprintf(
561 561
                 __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
562 562
                 $critical_page['name']
@@ -565,7 +565,7 @@  discard block
 block discarded – undo
565 565
             return $critical_page;
566 566
         }
567 567
         // get newly created post's details
568
-        if (! $critical_page['post'] = get_post($post_id)) {
568
+        if ( ! $critical_page['post'] = get_post($post_id)) {
569 569
             $msg = sprintf(
570 570
                 __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
571 571
                 $critical_page['name']
@@ -652,17 +652,17 @@  discard block
 block discarded – undo
652 652
             $role_to_check
653 653
         );
654 654
         if ($pre_filtered_id !== false) {
655
-            return (int)$pre_filtered_id;
655
+            return (int) $pre_filtered_id;
656 656
         }
657 657
         $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
658 658
         $query = $wpdb->prepare(
659 659
             "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
660
-            '%' . $role_to_check . '%'
660
+            '%'.$role_to_check.'%'
661 661
         );
662 662
         $user_id = $wpdb->get_var($query);
663 663
         $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
664
-        if ($user_id && (int)$user_id) {
665
-            self::$_default_creator_id = (int)$user_id;
664
+        if ($user_id && (int) $user_id) {
665
+            self::$_default_creator_id = (int) $user_id;
666 666
             return self::$_default_creator_id;
667 667
         } else {
668 668
             return null;
@@ -697,7 +697,7 @@  discard block
 block discarded – undo
697 697
         }
698 698
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
699 699
         if ( ! function_exists('dbDelta')) {
700
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
700
+            require_once(ABSPATH.'wp-admin/includes/upgrade.php');
701 701
         }
702 702
         $tableAnalysis = \EEH_Activation::getTableAnalysis();
703 703
         $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
@@ -908,13 +908,13 @@  discard block
 block discarded – undo
908 908
             // reset values array
909 909
             $QSG_values = array();
910 910
             // 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)
911
-            if (! in_array("$QSG_system", $question_groups)) {
911
+            if ( ! in_array("$QSG_system", $question_groups)) {
912 912
                 // add it
913 913
                 switch ($QSG_system) {
914 914
                     case 1:
915 915
                         $QSG_values = array(
916 916
                             'QSG_name'            => __('Personal Information', 'event_espresso'),
917
-                            'QSG_identifier'      => 'personal-information-' . time(),
917
+                            'QSG_identifier'      => 'personal-information-'.time(),
918 918
                             'QSG_desc'            => '',
919 919
                             'QSG_order'           => 1,
920 920
                             'QSG_show_group_name' => 1,
@@ -926,7 +926,7 @@  discard block
 block discarded – undo
926 926
                     case 2:
927 927
                         $QSG_values = array(
928 928
                             'QSG_name'            => __('Address Information', 'event_espresso'),
929
-                            'QSG_identifier'      => 'address-information-' . time(),
929
+                            'QSG_identifier'      => 'address-information-'.time(),
930 930
                             'QSG_desc'            => '',
931 931
                             'QSG_order'           => 2,
932 932
                             'QSG_show_group_name' => 1,
@@ -937,7 +937,7 @@  discard block
 block discarded – undo
937 937
                         break;
938 938
                 }
939 939
                 // make sure we have some values before inserting them
940
-                if (! empty($QSG_values)) {
940
+                if ( ! empty($QSG_values)) {
941 941
                     // insert system question
942 942
                     $wpdb->insert(
943 943
                         $table_name,
@@ -974,7 +974,7 @@  discard block
 block discarded – undo
974 974
             // reset values array
975 975
             $QST_values = array();
976 976
             // if we don't have what we should have
977
-            if (! in_array($QST_system, $questions)) {
977
+            if ( ! in_array($QST_system, $questions)) {
978 978
                 // add it
979 979
                 switch ($QST_system) {
980 980
                     case 'fname':
@@ -1126,7 +1126,7 @@  discard block
 block discarded – undo
1126 1126
                         );
1127 1127
                         break;
1128 1128
                 }
1129
-                if (! empty($QST_values)) {
1129
+                if ( ! empty($QST_values)) {
1130 1130
                     // insert system question
1131 1131
                     $wpdb->insert(
1132 1132
                         $table_name,
@@ -1187,7 +1187,7 @@  discard block
 block discarded – undo
1187 1187
      */
1188 1188
     public static function insert_default_payment_methods()
1189 1189
     {
1190
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1190
+        if ( ! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1191 1191
             EE_Registry::instance()->load_lib('Payment_Method_Manager');
1192 1192
             EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1193 1193
         } else {
@@ -1275,9 +1275,9 @@  discard block
 block discarded – undo
1275 1275
         $folders = array(
1276 1276
             EVENT_ESPRESSO_TEMPLATE_DIR,
1277 1277
             EVENT_ESPRESSO_GATEWAY_DIR,
1278
-            EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1279
-            EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1280
-            EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1278
+            EVENT_ESPRESSO_UPLOAD_DIR.'logs/',
1279
+            EVENT_ESPRESSO_UPLOAD_DIR.'css/',
1280
+            EVENT_ESPRESSO_UPLOAD_DIR.'tickets/',
1281 1281
         );
1282 1282
         foreach ($folders as $folder) {
1283 1283
             try {
@@ -1288,7 +1288,7 @@  discard block
 block discarded – undo
1288 1288
                     sprintf(
1289 1289
                         __('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1290 1290
                         $folder,
1291
-                        '<br />' . $e->getMessage()
1291
+                        '<br />'.$e->getMessage()
1292 1292
                     ),
1293 1293
                     __FILE__, __FUNCTION__, __LINE__
1294 1294
                 );
@@ -1299,7 +1299,7 @@  discard block
 block discarded – undo
1299 1299
         }
1300 1300
         //just add the .htaccess file to the logs directory to begin with. Even if logging
1301 1301
         //is disabled, there might be activation errors recorded in there
1302
-        EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1302
+        EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR.'logs/');
1303 1303
         //remember EE's folders are all good
1304 1304
         delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1305 1305
         return true;
@@ -1535,7 +1535,7 @@  discard block
 block discarded – undo
1535 1535
         // this creates an array for tracking events that have no active ticket prices created
1536 1536
         // this allows us to warn admins of the situation so that it can be corrected
1537 1537
         $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1538
-        if (! $espresso_no_ticket_prices) {
1538
+        if ( ! $espresso_no_ticket_prices) {
1539 1539
             add_option('ee_no_ticket_prices', array(), '', false);
1540 1540
         }
1541 1541
     }
@@ -1574,7 +1574,7 @@  discard block
 block discarded – undo
1574 1574
             }
1575 1575
         }
1576 1576
         //get all our CPTs
1577
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1577
+        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",", $ee_post_types).")";
1578 1578
         $cpt_ids = $wpdb->get_col($query);
1579 1579
         //delete each post meta and term relations too
1580 1580
         foreach ($cpt_ids as $post_id) {
@@ -1714,7 +1714,7 @@  discard block
 block discarded – undo
1714 1714
         if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1715 1715
             $db_update_sans_ee4 = array();
1716 1716
             foreach ($espresso_db_update as $version => $times_activated) {
1717
-                if ((string)$version[0] === '3') {//if its NON EE4
1717
+                if ((string) $version[0] === '3') {//if its NON EE4
1718 1718
                     $db_update_sans_ee4[$version] = $times_activated;
1719 1719
                 }
1720 1720
             }
Please login to merge, or discard this patch.
admin_pages/messages/EE_Message_List_Table.class.php 2 patches
Indentation   +427 added lines, -427 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if (! defined('EVENT_ESPRESSO_VERSION')) {
3
-    exit('NO direct script access allowed');
3
+	exit('NO direct script access allowed');
4 4
 }
5 5
 
6 6
 /**
@@ -15,430 +15,430 @@  discard block
 block discarded – undo
15 15
 {
16 16
 
17 17
 
18
-    /**
19
-     * @return Messages_Admin_Page
20
-     */
21
-    public function get_admin_page()
22
-    {
23
-        return $this->_admin_page;
24
-    }
25
-
26
-
27
-    protected function _setup_data()
28
-    {
29
-        $this->_data           = $this->_get_messages($this->_per_page, $this->_view);
30
-        $this->_all_data_count = $this->_get_messages($this->_per_page, $this->_view, true);
31
-    }
32
-
33
-
34
-    protected function _set_properties()
35
-    {
36
-        $this->_wp_list_args = array(
37
-            'singular' => __('Message', 'event_espresso'),
38
-            'plural'   => __('Messages', 'event_espresso'),
39
-            'ajax'     => true,
40
-            'screen'   => $this->get_admin_page()->get_current_screen()->id,
41
-        );
42
-
43
-        $this->_columns = array(
44
-            'cb'           => '<input type="checkbox" />',
45
-            'to'           => __('To', 'event_espresso'),
46
-            'from'         => __('From', 'event_espresso'),
47
-            'messenger'    => __('Messenger', 'event_espresso'),
48
-            'message_type' => __('Message Type', 'event_espresso'),
49
-            'context'      => __('Context', 'event_espresso'),
50
-            'modified'     => __('Modified', 'event_espresso'),
51
-            'action'       => __('Actions', 'event_espresso'),
52
-            'msg_id'       => __('ID', 'event_espresso'),
53
-        );
54
-
55
-        $this->_sortable_columns = array(
56
-            'modified'     => array('MSG_modified' => true),
57
-            'message_type' => array('MSG_message_type' => false),
58
-            'messenger'    => array('MSG_messenger' => false),
59
-            'to'           => array('MSG_to' => false),
60
-            'from'         => array('MSG_from' => false),
61
-            'context'      => array('MSG_context' => false),
62
-            'msg_id'       => array('MSG_ID', false),
63
-        );
64
-
65
-        $this->_primary_column = 'to';
66
-
67
-        $this->_hidden_columns = array(
68
-            'msg_id',
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     * This simply sets up the row class for the table rows.
75
-     * Allows for easier overriding of child methods for setting up sorting.
76
-     *
77
-     * @param  object $item the current item
78
-     * @return string
79
-     */
80
-    protected function _get_row_class($item)
81
-    {
82
-        $class = parent::_get_row_class($item);
83
-        //add status class
84
-        $class .= ' ee-status-strip msg-status-' . $item->STS_ID();
85
-        if ($this->_has_checkbox_column) {
86
-            $class .= ' has-checkbox-column';
87
-        }
88
-        return $class;
89
-    }
90
-
91
-
92
-    /**
93
-     * _get_table_filters
94
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
95
-     * get's shown in the table.
96
-     *
97
-     * @abstract
98
-     * @access protected
99
-     * @return string
100
-     * @throws \EE_Error
101
-     */
102
-    protected function _get_table_filters()
103
-    {
104
-        $filters = array();
105
-
106
-        //get select_inputs
107
-        $select_inputs = array(
108
-            $this->_get_messengers_dropdown_filter(),
109
-            $this->_get_message_types_dropdown_filter(),
110
-            $this->_get_contexts_for_message_types_dropdown_filter(),
111
-        );
112
-
113
-        //set filters to select inputs if they aren't empty
114
-        foreach ($select_inputs as $select_input) {
115
-            if ($select_input) {
116
-                $filters[] = $select_input;
117
-            }
118
-        }
119
-        return $filters;
120
-    }
121
-
122
-
123
-    protected function _add_view_counts()
124
-    {
125
-        foreach ($this->_views as $view => $args) {
126
-            $this->_views[$view]['count'] = $this->_get_messages($this->_per_page, $view, true, true);
127
-        }
128
-    }
129
-
130
-
131
-    /**
132
-     * @param EE_Message $message
133
-     * @return string   checkbox
134
-     * @throws \EE_Error
135
-     */
136
-    public function column_cb($message)
137
-    {
138
-        return sprintf('<input type="checkbox" name="MSG_ID[%s]" value="1" />', $message->ID());
139
-    }
140
-
141
-
142
-    /**
143
-     * @param EE_Message $message
144
-     * @return string
145
-     * @throws \EE_Error
146
-     */
147
-    public function column_msg_id(EE_Message $message)
148
-    {
149
-        return $message->ID();
150
-    }
151
-
152
-
153
-    /**
154
-     * @param EE_Message $message
155
-     * @return string    The recipient of the message
156
-     * @throws \EE_Error
157
-     */
158
-    public function column_to(EE_Message $message)
159
-    {
160
-        EE_Registry::instance()->load_helper('URL');
161
-        $actions           = array();
162
-        $actions['delete'] = '<a href="'
163
-                             . EEH_URL::add_query_args_and_nonce(
164
-                array(
165
-                    'page'   => 'espresso_messages',
166
-                    'action' => 'delete_ee_message',
167
-                    'MSG_ID' => $message->ID(),
168
-                ),
169
-                admin_url('admin.php')
170
-            )
171
-                             . '">' . __('Delete', 'event_espresso') . '</a>';
172
-        return esc_html($message->to()) . $this->row_actions($actions);
173
-    }
174
-
175
-
176
-    /**
177
-     * @param EE_Message $message
178
-     * @return string   The sender of the message
179
-     */
180
-    public function column_from(EE_Message $message)
181
-    {
182
-        return esc_html($message->from());
183
-    }
184
-
185
-
186
-    /**
187
-     * @param EE_Message $message
188
-     * @return string  The messenger used to send the message.
189
-     */
190
-    public function column_messenger(EE_Message $message)
191
-    {
192
-        return ucwords($message->messenger_label());
193
-    }
194
-
195
-
196
-    /**
197
-     * @param EE_Message $message
198
-     * @return string  The message type used to generate the message.
199
-     */
200
-    public function column_message_type(EE_Message $message)
201
-    {
202
-        return ucwords($message->message_type_label());
203
-    }
204
-
205
-
206
-    /**
207
-     * @param EE_Message $message
208
-     * @return string  The context the message was generated for.
209
-     */
210
-    public function column_context(EE_Message $message)
211
-    {
212
-        return $message->context_label();
213
-    }
214
-
215
-
216
-    /**
217
-     * @param EE_Message $message
218
-     * @return string    The timestamp when this message was last modified.
219
-     */
220
-    public function column_modified(EE_Message $message)
221
-    {
222
-        return $message->modified();
223
-    }
224
-
225
-
226
-    /**
227
-     * @param EE_Message $message
228
-     * @return string   Actions that can be done on the current message.
229
-     */
230
-    public function column_action(EE_Message $message)
231
-    {
232
-        EE_Registry::instance()->load_helper('MSG_Template');
233
-        $action_links = array(
234
-            'view'                => EEH_MSG_Template::get_message_action_link('view', $message),
235
-            'error'               => EEH_MSG_Template::get_message_action_link('error', $message),
236
-            'generate_now'        => EEH_MSG_Template::get_message_action_link('generate_now', $message),
237
-            'send_now'            => EEH_MSG_Template::get_message_action_link('send_now', $message),
238
-            'queue_for_resending' => EEH_MSG_Template::get_message_action_link('queue_for_resending', $message),
239
-            'view_transaction'    => EEH_MSG_Template::get_message_action_link('view_transaction', $message),
240
-        );
241
-        $content      = '';
242
-        switch ($message->STS_ID()) {
243
-            case EEM_Message::status_sent :
244
-                $content = $action_links['view'] . $action_links['queue_for_resending'] . $action_links['view_transaction'];
245
-                break;
246
-            case EEM_Message::status_resend :
247
-                $content = $action_links['view'] . $action_links['send_now'] . $action_links['view_transaction'];
248
-                break;
249
-            case EEM_Message::status_retry :
250
-                $content = $action_links['view'] . $action_links['send_now'] . $action_links['error'] . $action_links['view_transaction'];
251
-                break;
252
-            case EEM_Message::status_failed :
253
-            case EEM_Message::status_debug_only :
254
-                $content = $action_links['error'] . $action_links['view_transaction'];
255
-                break;
256
-            case EEM_Message::status_idle :
257
-                $content = $action_links['view'] . $action_links['send_now'] . $action_links['view_transaction'];
258
-                break;
259
-            case EEM_Message::status_incomplete;
260
-                $content = $action_links['generate_now'] . $action_links['view_transaction'];
261
-                break;
262
-        }
263
-        return $content;
264
-    }
265
-
266
-
267
-    /**
268
-     * Retrieve the EE_Message objects for the list table.
269
-     *
270
-     * @param int    $perpage The number of items per page
271
-     * @param string $view    The view items are being retrieved for
272
-     * @param bool   $count   Whether to just return a count or not.
273
-     * @param bool   $all     Disregard any paging info (no limit on data returned).
274
-     * @return int|EE_Message[]
275
-     * @throws \EE_Error
276
-     */
277
-    protected function _get_messages($perpage = 10, $view = 'all', $count = false, $all = false)
278
-    {
279
-
280
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
281
-            ? $this->_req_data['paged']
282
-            : 1;
283
-
284
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
285
-            ? $this->_req_data['perpage']
286
-            : $perpage;
287
-
288
-        $offset       = ($current_page - 1) * $per_page;
289
-        $limit        = $all || $count ? null : array($offset, $per_page);
290
-        $query_params = array(
291
-            'order_by' => empty($this->_req_data['orderby']) ? 'MSG_modified' : $this->_req_data['orderby'],
292
-            'order'    => empty($this->_req_data['order']) ? 'DESC' : $this->_req_data['order'],
293
-            'limit'    => $limit,
294
-        );
295
-
296
-        /**
297
-         * Any filters coming in from other routes?
298
-         */
299
-        if (isset($this->_req_data['filterby'])) {
300
-            $query_params = array_merge($query_params, EEM_Message::instance()->filter_by_query_params());
301
-            if ( ! $count) {
302
-                $query_params['group_by'] = 'MSG_ID';
303
-            }
304
-        }
305
-
306
-        //view conditionals
307
-        if ($view !== 'all' && $count && $all) {
308
-            $query_params[0]['AND*view_conditional'] = array(
309
-                'STS_ID' => strtoupper($view),
310
-            );
311
-        }
312
-
313
-        if (! $all && ! empty($this->_req_data['status']) && $this->_req_data['status'] !== 'all') {
314
-            $query_params[0]['AND*view_conditional'] = $this->_req_data === EEM_Message::status_failed
315
-                ? array(
316
-                    'STS_ID' => array(
317
-                        'IN',
318
-                        array(EEM_Message::status_failed, EEM_Message::status_messenger_executing)
319
-                    )
320
-                )
321
-                : array( 'STS_ID' => strtoupper($this->_req_data['status']) );
322
-        }
323
-
324
-        if (! $all && ! empty($this->_req_data['s'])) {
325
-            $search_string         = '%' . $this->_req_data['s'] . '%';
326
-            $query_params[0]['OR'] = array(
327
-                'MSG_to'      => array('LIKE', $search_string),
328
-                'MSG_from'    => array('LIKE', $search_string),
329
-                'MSG_subject' => array('LIKE', $search_string),
330
-                'MSG_content' => array('LIKE', $search_string),
331
-            );
332
-        }
333
-
334
-        //account for debug only status.  We don't show Messages with the EEM_Message::status_debug_only to clients when
335
-        //the messages system is in debug mode.
336
-        //Note: for backward compat with previous iterations, this is necessary because there may be EEM_Message::status_debug_only
337
-        //messages in the database.
338
-        if (! EEM_Message::debug()) {
339
-            $query_params[0]['AND*debug_only_conditional'] = array(
340
-                'STS_ID' => array('!=', EEM_Message::status_debug_only),
341
-            );
342
-        }
343
-
344
-        //account for filters
345
-        if (! $all
346
-            && isset($this->_req_data['ee_messenger_filter_by'])
347
-            && $this->_req_data['ee_messenger_filter_by'] !== 'none_selected'
348
-        ) {
349
-            $query_params[0]['AND*messenger_filter'] = array(
350
-                'MSG_messenger' => $this->_req_data['ee_messenger_filter_by'],
351
-            );
352
-        }
353
-        if (! $all
354
-            && ! empty($this->_req_data['ee_message_type_filter_by'])
355
-            && $this->_req_data['ee_message_type_filter_by'] !== 'none_selected'
356
-        ) {
357
-            $query_params[0]['AND*message_type_filter'] = array(
358
-                'MSG_message_type' => $this->_req_data['ee_message_type_filter_by'],
359
-            );
360
-        }
361
-
362
-        if (! $all
363
-            && ! empty($this->_req_data['ee_context_filter_by'])
364
-            && $this->_req_data['ee_context_filter_by'] !== 'none_selected'
365
-        ) {
366
-            $query_params[0]['AND*context_filter'] = array(
367
-                'MSG_context' => array('IN', explode(',', $this->_req_data['ee_context_filter_by'])),
368
-            );
369
-        }
370
-
371
-        return $count
372
-            /** @type int */
373
-            ? EEM_Message::instance()->count($query_params, null, true)
374
-            /** @type EE_Message[] */
375
-            : EEM_Message::instance()->get_all($query_params);
376
-    }
377
-
378
-
379
-    /**
380
-     * Generate dropdown filter select input for messengers.
381
-     *
382
-     * @return string
383
-     */
384
-    protected function _get_messengers_dropdown_filter()
385
-    {
386
-        $messenger_options                    = array();
387
-        $active_messages_grouped_by_messenger = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
388
-
389
-        //setup array of messenger options
390
-        foreach ($active_messages_grouped_by_messenger as $active_message) {
391
-            if ($active_message instanceof EE_Message) {
392
-                $messenger_options[$active_message->messenger()] = ucwords($active_message->messenger_label());
393
-            }
394
-        }
395
-        return $this->get_admin_page()->get_messengers_select_input($messenger_options);
396
-    }
397
-
398
-
399
-    /**
400
-     * Generate dropdown filter select input for message types
401
-     *
402
-     * @return string
403
-     */
404
-    protected function _get_message_types_dropdown_filter()
405
-    {
406
-        $message_type_options                    = array();
407
-        $active_messages_grouped_by_message_type = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
408
-
409
-        //setup array of message type options
410
-        foreach ($active_messages_grouped_by_message_type as $active_message) {
411
-            if ($active_message instanceof EE_Message) {
412
-                $message_type_options[$active_message->message_type()] = ucwords($active_message->message_type_label());
413
-            }
414
-        }
415
-        return $this->get_admin_page()->get_message_types_select_input($message_type_options);
416
-    }
417
-
418
-
419
-    /**
420
-     * Generate dropdown filter select input for message type contexts
421
-     *
422
-     * @return string
423
-     */
424
-    protected function _get_contexts_for_message_types_dropdown_filter()
425
-    {
426
-        $context_options                    = array();
427
-        $active_messages_grouped_by_context = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
428
-
429
-        //setup array of context options
430
-        foreach ($active_messages_grouped_by_context as $active_message) {
431
-            if ($active_message instanceof EE_Message) {
432
-                $message_type = $active_message->message_type_object();
433
-                if ($message_type instanceof EE_message_type) {
434
-                    foreach ($message_type->get_contexts() as $context => $context_details) {
435
-                        if (isset($context_details['label'])) {
436
-                            $context_options[$context] = $context_details['label'];
437
-                        }
438
-                    }
439
-                }
440
-            }
441
-        }
442
-        return $this->get_admin_page()->get_contexts_for_message_types_select_input($context_options);
443
-    }
18
+	/**
19
+	 * @return Messages_Admin_Page
20
+	 */
21
+	public function get_admin_page()
22
+	{
23
+		return $this->_admin_page;
24
+	}
25
+
26
+
27
+	protected function _setup_data()
28
+	{
29
+		$this->_data           = $this->_get_messages($this->_per_page, $this->_view);
30
+		$this->_all_data_count = $this->_get_messages($this->_per_page, $this->_view, true);
31
+	}
32
+
33
+
34
+	protected function _set_properties()
35
+	{
36
+		$this->_wp_list_args = array(
37
+			'singular' => __('Message', 'event_espresso'),
38
+			'plural'   => __('Messages', 'event_espresso'),
39
+			'ajax'     => true,
40
+			'screen'   => $this->get_admin_page()->get_current_screen()->id,
41
+		);
42
+
43
+		$this->_columns = array(
44
+			'cb'           => '<input type="checkbox" />',
45
+			'to'           => __('To', 'event_espresso'),
46
+			'from'         => __('From', 'event_espresso'),
47
+			'messenger'    => __('Messenger', 'event_espresso'),
48
+			'message_type' => __('Message Type', 'event_espresso'),
49
+			'context'      => __('Context', 'event_espresso'),
50
+			'modified'     => __('Modified', 'event_espresso'),
51
+			'action'       => __('Actions', 'event_espresso'),
52
+			'msg_id'       => __('ID', 'event_espresso'),
53
+		);
54
+
55
+		$this->_sortable_columns = array(
56
+			'modified'     => array('MSG_modified' => true),
57
+			'message_type' => array('MSG_message_type' => false),
58
+			'messenger'    => array('MSG_messenger' => false),
59
+			'to'           => array('MSG_to' => false),
60
+			'from'         => array('MSG_from' => false),
61
+			'context'      => array('MSG_context' => false),
62
+			'msg_id'       => array('MSG_ID', false),
63
+		);
64
+
65
+		$this->_primary_column = 'to';
66
+
67
+		$this->_hidden_columns = array(
68
+			'msg_id',
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 * This simply sets up the row class for the table rows.
75
+	 * Allows for easier overriding of child methods for setting up sorting.
76
+	 *
77
+	 * @param  object $item the current item
78
+	 * @return string
79
+	 */
80
+	protected function _get_row_class($item)
81
+	{
82
+		$class = parent::_get_row_class($item);
83
+		//add status class
84
+		$class .= ' ee-status-strip msg-status-' . $item->STS_ID();
85
+		if ($this->_has_checkbox_column) {
86
+			$class .= ' has-checkbox-column';
87
+		}
88
+		return $class;
89
+	}
90
+
91
+
92
+	/**
93
+	 * _get_table_filters
94
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
95
+	 * get's shown in the table.
96
+	 *
97
+	 * @abstract
98
+	 * @access protected
99
+	 * @return string
100
+	 * @throws \EE_Error
101
+	 */
102
+	protected function _get_table_filters()
103
+	{
104
+		$filters = array();
105
+
106
+		//get select_inputs
107
+		$select_inputs = array(
108
+			$this->_get_messengers_dropdown_filter(),
109
+			$this->_get_message_types_dropdown_filter(),
110
+			$this->_get_contexts_for_message_types_dropdown_filter(),
111
+		);
112
+
113
+		//set filters to select inputs if they aren't empty
114
+		foreach ($select_inputs as $select_input) {
115
+			if ($select_input) {
116
+				$filters[] = $select_input;
117
+			}
118
+		}
119
+		return $filters;
120
+	}
121
+
122
+
123
+	protected function _add_view_counts()
124
+	{
125
+		foreach ($this->_views as $view => $args) {
126
+			$this->_views[$view]['count'] = $this->_get_messages($this->_per_page, $view, true, true);
127
+		}
128
+	}
129
+
130
+
131
+	/**
132
+	 * @param EE_Message $message
133
+	 * @return string   checkbox
134
+	 * @throws \EE_Error
135
+	 */
136
+	public function column_cb($message)
137
+	{
138
+		return sprintf('<input type="checkbox" name="MSG_ID[%s]" value="1" />', $message->ID());
139
+	}
140
+
141
+
142
+	/**
143
+	 * @param EE_Message $message
144
+	 * @return string
145
+	 * @throws \EE_Error
146
+	 */
147
+	public function column_msg_id(EE_Message $message)
148
+	{
149
+		return $message->ID();
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param EE_Message $message
155
+	 * @return string    The recipient of the message
156
+	 * @throws \EE_Error
157
+	 */
158
+	public function column_to(EE_Message $message)
159
+	{
160
+		EE_Registry::instance()->load_helper('URL');
161
+		$actions           = array();
162
+		$actions['delete'] = '<a href="'
163
+							 . EEH_URL::add_query_args_and_nonce(
164
+				array(
165
+					'page'   => 'espresso_messages',
166
+					'action' => 'delete_ee_message',
167
+					'MSG_ID' => $message->ID(),
168
+				),
169
+				admin_url('admin.php')
170
+			)
171
+							 . '">' . __('Delete', 'event_espresso') . '</a>';
172
+		return esc_html($message->to()) . $this->row_actions($actions);
173
+	}
174
+
175
+
176
+	/**
177
+	 * @param EE_Message $message
178
+	 * @return string   The sender of the message
179
+	 */
180
+	public function column_from(EE_Message $message)
181
+	{
182
+		return esc_html($message->from());
183
+	}
184
+
185
+
186
+	/**
187
+	 * @param EE_Message $message
188
+	 * @return string  The messenger used to send the message.
189
+	 */
190
+	public function column_messenger(EE_Message $message)
191
+	{
192
+		return ucwords($message->messenger_label());
193
+	}
194
+
195
+
196
+	/**
197
+	 * @param EE_Message $message
198
+	 * @return string  The message type used to generate the message.
199
+	 */
200
+	public function column_message_type(EE_Message $message)
201
+	{
202
+		return ucwords($message->message_type_label());
203
+	}
204
+
205
+
206
+	/**
207
+	 * @param EE_Message $message
208
+	 * @return string  The context the message was generated for.
209
+	 */
210
+	public function column_context(EE_Message $message)
211
+	{
212
+		return $message->context_label();
213
+	}
214
+
215
+
216
+	/**
217
+	 * @param EE_Message $message
218
+	 * @return string    The timestamp when this message was last modified.
219
+	 */
220
+	public function column_modified(EE_Message $message)
221
+	{
222
+		return $message->modified();
223
+	}
224
+
225
+
226
+	/**
227
+	 * @param EE_Message $message
228
+	 * @return string   Actions that can be done on the current message.
229
+	 */
230
+	public function column_action(EE_Message $message)
231
+	{
232
+		EE_Registry::instance()->load_helper('MSG_Template');
233
+		$action_links = array(
234
+			'view'                => EEH_MSG_Template::get_message_action_link('view', $message),
235
+			'error'               => EEH_MSG_Template::get_message_action_link('error', $message),
236
+			'generate_now'        => EEH_MSG_Template::get_message_action_link('generate_now', $message),
237
+			'send_now'            => EEH_MSG_Template::get_message_action_link('send_now', $message),
238
+			'queue_for_resending' => EEH_MSG_Template::get_message_action_link('queue_for_resending', $message),
239
+			'view_transaction'    => EEH_MSG_Template::get_message_action_link('view_transaction', $message),
240
+		);
241
+		$content      = '';
242
+		switch ($message->STS_ID()) {
243
+			case EEM_Message::status_sent :
244
+				$content = $action_links['view'] . $action_links['queue_for_resending'] . $action_links['view_transaction'];
245
+				break;
246
+			case EEM_Message::status_resend :
247
+				$content = $action_links['view'] . $action_links['send_now'] . $action_links['view_transaction'];
248
+				break;
249
+			case EEM_Message::status_retry :
250
+				$content = $action_links['view'] . $action_links['send_now'] . $action_links['error'] . $action_links['view_transaction'];
251
+				break;
252
+			case EEM_Message::status_failed :
253
+			case EEM_Message::status_debug_only :
254
+				$content = $action_links['error'] . $action_links['view_transaction'];
255
+				break;
256
+			case EEM_Message::status_idle :
257
+				$content = $action_links['view'] . $action_links['send_now'] . $action_links['view_transaction'];
258
+				break;
259
+			case EEM_Message::status_incomplete;
260
+				$content = $action_links['generate_now'] . $action_links['view_transaction'];
261
+				break;
262
+		}
263
+		return $content;
264
+	}
265
+
266
+
267
+	/**
268
+	 * Retrieve the EE_Message objects for the list table.
269
+	 *
270
+	 * @param int    $perpage The number of items per page
271
+	 * @param string $view    The view items are being retrieved for
272
+	 * @param bool   $count   Whether to just return a count or not.
273
+	 * @param bool   $all     Disregard any paging info (no limit on data returned).
274
+	 * @return int|EE_Message[]
275
+	 * @throws \EE_Error
276
+	 */
277
+	protected function _get_messages($perpage = 10, $view = 'all', $count = false, $all = false)
278
+	{
279
+
280
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
281
+			? $this->_req_data['paged']
282
+			: 1;
283
+
284
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
285
+			? $this->_req_data['perpage']
286
+			: $perpage;
287
+
288
+		$offset       = ($current_page - 1) * $per_page;
289
+		$limit        = $all || $count ? null : array($offset, $per_page);
290
+		$query_params = array(
291
+			'order_by' => empty($this->_req_data['orderby']) ? 'MSG_modified' : $this->_req_data['orderby'],
292
+			'order'    => empty($this->_req_data['order']) ? 'DESC' : $this->_req_data['order'],
293
+			'limit'    => $limit,
294
+		);
295
+
296
+		/**
297
+		 * Any filters coming in from other routes?
298
+		 */
299
+		if (isset($this->_req_data['filterby'])) {
300
+			$query_params = array_merge($query_params, EEM_Message::instance()->filter_by_query_params());
301
+			if ( ! $count) {
302
+				$query_params['group_by'] = 'MSG_ID';
303
+			}
304
+		}
305
+
306
+		//view conditionals
307
+		if ($view !== 'all' && $count && $all) {
308
+			$query_params[0]['AND*view_conditional'] = array(
309
+				'STS_ID' => strtoupper($view),
310
+			);
311
+		}
312
+
313
+		if (! $all && ! empty($this->_req_data['status']) && $this->_req_data['status'] !== 'all') {
314
+			$query_params[0]['AND*view_conditional'] = $this->_req_data === EEM_Message::status_failed
315
+				? array(
316
+					'STS_ID' => array(
317
+						'IN',
318
+						array(EEM_Message::status_failed, EEM_Message::status_messenger_executing)
319
+					)
320
+				)
321
+				: array( 'STS_ID' => strtoupper($this->_req_data['status']) );
322
+		}
323
+
324
+		if (! $all && ! empty($this->_req_data['s'])) {
325
+			$search_string         = '%' . $this->_req_data['s'] . '%';
326
+			$query_params[0]['OR'] = array(
327
+				'MSG_to'      => array('LIKE', $search_string),
328
+				'MSG_from'    => array('LIKE', $search_string),
329
+				'MSG_subject' => array('LIKE', $search_string),
330
+				'MSG_content' => array('LIKE', $search_string),
331
+			);
332
+		}
333
+
334
+		//account for debug only status.  We don't show Messages with the EEM_Message::status_debug_only to clients when
335
+		//the messages system is in debug mode.
336
+		//Note: for backward compat with previous iterations, this is necessary because there may be EEM_Message::status_debug_only
337
+		//messages in the database.
338
+		if (! EEM_Message::debug()) {
339
+			$query_params[0]['AND*debug_only_conditional'] = array(
340
+				'STS_ID' => array('!=', EEM_Message::status_debug_only),
341
+			);
342
+		}
343
+
344
+		//account for filters
345
+		if (! $all
346
+			&& isset($this->_req_data['ee_messenger_filter_by'])
347
+			&& $this->_req_data['ee_messenger_filter_by'] !== 'none_selected'
348
+		) {
349
+			$query_params[0]['AND*messenger_filter'] = array(
350
+				'MSG_messenger' => $this->_req_data['ee_messenger_filter_by'],
351
+			);
352
+		}
353
+		if (! $all
354
+			&& ! empty($this->_req_data['ee_message_type_filter_by'])
355
+			&& $this->_req_data['ee_message_type_filter_by'] !== 'none_selected'
356
+		) {
357
+			$query_params[0]['AND*message_type_filter'] = array(
358
+				'MSG_message_type' => $this->_req_data['ee_message_type_filter_by'],
359
+			);
360
+		}
361
+
362
+		if (! $all
363
+			&& ! empty($this->_req_data['ee_context_filter_by'])
364
+			&& $this->_req_data['ee_context_filter_by'] !== 'none_selected'
365
+		) {
366
+			$query_params[0]['AND*context_filter'] = array(
367
+				'MSG_context' => array('IN', explode(',', $this->_req_data['ee_context_filter_by'])),
368
+			);
369
+		}
370
+
371
+		return $count
372
+			/** @type int */
373
+			? EEM_Message::instance()->count($query_params, null, true)
374
+			/** @type EE_Message[] */
375
+			: EEM_Message::instance()->get_all($query_params);
376
+	}
377
+
378
+
379
+	/**
380
+	 * Generate dropdown filter select input for messengers.
381
+	 *
382
+	 * @return string
383
+	 */
384
+	protected function _get_messengers_dropdown_filter()
385
+	{
386
+		$messenger_options                    = array();
387
+		$active_messages_grouped_by_messenger = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
388
+
389
+		//setup array of messenger options
390
+		foreach ($active_messages_grouped_by_messenger as $active_message) {
391
+			if ($active_message instanceof EE_Message) {
392
+				$messenger_options[$active_message->messenger()] = ucwords($active_message->messenger_label());
393
+			}
394
+		}
395
+		return $this->get_admin_page()->get_messengers_select_input($messenger_options);
396
+	}
397
+
398
+
399
+	/**
400
+	 * Generate dropdown filter select input for message types
401
+	 *
402
+	 * @return string
403
+	 */
404
+	protected function _get_message_types_dropdown_filter()
405
+	{
406
+		$message_type_options                    = array();
407
+		$active_messages_grouped_by_message_type = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
408
+
409
+		//setup array of message type options
410
+		foreach ($active_messages_grouped_by_message_type as $active_message) {
411
+			if ($active_message instanceof EE_Message) {
412
+				$message_type_options[$active_message->message_type()] = ucwords($active_message->message_type_label());
413
+			}
414
+		}
415
+		return $this->get_admin_page()->get_message_types_select_input($message_type_options);
416
+	}
417
+
418
+
419
+	/**
420
+	 * Generate dropdown filter select input for message type contexts
421
+	 *
422
+	 * @return string
423
+	 */
424
+	protected function _get_contexts_for_message_types_dropdown_filter()
425
+	{
426
+		$context_options                    = array();
427
+		$active_messages_grouped_by_context = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
428
+
429
+		//setup array of context options
430
+		foreach ($active_messages_grouped_by_context as $active_message) {
431
+			if ($active_message instanceof EE_Message) {
432
+				$message_type = $active_message->message_type_object();
433
+				if ($message_type instanceof EE_message_type) {
434
+					foreach ($message_type->get_contexts() as $context => $context_details) {
435
+						if (isset($context_details['label'])) {
436
+							$context_options[$context] = $context_details['label'];
437
+						}
438
+					}
439
+				}
440
+			}
441
+		}
442
+		return $this->get_admin_page()->get_contexts_for_message_types_select_input($context_options);
443
+	}
444 444
 } //end EE_Message_List_Table class
445 445
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-if (! defined('EVENT_ESPRESSO_VERSION')) {
2
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
3 3
     exit('NO direct script access allowed');
4 4
 }
5 5
 
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
     {
82 82
         $class = parent::_get_row_class($item);
83 83
         //add status class
84
-        $class .= ' ee-status-strip msg-status-' . $item->STS_ID();
84
+        $class .= ' ee-status-strip msg-status-'.$item->STS_ID();
85 85
         if ($this->_has_checkbox_column) {
86 86
             $class .= ' has-checkbox-column';
87 87
         }
@@ -168,8 +168,8 @@  discard block
 block discarded – undo
168 168
                 ),
169 169
                 admin_url('admin.php')
170 170
             )
171
-                             . '">' . __('Delete', 'event_espresso') . '</a>';
172
-        return esc_html($message->to()) . $this->row_actions($actions);
171
+                             . '">'.__('Delete', 'event_espresso').'</a>';
172
+        return esc_html($message->to()).$this->row_actions($actions);
173 173
     }
174 174
 
175 175
 
@@ -238,26 +238,26 @@  discard block
 block discarded – undo
238 238
             'queue_for_resending' => EEH_MSG_Template::get_message_action_link('queue_for_resending', $message),
239 239
             'view_transaction'    => EEH_MSG_Template::get_message_action_link('view_transaction', $message),
240 240
         );
241
-        $content      = '';
241
+        $content = '';
242 242
         switch ($message->STS_ID()) {
243 243
             case EEM_Message::status_sent :
244
-                $content = $action_links['view'] . $action_links['queue_for_resending'] . $action_links['view_transaction'];
244
+                $content = $action_links['view'].$action_links['queue_for_resending'].$action_links['view_transaction'];
245 245
                 break;
246 246
             case EEM_Message::status_resend :
247
-                $content = $action_links['view'] . $action_links['send_now'] . $action_links['view_transaction'];
247
+                $content = $action_links['view'].$action_links['send_now'].$action_links['view_transaction'];
248 248
                 break;
249 249
             case EEM_Message::status_retry :
250
-                $content = $action_links['view'] . $action_links['send_now'] . $action_links['error'] . $action_links['view_transaction'];
250
+                $content = $action_links['view'].$action_links['send_now'].$action_links['error'].$action_links['view_transaction'];
251 251
                 break;
252 252
             case EEM_Message::status_failed :
253 253
             case EEM_Message::status_debug_only :
254
-                $content = $action_links['error'] . $action_links['view_transaction'];
254
+                $content = $action_links['error'].$action_links['view_transaction'];
255 255
                 break;
256 256
             case EEM_Message::status_idle :
257
-                $content = $action_links['view'] . $action_links['send_now'] . $action_links['view_transaction'];
257
+                $content = $action_links['view'].$action_links['send_now'].$action_links['view_transaction'];
258 258
                 break;
259 259
             case EEM_Message::status_incomplete;
260
-                $content = $action_links['generate_now'] . $action_links['view_transaction'];
260
+                $content = $action_links['generate_now'].$action_links['view_transaction'];
261 261
                 break;
262 262
         }
263 263
         return $content;
@@ -310,7 +310,7 @@  discard block
 block discarded – undo
310 310
             );
311 311
         }
312 312
 
313
-        if (! $all && ! empty($this->_req_data['status']) && $this->_req_data['status'] !== 'all') {
313
+        if ( ! $all && ! empty($this->_req_data['status']) && $this->_req_data['status'] !== 'all') {
314 314
             $query_params[0]['AND*view_conditional'] = $this->_req_data === EEM_Message::status_failed
315 315
                 ? array(
316 316
                     'STS_ID' => array(
@@ -318,11 +318,11 @@  discard block
 block discarded – undo
318 318
                         array(EEM_Message::status_failed, EEM_Message::status_messenger_executing)
319 319
                     )
320 320
                 )
321
-                : array( 'STS_ID' => strtoupper($this->_req_data['status']) );
321
+                : array('STS_ID' => strtoupper($this->_req_data['status']));
322 322
         }
323 323
 
324
-        if (! $all && ! empty($this->_req_data['s'])) {
325
-            $search_string         = '%' . $this->_req_data['s'] . '%';
324
+        if ( ! $all && ! empty($this->_req_data['s'])) {
325
+            $search_string         = '%'.$this->_req_data['s'].'%';
326 326
             $query_params[0]['OR'] = array(
327 327
                 'MSG_to'      => array('LIKE', $search_string),
328 328
                 'MSG_from'    => array('LIKE', $search_string),
@@ -335,14 +335,14 @@  discard block
 block discarded – undo
335 335
         //the messages system is in debug mode.
336 336
         //Note: for backward compat with previous iterations, this is necessary because there may be EEM_Message::status_debug_only
337 337
         //messages in the database.
338
-        if (! EEM_Message::debug()) {
338
+        if ( ! EEM_Message::debug()) {
339 339
             $query_params[0]['AND*debug_only_conditional'] = array(
340 340
                 'STS_ID' => array('!=', EEM_Message::status_debug_only),
341 341
             );
342 342
         }
343 343
 
344 344
         //account for filters
345
-        if (! $all
345
+        if ( ! $all
346 346
             && isset($this->_req_data['ee_messenger_filter_by'])
347 347
             && $this->_req_data['ee_messenger_filter_by'] !== 'none_selected'
348 348
         ) {
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
                 'MSG_messenger' => $this->_req_data['ee_messenger_filter_by'],
351 351
             );
352 352
         }
353
-        if (! $all
353
+        if ( ! $all
354 354
             && ! empty($this->_req_data['ee_message_type_filter_by'])
355 355
             && $this->_req_data['ee_message_type_filter_by'] !== 'none_selected'
356 356
         ) {
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
             );
360 360
         }
361 361
 
362
-        if (! $all
362
+        if ( ! $all
363 363
             && ! empty($this->_req_data['ee_context_filter_by'])
364 364
             && $this->_req_data['ee_context_filter_by'] !== 'none_selected'
365 365
         ) {
Please login to merge, or discard this patch.
core/db_models/EEM_Message.model.php 1 patch
Indentation   +472 added lines, -472 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
 /**
@@ -12,481 +12,481 @@  discard block
 block discarded – undo
12 12
 class EEM_Message extends EEM_Base implements EEI_Query_Filter
13 13
 {
14 14
 
15
-    // private instance of the Message object
16
-    protected static $_instance = null;
15
+	// private instance of the Message object
16
+	protected static $_instance = null;
17 17
 
18 18
 
19
-    /**
20
-     * This priority indicates a message should be generated and sent ASAP
21
-     *
22
-     * @type int
23
-     */
24
-    const priority_high = 10;
19
+	/**
20
+	 * This priority indicates a message should be generated and sent ASAP
21
+	 *
22
+	 * @type int
23
+	 */
24
+	const priority_high = 10;
25 25
 
26 26
 
27
-    /**
28
-     * This priority indicates a message should be generated ASAP and queued for sending.
29
-     *
30
-     * @type
31
-     */
32
-    const priority_medium = 20;
33
-
34
-
35
-    /**
36
-     * This priority indicates a message should be queued for generating.
37
-     *
38
-     * @type int
39
-     */
40
-    const priority_low = 30;
41
-
42
-
43
-    /**
44
-     * indicates this message was sent at the time modified
45
-     */
46
-    const status_sent = 'MSN';
47
-
48
-
49
-    /**
50
-     * indicates this message is waiting to be sent
51
-     */
52
-    const status_idle = 'MID';
53
-
54
-
55
-    /**
56
-     * indicates an attempt was a made to send this message
57
-     * at the scheduled time, but it failed at the time modified.  This differs from MDO status in that it will ALWAYS
58
-     * appear to the end user.
59
-     */
60
-    const status_failed = 'MFL';
61
-
62
-
63
-    /**
64
-     * indicates the message has been flagged for resending (at the time modified).
65
-     */
66
-    const status_resend = 'MRS';
67
-
68
-
69
-    /**
70
-     * indicates the message has been flagged for generation but has not been generated yet.  Messages always start as
71
-     * this status when added to the queue.
72
-     */
73
-    const status_incomplete = 'MIC';
74
-
75
-
76
-    /**
77
-     * Indicates everything was generated fine for the message, however, the messenger was unable to send.
78
-     * This status means that its possible to retry sending the message.
79
-     */
80
-    const status_retry = 'MRT';
81
-
82
-
83
-    /**
84
-     * This is used for more informational messages that may not indicate anything is broken but still cannot be
85
-     * generated or sent correctly. An example of a message that would get flagged this way would be when a not
86
-     * approved message was queued for generation, but at time of generation, the attached registration(s) are
87
-     * approved. So the message queued for generation is no longer valid.  Messages for this status will only persist
88
-     * in the db and be viewable in the message activity list table when the messages system is in debug mode.
89
-     *
90
-     * @see EEM_Message::debug()
91
-     */
92
-    const status_debug_only = 'MDO';
93
-
94
-
95
-    /**
96
-     * This status is given to messages it is processed by the messenger send method.
97
-     * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually
98
-     * indicative of a PHP timeout or memory limit issue.
99
-     */
100
-    const status_messenger_executing = 'MEX';
101
-
102
-
103
-    /**
104
-     *    Private constructor to prevent direct creation.
105
-     *
106
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and
107
-     *                         any incoming timezone data that gets saved).  Note this just sends the timezone info to
108
-     *                         the date time model field objects.  Default is null (and will be assumed using the set
109
-     *                         timezone in the 'timezone_string' wp option)
110
-     * @return EEM_Message
111
-     */
112
-    protected function __construct($timezone = null)
113
-    {
114
-        $this->singular_item = __('Message', 'event_espresso');
115
-        $this->plural_item   = __('Messages', 'event_espresso');
116
-
117
-        //used for token generator
118
-        EE_Registry::instance()->load_helper('URL');
119
-
120
-        $this->_tables = array(
121
-            'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'),
122
-        );
123
-
124
-        $allowed_priority = array(
125
-            self::priority_high   => __('high', 'event_espresso'),
126
-            self::priority_medium => __('medium', 'event_espresso'),
127
-            self::priority_low    => __('low', 'event_espresso'),
128
-        );
129
-
130
-        $this->_fields          = array(
131
-            'Message' => array(
132
-                'MSG_ID'             => new EE_Primary_Key_Int_Field('MSG_ID', __('Message ID', 'event_espresso')),
133
-                'MSG_token'          => new EE_Plain_Text_Field('MSG_token',
134
-                    __('Unique Token used to represent this row in publicly viewable contexts (eg. a url).',
135
-                        'event_espresso'), false, EEH_URL::generate_unique_token()),
136
-                'GRP_ID'             => new EE_Foreign_Key_Int_Field('GRP_ID',
137
-                    __('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'), true, 0,
138
-                    'Message_Template_Group'),
139
-                'TXN_ID'             => new EE_Foreign_Key_Int_Field('TXN_ID',
140
-                    __('Foreign key to the related EE_Transaction.  This is required to give context for regenerating the specific message',
141
-                        'event_espresso'), true, 0, 'Transaction'),
142
-                'MSG_messenger'      => new EE_Plain_Text_Field('MSG_messenger',
143
-                    __('Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.',
144
-                        'event_espresso'), false, 'email'),
145
-                'MSG_message_type'   => new EE_Plain_Text_Field('MSG_message_type',
146
-                    __('Corresponds to the EE_message_type::name used to generate this message.', 'event_espresso'),
147
-                    false, 'receipt'),
148
-                'MSG_context'        => new EE_Plain_Text_Field('MSG_context', __('Context', 'event_espresso'), false),
149
-                'MSG_recipient_ID'   => new EE_Foreign_Key_Int_Field('MSG_recipient_ID',
150
-                    __('Recipient ID', 'event_espresso'), true, null, array('Registration', 'Attendee', 'WP_User')),
151
-                'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field('MSG_recipient_type',
152
-                    __('Recipient Type', 'event_espresso'), true, null, array('Registration', 'Attendee', 'WP_User')),
153
-                'MSG_content'        => new EE_Maybe_Serialized_Text_Field('MSG_content',
154
-                    __('Content', 'event_espresso'), true, ''),
155
-                'MSG_to'             => new EE_Maybe_Serialized_Text_Field('MSG_to', __('Address To', 'event_espresso'),
156
-                    true),
157
-                'MSG_from'           => new EE_Maybe_Serialized_Text_Field('MSG_from',
158
-                    __('Address From', 'event_espresso'), true),
159
-                'MSG_subject'        => new EE_Maybe_Serialized_Text_Field('MSG_subject',
160
-                    __('Subject', 'event_espresso'), true, ''),
161
-                'MSG_priority'       => new EE_Enum_Integer_Field('MSG_priority', __('Priority', 'event_espresso'),
162
-                    false, self::priority_low, $allowed_priority),
163
-                'STS_ID'             => new EE_Foreign_Key_String_Field('STS_ID', __('Status', 'event_espresso'), false,
164
-                    self::status_incomplete, 'Status'),
165
-                'MSG_created'        => new EE_Datetime_Field('MSG_created', __('Created', 'event_espresso'), false,
166
-                    EE_Datetime_Field::now),
167
-                'MSG_modified'       => new EE_Datetime_Field('MSG_modified', __('Modified', 'event_espresso'), true,
168
-                    EE_Datetime_Field::now),
169
-            ),
170
-        );
171
-        $this->_model_relations = array(
172
-            'Attendee'               => new EE_Belongs_To_Any_Relation(),
173
-            'Registration'           => new EE_Belongs_To_Any_Relation(),
174
-            'WP_User'                => new EE_Belongs_To_Any_Relation(),
175
-            'Message_Template_Group' => new EE_Belongs_To_Relation(),
176
-            'Transaction'            => new EE_Belongs_To_Relation(),
177
-        );
178
-        parent::__construct($timezone);
179
-    }
180
-
181
-
182
-    /**
183
-     * @return \EE_Message
184
-     */
185
-    public function create_default_object()
186
-    {
187
-        /** @type EE_Message $message */
188
-        $message = parent::create_default_object();
189
-        if ($message instanceof EE_Message) {
190
-            return EE_Message_Factory::set_messenger_and_message_type($message);
191
-        }
192
-        return null;
193
-    }
194
-
195
-
196
-    /**
197
-     * @param mixed $cols_n_values
198
-     * @return \EE_Message
199
-     */
200
-    public function instantiate_class_from_array_or_object($cols_n_values)
201
-    {
202
-        /** @type EE_Message $message */
203
-        $message = parent::instantiate_class_from_array_or_object($cols_n_values);
204
-        if ($message instanceof EE_Message) {
205
-            return EE_Message_Factory::set_messenger_and_message_type($message);
206
-        }
207
-        return null;
208
-    }
209
-
210
-
211
-    /**
212
-     * Returns whether or not a message of that type was sent for a given attendee.
213
-     *
214
-     * @param EE_Attendee|int $attendee
215
-     * @param string          $message_type the message type slug
216
-     * @return boolean
217
-     */
218
-    public function message_sent_for_attendee($attendee, $message_type)
219
-    {
220
-        $attendee_ID = EEM_Attendee::instance()->ensure_is_ID($attendee);
221
-        return $this->exists(array(
222
-            array(
223
-                'Attendee.ATT_ID'  => $attendee_ID,
224
-                'MSG_message_type' => $message_type,
225
-                'STS_ID'           => array('IN', $this->stati_indicating_sent()),
226
-            ),
227
-        ));
228
-    }
229
-
230
-
231
-    /**
232
-     * Returns whether or not a message of that type was sent for a given registration
233
-     *
234
-     * @param EE_Registration|int $registration
235
-     * @param string              $message_type the message type slug
236
-     * @return boolean
237
-     */
238
-    public function message_sent_for_registration($registration, $message_type)
239
-    {
240
-        $registrationID = EEM_Registration::instance()->ensure_is_ID($registration);
241
-        return $this->exists(array(
242
-            array(
243
-                'Registration.REG_ID' => $registrationID,
244
-                'MSG_message_type'    => $message_type,
245
-                'STS_ID'              => array('IN', $this->stati_indicating_sent()),
246
-            ),
247
-        ));
248
-    }
249
-
250
-
251
-    /**
252
-     * This retrieves an EE_Message object from the db matching the given token string.
253
-     *
254
-     * @param string $token
255
-     * @return EE_Message
256
-     */
257
-    public function get_one_by_token($token)
258
-    {
259
-        return $this->get_one(array(
260
-            array(
261
-                'MSG_token' => $token,
262
-            ),
263
-        ));
264
-    }
265
-
266
-
267
-    /**
268
-     * Returns stati that indicate the message HAS been sent
269
-     *
270
-     * @return array of strings for possible stati
271
-     */
272
-    public function stati_indicating_sent()
273
-    {
274
-        return apply_filters('FHEE__EEM_Message__stati_indicating_sent', array(self::status_sent));
275
-    }
276
-
277
-
278
-    /**
279
-     * Returns stati that indicate the message is waiting to be sent.
280
-     *
281
-     * @return array of strings for possible stati.
282
-     */
283
-    public function stati_indicating_to_send()
284
-    {
285
-        return apply_filters('FHEE__EEM_Message__stati_indicating_to_send',
286
-            array(self::status_idle, self::status_resend));
287
-    }
288
-
289
-
290
-    /**
291
-     * Returns stati that indicate the message has failed sending
292
-     *
293
-     * @return array  array of strings for possible stati.
294
-     */
295
-    public function stati_indicating_failed_sending()
296
-    {
297
-        $failed_stati = array(
298
-            self::status_failed,
299
-            self::status_retry,
300
-            self::status_messenger_executing,
301
-        );
302
-        //if WP_DEBUG is set, then let's include debug_only fails
303
-        if (WP_DEBUG) {
304
-            $failed_stati[] = self::status_debug_only;
305
-        }
306
-        return apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati);
307
-    }
308
-
309
-
310
-    /**
311
-     * Returns filterable array of all EEM_Message statuses.
312
-     *
313
-     * @return array
314
-     */
315
-    public function all_statuses()
316
-    {
317
-        return apply_filters(
318
-            'FHEE__EEM_Message__all_statuses',
319
-            array(
320
-                EEM_Message::status_sent,
321
-                EEM_Message::status_incomplete,
322
-                EEM_Message::status_idle,
323
-                EEM_Message::status_resend,
324
-                EEM_Message::status_retry,
325
-                EEM_Message::status_failed,
326
-                EEM_Message::status_messenger_executing,
327
-                EEM_Message::status_debug_only,
328
-            )
329
-        );
330
-    }
331
-
332
-    /**
333
-     * Detects any specific query variables in the request and uses those to setup appropriate
334
-     * filter for any queries.
335
-     *
336
-     * @return array
337
-     */
338
-    public function filter_by_query_params()
339
-    {
340
-        // expected possible query_vars, the key in this array matches an expected key in the request,
341
-        // the value, matches the corresponding EEM_Base child reference.
342
-        $expected_vars   = $this->_expected_vars_for_query_inject();
343
-        $query_params[0] = array();
344
-        foreach ($expected_vars as $request_key => $model_name) {
345
-            $request_value = EE_Registry::instance()->REQ->get($request_key);
346
-            if ($request_value) {
347
-                //special case
348
-                switch ($request_key) {
349
-                    case '_REG_ID' :
350
-                        $query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = array(
351
-                            'Transaction.Registration.REG_ID' => $request_value,
352
-                        );
353
-                        break;
354
-                    case 'EVT_ID' :
355
-                        $query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = array(
356
-                            'Transaction.Registration.EVT_ID' => $request_value,
357
-                        );
358
-                        break;
359
-                    default :
360
-                        $query_params[0]['AND**filter_by']['OR**filter_by_' . $request_key][$model_name . '.' . $request_key] = $request_value;
361
-                        break;
362
-                }
363
-            }
364
-        }
365
-        return $query_params;
366
-    }
367
-
368
-
369
-    /**
370
-     * @return string
371
-     */
372
-    public function get_pretty_label_for_results()
373
-    {
374
-        $expected_vars = $this->_expected_vars_for_query_inject();
375
-        $pretty_label  = '';
376
-        $label_parts   = array();
377
-        foreach ($expected_vars as $request_key => $model_name) {
378
-            $model = EE_Registry::instance()->load_model($model_name);
379
-            if ($model_field_value = EE_Registry::instance()->REQ->get($request_key)) {
380
-                switch ($request_key) {
381
-                    case '_REG_ID' :
382
-                        $label_parts[] = sprintf(
383
-                            esc_html__('Registration with the ID: %s', 'event_espresso'),
384
-                            $model_field_value
385
-                        );
386
-                        break;
387
-                    case 'ATT_ID' :
388
-                        /** @var EE_Attendee $attendee */
389
-                        $attendee      = $model->get_one_by_ID($model_field_value);
390
-                        $label_parts[] = $attendee instanceof EE_Attendee
391
-                            ? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name())
392
-                            : sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value);
393
-                        break;
394
-                    case 'ID' :
395
-                        /** @var EE_WP_User $wpUser */
396
-                        $wpUser        = $model->get_one_by_ID($model_field_value);
397
-                        $label_parts[] = $wpUser instanceof EE_WP_User
398
-                            ? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name())
399
-                            : sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value);
400
-                        break;
401
-                    case 'TXN_ID' :
402
-                        $label_parts[] = sprintf(
403
-                            esc_html__('Transaction with the ID: %s', 'event_espresso'),
404
-                            $model_field_value
405
-                        );
406
-                        break;
407
-                    case 'EVT_ID' :
408
-                        /** @var EE_Event $Event */
409
-                        $Event         = $model->get_one_by_ID($model_field_value);
410
-                        $label_parts[] = $Event instanceof EE_Event
411
-                            ? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name())
412
-                            : sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value);
413
-                        break;
414
-                }
415
-            }
416
-        }
417
-
418
-        if ($label_parts) {
419
-
420
-            //prepend to the last element of $label_parts an "and".
421
-            if (count($label_parts) > 1) {
422
-                $label_parts_index_to_prepend               = count($label_parts) - 1;
423
-                $label_parts[$label_parts_index_to_prepend] = 'and' . $label_parts[$label_parts_index_to_prepend];
424
-            }
425
-
426
-            $pretty_label .= sprintf(
427
-                esc_html_x(
428
-                    'Showing messages for %s',
429
-                    'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.',
430
-                    'event_espresso'
431
-                ),
432
-                implode(', ', $label_parts)
433
-            );
434
-        }
435
-        return $pretty_label;
436
-    }
437
-
438
-
439
-    /**
440
-     * This returns the array of expected variables for the EEI_Query_Filter methods being implemented
441
-     * The array is in the format:
442
-     * array(
443
-     *  {$field_name} => {$model_name}
444
-     * );
445
-     *
446
-     * @since 4.9.0
447
-     * @return array
448
-     */
449
-    protected function _expected_vars_for_query_inject()
450
-    {
451
-        return array(
452
-            '_REG_ID' => 'Registration',
453
-            'ATT_ID'  => 'Attendee',
454
-            'ID'      => 'WP_User',
455
-            'TXN_ID'  => 'Transaction',
456
-            'EVT_ID'  => 'Event',
457
-        );
458
-    }
459
-
460
-
461
-    /**
462
-     * This returns whether EEM_Message is in debug mode or not.
463
-     * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when
464
-     * generating/sending messages. Debug mode can be set by either:
465
-     * 1. Sending in a value for the $set_debug argument
466
-     * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php
467
-     * 3. Overriding the above via the provided filter.
468
-     *
469
-     * @param bool|null $set_debug      If provided, then the debug mode will be set internally until reset via the
470
-     *                                  provided boolean. When no argument is provided (default null) then the debug
471
-     *                                  mode will be returned.
472
-     * @return bool         true means Messages is in debug mode.  false means messages system is not in debug mode.
473
-     */
474
-    public static function debug($set_debug = null)
475
-    {
476
-        static $is_debugging = null;
477
-
478
-        //initialize (use constant if set).
479
-        if (is_null($set_debug) && is_null($is_debugging)) {
480
-            $is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES;
481
-        }
482
-
483
-        if ( ! is_null($set_debug)) {
484
-            $is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN);
485
-        }
486
-
487
-        //return filtered value
488
-        return apply_filters('FHEE__EEM_Message__debug', $is_debugging);
489
-    }
27
+	/**
28
+	 * This priority indicates a message should be generated ASAP and queued for sending.
29
+	 *
30
+	 * @type
31
+	 */
32
+	const priority_medium = 20;
33
+
34
+
35
+	/**
36
+	 * This priority indicates a message should be queued for generating.
37
+	 *
38
+	 * @type int
39
+	 */
40
+	const priority_low = 30;
41
+
42
+
43
+	/**
44
+	 * indicates this message was sent at the time modified
45
+	 */
46
+	const status_sent = 'MSN';
47
+
48
+
49
+	/**
50
+	 * indicates this message is waiting to be sent
51
+	 */
52
+	const status_idle = 'MID';
53
+
54
+
55
+	/**
56
+	 * indicates an attempt was a made to send this message
57
+	 * at the scheduled time, but it failed at the time modified.  This differs from MDO status in that it will ALWAYS
58
+	 * appear to the end user.
59
+	 */
60
+	const status_failed = 'MFL';
61
+
62
+
63
+	/**
64
+	 * indicates the message has been flagged for resending (at the time modified).
65
+	 */
66
+	const status_resend = 'MRS';
67
+
68
+
69
+	/**
70
+	 * indicates the message has been flagged for generation but has not been generated yet.  Messages always start as
71
+	 * this status when added to the queue.
72
+	 */
73
+	const status_incomplete = 'MIC';
74
+
75
+
76
+	/**
77
+	 * Indicates everything was generated fine for the message, however, the messenger was unable to send.
78
+	 * This status means that its possible to retry sending the message.
79
+	 */
80
+	const status_retry = 'MRT';
81
+
82
+
83
+	/**
84
+	 * This is used for more informational messages that may not indicate anything is broken but still cannot be
85
+	 * generated or sent correctly. An example of a message that would get flagged this way would be when a not
86
+	 * approved message was queued for generation, but at time of generation, the attached registration(s) are
87
+	 * approved. So the message queued for generation is no longer valid.  Messages for this status will only persist
88
+	 * in the db and be viewable in the message activity list table when the messages system is in debug mode.
89
+	 *
90
+	 * @see EEM_Message::debug()
91
+	 */
92
+	const status_debug_only = 'MDO';
93
+
94
+
95
+	/**
96
+	 * This status is given to messages it is processed by the messenger send method.
97
+	 * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually
98
+	 * indicative of a PHP timeout or memory limit issue.
99
+	 */
100
+	const status_messenger_executing = 'MEX';
101
+
102
+
103
+	/**
104
+	 *    Private constructor to prevent direct creation.
105
+	 *
106
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and
107
+	 *                         any incoming timezone data that gets saved).  Note this just sends the timezone info to
108
+	 *                         the date time model field objects.  Default is null (and will be assumed using the set
109
+	 *                         timezone in the 'timezone_string' wp option)
110
+	 * @return EEM_Message
111
+	 */
112
+	protected function __construct($timezone = null)
113
+	{
114
+		$this->singular_item = __('Message', 'event_espresso');
115
+		$this->plural_item   = __('Messages', 'event_espresso');
116
+
117
+		//used for token generator
118
+		EE_Registry::instance()->load_helper('URL');
119
+
120
+		$this->_tables = array(
121
+			'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'),
122
+		);
123
+
124
+		$allowed_priority = array(
125
+			self::priority_high   => __('high', 'event_espresso'),
126
+			self::priority_medium => __('medium', 'event_espresso'),
127
+			self::priority_low    => __('low', 'event_espresso'),
128
+		);
129
+
130
+		$this->_fields          = array(
131
+			'Message' => array(
132
+				'MSG_ID'             => new EE_Primary_Key_Int_Field('MSG_ID', __('Message ID', 'event_espresso')),
133
+				'MSG_token'          => new EE_Plain_Text_Field('MSG_token',
134
+					__('Unique Token used to represent this row in publicly viewable contexts (eg. a url).',
135
+						'event_espresso'), false, EEH_URL::generate_unique_token()),
136
+				'GRP_ID'             => new EE_Foreign_Key_Int_Field('GRP_ID',
137
+					__('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'), true, 0,
138
+					'Message_Template_Group'),
139
+				'TXN_ID'             => new EE_Foreign_Key_Int_Field('TXN_ID',
140
+					__('Foreign key to the related EE_Transaction.  This is required to give context for regenerating the specific message',
141
+						'event_espresso'), true, 0, 'Transaction'),
142
+				'MSG_messenger'      => new EE_Plain_Text_Field('MSG_messenger',
143
+					__('Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.',
144
+						'event_espresso'), false, 'email'),
145
+				'MSG_message_type'   => new EE_Plain_Text_Field('MSG_message_type',
146
+					__('Corresponds to the EE_message_type::name used to generate this message.', 'event_espresso'),
147
+					false, 'receipt'),
148
+				'MSG_context'        => new EE_Plain_Text_Field('MSG_context', __('Context', 'event_espresso'), false),
149
+				'MSG_recipient_ID'   => new EE_Foreign_Key_Int_Field('MSG_recipient_ID',
150
+					__('Recipient ID', 'event_espresso'), true, null, array('Registration', 'Attendee', 'WP_User')),
151
+				'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field('MSG_recipient_type',
152
+					__('Recipient Type', 'event_espresso'), true, null, array('Registration', 'Attendee', 'WP_User')),
153
+				'MSG_content'        => new EE_Maybe_Serialized_Text_Field('MSG_content',
154
+					__('Content', 'event_espresso'), true, ''),
155
+				'MSG_to'             => new EE_Maybe_Serialized_Text_Field('MSG_to', __('Address To', 'event_espresso'),
156
+					true),
157
+				'MSG_from'           => new EE_Maybe_Serialized_Text_Field('MSG_from',
158
+					__('Address From', 'event_espresso'), true),
159
+				'MSG_subject'        => new EE_Maybe_Serialized_Text_Field('MSG_subject',
160
+					__('Subject', 'event_espresso'), true, ''),
161
+				'MSG_priority'       => new EE_Enum_Integer_Field('MSG_priority', __('Priority', 'event_espresso'),
162
+					false, self::priority_low, $allowed_priority),
163
+				'STS_ID'             => new EE_Foreign_Key_String_Field('STS_ID', __('Status', 'event_espresso'), false,
164
+					self::status_incomplete, 'Status'),
165
+				'MSG_created'        => new EE_Datetime_Field('MSG_created', __('Created', 'event_espresso'), false,
166
+					EE_Datetime_Field::now),
167
+				'MSG_modified'       => new EE_Datetime_Field('MSG_modified', __('Modified', 'event_espresso'), true,
168
+					EE_Datetime_Field::now),
169
+			),
170
+		);
171
+		$this->_model_relations = array(
172
+			'Attendee'               => new EE_Belongs_To_Any_Relation(),
173
+			'Registration'           => new EE_Belongs_To_Any_Relation(),
174
+			'WP_User'                => new EE_Belongs_To_Any_Relation(),
175
+			'Message_Template_Group' => new EE_Belongs_To_Relation(),
176
+			'Transaction'            => new EE_Belongs_To_Relation(),
177
+		);
178
+		parent::__construct($timezone);
179
+	}
180
+
181
+
182
+	/**
183
+	 * @return \EE_Message
184
+	 */
185
+	public function create_default_object()
186
+	{
187
+		/** @type EE_Message $message */
188
+		$message = parent::create_default_object();
189
+		if ($message instanceof EE_Message) {
190
+			return EE_Message_Factory::set_messenger_and_message_type($message);
191
+		}
192
+		return null;
193
+	}
194
+
195
+
196
+	/**
197
+	 * @param mixed $cols_n_values
198
+	 * @return \EE_Message
199
+	 */
200
+	public function instantiate_class_from_array_or_object($cols_n_values)
201
+	{
202
+		/** @type EE_Message $message */
203
+		$message = parent::instantiate_class_from_array_or_object($cols_n_values);
204
+		if ($message instanceof EE_Message) {
205
+			return EE_Message_Factory::set_messenger_and_message_type($message);
206
+		}
207
+		return null;
208
+	}
209
+
210
+
211
+	/**
212
+	 * Returns whether or not a message of that type was sent for a given attendee.
213
+	 *
214
+	 * @param EE_Attendee|int $attendee
215
+	 * @param string          $message_type the message type slug
216
+	 * @return boolean
217
+	 */
218
+	public function message_sent_for_attendee($attendee, $message_type)
219
+	{
220
+		$attendee_ID = EEM_Attendee::instance()->ensure_is_ID($attendee);
221
+		return $this->exists(array(
222
+			array(
223
+				'Attendee.ATT_ID'  => $attendee_ID,
224
+				'MSG_message_type' => $message_type,
225
+				'STS_ID'           => array('IN', $this->stati_indicating_sent()),
226
+			),
227
+		));
228
+	}
229
+
230
+
231
+	/**
232
+	 * Returns whether or not a message of that type was sent for a given registration
233
+	 *
234
+	 * @param EE_Registration|int $registration
235
+	 * @param string              $message_type the message type slug
236
+	 * @return boolean
237
+	 */
238
+	public function message_sent_for_registration($registration, $message_type)
239
+	{
240
+		$registrationID = EEM_Registration::instance()->ensure_is_ID($registration);
241
+		return $this->exists(array(
242
+			array(
243
+				'Registration.REG_ID' => $registrationID,
244
+				'MSG_message_type'    => $message_type,
245
+				'STS_ID'              => array('IN', $this->stati_indicating_sent()),
246
+			),
247
+		));
248
+	}
249
+
250
+
251
+	/**
252
+	 * This retrieves an EE_Message object from the db matching the given token string.
253
+	 *
254
+	 * @param string $token
255
+	 * @return EE_Message
256
+	 */
257
+	public function get_one_by_token($token)
258
+	{
259
+		return $this->get_one(array(
260
+			array(
261
+				'MSG_token' => $token,
262
+			),
263
+		));
264
+	}
265
+
266
+
267
+	/**
268
+	 * Returns stati that indicate the message HAS been sent
269
+	 *
270
+	 * @return array of strings for possible stati
271
+	 */
272
+	public function stati_indicating_sent()
273
+	{
274
+		return apply_filters('FHEE__EEM_Message__stati_indicating_sent', array(self::status_sent));
275
+	}
276
+
277
+
278
+	/**
279
+	 * Returns stati that indicate the message is waiting to be sent.
280
+	 *
281
+	 * @return array of strings for possible stati.
282
+	 */
283
+	public function stati_indicating_to_send()
284
+	{
285
+		return apply_filters('FHEE__EEM_Message__stati_indicating_to_send',
286
+			array(self::status_idle, self::status_resend));
287
+	}
288
+
289
+
290
+	/**
291
+	 * Returns stati that indicate the message has failed sending
292
+	 *
293
+	 * @return array  array of strings for possible stati.
294
+	 */
295
+	public function stati_indicating_failed_sending()
296
+	{
297
+		$failed_stati = array(
298
+			self::status_failed,
299
+			self::status_retry,
300
+			self::status_messenger_executing,
301
+		);
302
+		//if WP_DEBUG is set, then let's include debug_only fails
303
+		if (WP_DEBUG) {
304
+			$failed_stati[] = self::status_debug_only;
305
+		}
306
+		return apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati);
307
+	}
308
+
309
+
310
+	/**
311
+	 * Returns filterable array of all EEM_Message statuses.
312
+	 *
313
+	 * @return array
314
+	 */
315
+	public function all_statuses()
316
+	{
317
+		return apply_filters(
318
+			'FHEE__EEM_Message__all_statuses',
319
+			array(
320
+				EEM_Message::status_sent,
321
+				EEM_Message::status_incomplete,
322
+				EEM_Message::status_idle,
323
+				EEM_Message::status_resend,
324
+				EEM_Message::status_retry,
325
+				EEM_Message::status_failed,
326
+				EEM_Message::status_messenger_executing,
327
+				EEM_Message::status_debug_only,
328
+			)
329
+		);
330
+	}
331
+
332
+	/**
333
+	 * Detects any specific query variables in the request and uses those to setup appropriate
334
+	 * filter for any queries.
335
+	 *
336
+	 * @return array
337
+	 */
338
+	public function filter_by_query_params()
339
+	{
340
+		// expected possible query_vars, the key in this array matches an expected key in the request,
341
+		// the value, matches the corresponding EEM_Base child reference.
342
+		$expected_vars   = $this->_expected_vars_for_query_inject();
343
+		$query_params[0] = array();
344
+		foreach ($expected_vars as $request_key => $model_name) {
345
+			$request_value = EE_Registry::instance()->REQ->get($request_key);
346
+			if ($request_value) {
347
+				//special case
348
+				switch ($request_key) {
349
+					case '_REG_ID' :
350
+						$query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = array(
351
+							'Transaction.Registration.REG_ID' => $request_value,
352
+						);
353
+						break;
354
+					case 'EVT_ID' :
355
+						$query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = array(
356
+							'Transaction.Registration.EVT_ID' => $request_value,
357
+						);
358
+						break;
359
+					default :
360
+						$query_params[0]['AND**filter_by']['OR**filter_by_' . $request_key][$model_name . '.' . $request_key] = $request_value;
361
+						break;
362
+				}
363
+			}
364
+		}
365
+		return $query_params;
366
+	}
367
+
368
+
369
+	/**
370
+	 * @return string
371
+	 */
372
+	public function get_pretty_label_for_results()
373
+	{
374
+		$expected_vars = $this->_expected_vars_for_query_inject();
375
+		$pretty_label  = '';
376
+		$label_parts   = array();
377
+		foreach ($expected_vars as $request_key => $model_name) {
378
+			$model = EE_Registry::instance()->load_model($model_name);
379
+			if ($model_field_value = EE_Registry::instance()->REQ->get($request_key)) {
380
+				switch ($request_key) {
381
+					case '_REG_ID' :
382
+						$label_parts[] = sprintf(
383
+							esc_html__('Registration with the ID: %s', 'event_espresso'),
384
+							$model_field_value
385
+						);
386
+						break;
387
+					case 'ATT_ID' :
388
+						/** @var EE_Attendee $attendee */
389
+						$attendee      = $model->get_one_by_ID($model_field_value);
390
+						$label_parts[] = $attendee instanceof EE_Attendee
391
+							? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name())
392
+							: sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value);
393
+						break;
394
+					case 'ID' :
395
+						/** @var EE_WP_User $wpUser */
396
+						$wpUser        = $model->get_one_by_ID($model_field_value);
397
+						$label_parts[] = $wpUser instanceof EE_WP_User
398
+							? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name())
399
+							: sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value);
400
+						break;
401
+					case 'TXN_ID' :
402
+						$label_parts[] = sprintf(
403
+							esc_html__('Transaction with the ID: %s', 'event_espresso'),
404
+							$model_field_value
405
+						);
406
+						break;
407
+					case 'EVT_ID' :
408
+						/** @var EE_Event $Event */
409
+						$Event         = $model->get_one_by_ID($model_field_value);
410
+						$label_parts[] = $Event instanceof EE_Event
411
+							? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name())
412
+							: sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value);
413
+						break;
414
+				}
415
+			}
416
+		}
417
+
418
+		if ($label_parts) {
419
+
420
+			//prepend to the last element of $label_parts an "and".
421
+			if (count($label_parts) > 1) {
422
+				$label_parts_index_to_prepend               = count($label_parts) - 1;
423
+				$label_parts[$label_parts_index_to_prepend] = 'and' . $label_parts[$label_parts_index_to_prepend];
424
+			}
425
+
426
+			$pretty_label .= sprintf(
427
+				esc_html_x(
428
+					'Showing messages for %s',
429
+					'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.',
430
+					'event_espresso'
431
+				),
432
+				implode(', ', $label_parts)
433
+			);
434
+		}
435
+		return $pretty_label;
436
+	}
437
+
438
+
439
+	/**
440
+	 * This returns the array of expected variables for the EEI_Query_Filter methods being implemented
441
+	 * The array is in the format:
442
+	 * array(
443
+	 *  {$field_name} => {$model_name}
444
+	 * );
445
+	 *
446
+	 * @since 4.9.0
447
+	 * @return array
448
+	 */
449
+	protected function _expected_vars_for_query_inject()
450
+	{
451
+		return array(
452
+			'_REG_ID' => 'Registration',
453
+			'ATT_ID'  => 'Attendee',
454
+			'ID'      => 'WP_User',
455
+			'TXN_ID'  => 'Transaction',
456
+			'EVT_ID'  => 'Event',
457
+		);
458
+	}
459
+
460
+
461
+	/**
462
+	 * This returns whether EEM_Message is in debug mode or not.
463
+	 * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when
464
+	 * generating/sending messages. Debug mode can be set by either:
465
+	 * 1. Sending in a value for the $set_debug argument
466
+	 * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php
467
+	 * 3. Overriding the above via the provided filter.
468
+	 *
469
+	 * @param bool|null $set_debug      If provided, then the debug mode will be set internally until reset via the
470
+	 *                                  provided boolean. When no argument is provided (default null) then the debug
471
+	 *                                  mode will be returned.
472
+	 * @return bool         true means Messages is in debug mode.  false means messages system is not in debug mode.
473
+	 */
474
+	public static function debug($set_debug = null)
475
+	{
476
+		static $is_debugging = null;
477
+
478
+		//initialize (use constant if set).
479
+		if (is_null($set_debug) && is_null($is_debugging)) {
480
+			$is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES;
481
+		}
482
+
483
+		if ( ! is_null($set_debug)) {
484
+			$is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN);
485
+		}
486
+
487
+		//return filtered value
488
+		return apply_filters('FHEE__EEM_Message__debug', $is_debugging);
489
+	}
490 490
 
491 491
 
492 492
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Status.model.php 1 patch
Indentation   +275 added lines, -275 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
  * Event Espresso
@@ -25,291 +25,291 @@  discard block
 block discarded – undo
25 25
 class EEM_Status extends EEM_Base
26 26
 {
27 27
 
28
-    // private instance of the Attendee object
29
-    protected static $_instance = null;
28
+	// private instance of the Attendee object
29
+	protected static $_instance = null;
30 30
 
31 31
 
32
-    /**
33
-     * @return EEM_Status
34
-     */
35
-    protected function __construct($timezone = null)
36
-    {
37
-        $this->singular_item    = __('Status', 'event_espresso');
38
-        $this->plural_item      = __('Stati', 'event_espresso');
39
-        $this->_tables          = array(
40
-            'StatusTable' => new EE_Primary_Table('esp_status', 'STS_ID'),
41
-        );
42
-        $this->_fields          = array(
43
-            'StatusTable' => array(
44
-                'STS_ID'       => new EE_Primary_Key_String_Field('STS_ID', __('Status ID', 'event_espresso')),
45
-                'STS_code'     => new EE_Plain_Text_Field('STS_code', __('Status Code', 'event_espresso'), false, ''),
46
-                'STS_type'     => new EE_Enum_Text_Field(
47
-                    'STS_type',
48
-                    __("Type", "event_espresso"),
49
-                    false,
50
-                    'event',
51
-                    array(
52
-                        'event'        => __("Event", "event_espresso"),//deprecated
53
-                        'registration' => __("Registration", "event_espresso"),
54
-                        'transaction'  => __("Transaction", "event_espresso"),
55
-                        'payment'      => __("Payment", "event_espresso"),
56
-                        'email'        => __("Email", "event_espresso"),
57
-                        'message'      => __("Message", "event_espresso"),
58
-                    )),
59
-                'STS_can_edit' => new EE_Boolean_Field('STS_can_edit', __('Editable?', 'event_espresso'), false),
60
-                'STS_desc'     => new EE_Simple_HTML_Field('STS_desc', __("Description", "event_espresso"), false, ''),
61
-                'STS_open'     => new EE_Boolean_Field('STS_open', __("Open?", "event_espresso"), false, false),
62
-            ),
63
-        );
64
-        $this->_model_relations = array(
65
-            'Registration' => new EE_Has_Many_Relation(),
66
-            'Transaction'  => new EE_Has_Many_Relation(),
67
-            'Payment'      => new EE_Has_Many_Relation(),
68
-        );
69
-        //this model is generally available for reading
70
-        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
32
+	/**
33
+	 * @return EEM_Status
34
+	 */
35
+	protected function __construct($timezone = null)
36
+	{
37
+		$this->singular_item    = __('Status', 'event_espresso');
38
+		$this->plural_item      = __('Stati', 'event_espresso');
39
+		$this->_tables          = array(
40
+			'StatusTable' => new EE_Primary_Table('esp_status', 'STS_ID'),
41
+		);
42
+		$this->_fields          = array(
43
+			'StatusTable' => array(
44
+				'STS_ID'       => new EE_Primary_Key_String_Field('STS_ID', __('Status ID', 'event_espresso')),
45
+				'STS_code'     => new EE_Plain_Text_Field('STS_code', __('Status Code', 'event_espresso'), false, ''),
46
+				'STS_type'     => new EE_Enum_Text_Field(
47
+					'STS_type',
48
+					__("Type", "event_espresso"),
49
+					false,
50
+					'event',
51
+					array(
52
+						'event'        => __("Event", "event_espresso"),//deprecated
53
+						'registration' => __("Registration", "event_espresso"),
54
+						'transaction'  => __("Transaction", "event_espresso"),
55
+						'payment'      => __("Payment", "event_espresso"),
56
+						'email'        => __("Email", "event_espresso"),
57
+						'message'      => __("Message", "event_espresso"),
58
+					)),
59
+				'STS_can_edit' => new EE_Boolean_Field('STS_can_edit', __('Editable?', 'event_espresso'), false),
60
+				'STS_desc'     => new EE_Simple_HTML_Field('STS_desc', __("Description", "event_espresso"), false, ''),
61
+				'STS_open'     => new EE_Boolean_Field('STS_open', __("Open?", "event_espresso"), false, false),
62
+			),
63
+		);
64
+		$this->_model_relations = array(
65
+			'Registration' => new EE_Has_Many_Relation(),
66
+			'Transaction'  => new EE_Has_Many_Relation(),
67
+			'Payment'      => new EE_Has_Many_Relation(),
68
+		);
69
+		//this model is generally available for reading
70
+		$this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
71 71
 
72
-        parent::__construct($timezone);
73
-    }
72
+		parent::__construct($timezone);
73
+	}
74 74
 
75 75
 
76
-    /**
77
-     * This method provides the localized singular or plural string for a given status id
78
-     *
79
-     * @param  array   $statuses This should be an array of statuses in the format array( $status_id, $status_code ).
80
-     *                           That way if there isn't a translation in the index we'll return the default code.
81
-     * @param  boolean $plural   Whether to return plural string or not. Note, nearly all of the plural strings are the
82
-     *                           same as the singular (in English), however, this may NOT be the case with other
83
-     *                           languages
84
-     * @param  string  $schema   This can be either 'upper', 'lower', or 'sentence'.  Basically indicates how we want
85
-     *                           the status string returned ( UPPER, lower, Sentence)
86
-     * @throws EE_Error
87
-     * @return array             an array of translated strings for the incoming status id.
88
-     */
89
-    public function localized_status($statuses, $plural = false, $schema = 'upper')
90
-    {
91
-        //note these are all in lower case because ucwords() on upper case will NOT convert.
92
-        $translation_array = array(
93
-            EEM_Registration::status_id_pending_payment => array(
94
-                __('pending payment', 'event_espresso'), //singular
95
-                __('pending payments', 'event_espresso') //plural
96
-            ),
97
-            EEM_Registration::status_id_approved        => array(
98
-                __('approved', 'event_espresso'), //singular
99
-                __('approved', 'event_espresso') //plural
100
-            ),
101
-            EEM_Registration::status_id_not_approved    => array(
102
-                __('not approved', 'event_espresso'),
103
-                __('not approved', 'event_espresso'),
104
-            ),
105
-            EEM_Registration::status_id_cancelled       => array(
106
-                __('cancelled', 'event_espresso'),
107
-                __('cancelled', 'event_espresso'),
108
-            ),
109
-            EEM_Registration::status_id_incomplete      => array(
110
-                __('incomplete', 'event_espresso'),
111
-                __('incomplete', 'event_espresso'),
112
-            ),
113
-            EEM_Registration::status_id_declined        => array(
114
-                __('declined', 'event_espresso'),
115
-                __('declined', 'event_espresso'),
116
-            ),
117
-            EEM_Registration::status_id_wait_list       => array(
118
-                __('wait list', 'event_espresso'),
119
-                __('wait list', 'event_espresso'),
120
-            ),
121
-            EEM_Transaction::overpaid_status_code       => array(
122
-                __('overpaid', 'event_espresso'),
123
-                __('overpaid', 'event_espresso'),
124
-            ),
125
-            EEM_Transaction::complete_status_code       => array(
126
-                __('complete', 'event_espresso'),
127
-                __('complete', 'event_espresso'),
128
-            ),
129
-            EEM_Transaction::incomplete_status_code     => array(
130
-                __('incomplete', 'event_espresso'),
131
-                __('incomplete', 'event_espresso'),
132
-            ),
133
-            EEM_Transaction::failed_status_code         => array(
134
-                __('failed', 'event_espresso'),
135
-                __('failed', 'event_espresso'),
136
-            ),
137
-            EEM_Transaction::abandoned_status_code      => array(
138
-                __('abandoned', 'event_espresso'),
139
-                __('abandoned', 'event_espresso'),
140
-            ),
141
-            EEM_Payment::status_id_approved             => array(
142
-                __('accepted', 'event_espresso'),
143
-                __('accepted', 'event_espresso'),
144
-            ),
145
-            EEM_Payment::status_id_pending              => array(
146
-                __('pending', 'event_espresso'),
147
-                __('pending', 'event_espresso'),
148
-            ),
149
-            EEM_Payment::status_id_cancelled            => array(
150
-                __('cancelled', 'event_espresso'),
151
-                __('cancelled', 'event_espresso'),
152
-            ),
153
-            EEM_Payment::status_id_declined             => array(
154
-                __('declined', 'event_espresso'),
155
-                __('declined', 'event_espresso'),
156
-            ),
157
-            EEM_Payment::status_id_failed               => array(
158
-                __('failed', 'event_espresso'),
159
-                __('failed', 'event_espresso'),
160
-            ),
161
-            //following statuses are NOT part of the EEM_Status but to keep things centralized we include in here.
162
-            EEM_Event::sold_out                         => array(
163
-                __('sold out', 'event_espresso'),
164
-                __('sold out', 'event_espresso'),
165
-            ),
166
-            EEM_Event::postponed                        => array(
167
-                __('postponed', 'event_espresso'),
168
-                __('Postponed', 'event_espresso'),
169
-            ),
170
-            EEM_Event::cancelled                        => array(
171
-                __('cancelled', 'event_espresso'),
172
-                __('cancelled', 'event_espresso'),
173
-            ),
174
-            EE_Ticket::archived                         => array(
175
-                __('archived', 'event_espresso'),
176
-                __('archived', 'event_espresso'),
177
-            ),
178
-            EE_Ticket::expired                          => array(
179
-                __('expired', 'event_espresso'),
180
-                __('expired', 'event_espresso'),
181
-            ),
182
-            EE_Ticket::sold_out                         => array(
183
-                __('sold out', 'event_espresso'),
184
-                __('sold out', 'event_espresso'),
185
-            ),
186
-            EE_Ticket::pending                          => array(
187
-                __('upcoming', 'event_espresso'),
188
-                __('upcoming', 'event_espresso'),
189
-            ),
190
-            EE_Ticket::onsale                           => array(
191
-                __('on sale', 'event_espresso'),
192
-                __('on sale', 'event_espresso'),
193
-            ),
194
-            EE_Datetime::cancelled                      => array(
195
-                __('cancelled', 'event_espresso'),
196
-                __('cancelled', 'event_espresso'),
197
-            ),
198
-            EE_Datetime::sold_out                       => array(
199
-                __('sold out', 'event_espresso'),
200
-                __('sold out', 'event_espresso'),
201
-            ),
202
-            EE_Datetime::expired                        => array(
203
-                __('expired', 'event_espresso'),
204
-                __('expired', 'event_espresso'),
205
-            ),
206
-            EE_Datetime::inactive                       => array(
207
-                __('inactive', 'event_espresso'),
208
-                __('inactive', 'event_espresso'),
209
-            ),
210
-            EE_Datetime::upcoming                       => array(
211
-                __('upcoming', 'event_espresso'),
212
-                __('upcoming', 'event_espresso'),
213
-            ),
214
-            EE_Datetime::active                         => array(
215
-                __('active', 'event_espresso'),
216
-                __('active', 'event_espresso'),
217
-            ),
218
-            EE_Datetime::postponed                      => array(
219
-                __('postponed', 'event_espresso'),
220
-                __('postponed', 'event_espresso'),
221
-            ),
222
-            //messages related
223
-            EEM_Message::status_sent                    => array(
224
-                __('sent', 'event_espresso'),
225
-                __('sent', 'event_espresso'),
226
-            ),
227
-            EEM_Message::status_idle                    => array(
228
-                __('queued for sending', 'event_espresso'),
229
-                __('queued for sending', 'event_espresso'),
230
-            ),
231
-            EEM_Message::status_failed                  => array(
232
-                __('failed', 'event_espresso'),
233
-                __('failed', 'event_espresso'),
234
-            ),
235
-            EEM_Message::status_debug_only              => array(
236
-                __('debug only', 'event_espresso'),
237
-                __('debug only', 'event_espresso'),
238
-            ),
239
-            EEM_Message::status_messenger_executing     => array(
240
-                __('messenger is executing', 'event_espresso'),
241
-                __('messenger is executing', 'event_espresso'),
242
-            ),
243
-            EEM_Message::status_resend                  => array(
244
-                __('queued for resending', 'event_espresso'),
245
-                __('queued for resending', 'event_espresso'),
246
-            ),
247
-            EEM_Message::status_incomplete              => array(
248
-                __('queued for generating', 'event_espresso'),
249
-                __('queued for generating', 'event_espresso'),
250
-            ),
251
-            EEM_Message::status_retry                   => array(
252
-                __('failed sending, can be retried', 'event_espresso'),
253
-                __('failed sending, can be retried', 'event_espresso'),
254
-            ),
255
-            EEM_CPT_Base::post_status_publish           => array(
256
-                __('published', 'event_espresso'),
257
-                __('published', 'event_espresso'),
258
-            ),
259
-            EEM_CPT_Base::post_status_future            => array(
260
-                __('scheduled', 'event_espresso'),
261
-                __('scheduled', 'event_espresso'),
262
-            ),
263
-            EEM_CPT_Base::post_status_draft             => array(
264
-                __('draft', 'event_espresso'),
265
-                __('draft', 'event_espresso'),
266
-            ),
267
-            EEM_CPT_Base::post_status_pending           => array(
268
-                __('pending', 'event_espresso'),
269
-                __('pending', 'event_espresso'),
270
-            ),
271
-            EEM_CPT_Base::post_status_private           => array(
272
-                __('private', 'event_espresso'),
273
-                __('private', 'event_espresso'),
274
-            ),
275
-            EEM_CPT_Base::post_status_trashed           => array(
276
-                __('trashed', 'event_espresso'),
277
-                __('trashed', 'event_espresso'),
278
-            ),
279
-        );
76
+	/**
77
+	 * This method provides the localized singular or plural string for a given status id
78
+	 *
79
+	 * @param  array   $statuses This should be an array of statuses in the format array( $status_id, $status_code ).
80
+	 *                           That way if there isn't a translation in the index we'll return the default code.
81
+	 * @param  boolean $plural   Whether to return plural string or not. Note, nearly all of the plural strings are the
82
+	 *                           same as the singular (in English), however, this may NOT be the case with other
83
+	 *                           languages
84
+	 * @param  string  $schema   This can be either 'upper', 'lower', or 'sentence'.  Basically indicates how we want
85
+	 *                           the status string returned ( UPPER, lower, Sentence)
86
+	 * @throws EE_Error
87
+	 * @return array             an array of translated strings for the incoming status id.
88
+	 */
89
+	public function localized_status($statuses, $plural = false, $schema = 'upper')
90
+	{
91
+		//note these are all in lower case because ucwords() on upper case will NOT convert.
92
+		$translation_array = array(
93
+			EEM_Registration::status_id_pending_payment => array(
94
+				__('pending payment', 'event_espresso'), //singular
95
+				__('pending payments', 'event_espresso') //plural
96
+			),
97
+			EEM_Registration::status_id_approved        => array(
98
+				__('approved', 'event_espresso'), //singular
99
+				__('approved', 'event_espresso') //plural
100
+			),
101
+			EEM_Registration::status_id_not_approved    => array(
102
+				__('not approved', 'event_espresso'),
103
+				__('not approved', 'event_espresso'),
104
+			),
105
+			EEM_Registration::status_id_cancelled       => array(
106
+				__('cancelled', 'event_espresso'),
107
+				__('cancelled', 'event_espresso'),
108
+			),
109
+			EEM_Registration::status_id_incomplete      => array(
110
+				__('incomplete', 'event_espresso'),
111
+				__('incomplete', 'event_espresso'),
112
+			),
113
+			EEM_Registration::status_id_declined        => array(
114
+				__('declined', 'event_espresso'),
115
+				__('declined', 'event_espresso'),
116
+			),
117
+			EEM_Registration::status_id_wait_list       => array(
118
+				__('wait list', 'event_espresso'),
119
+				__('wait list', 'event_espresso'),
120
+			),
121
+			EEM_Transaction::overpaid_status_code       => array(
122
+				__('overpaid', 'event_espresso'),
123
+				__('overpaid', 'event_espresso'),
124
+			),
125
+			EEM_Transaction::complete_status_code       => array(
126
+				__('complete', 'event_espresso'),
127
+				__('complete', 'event_espresso'),
128
+			),
129
+			EEM_Transaction::incomplete_status_code     => array(
130
+				__('incomplete', 'event_espresso'),
131
+				__('incomplete', 'event_espresso'),
132
+			),
133
+			EEM_Transaction::failed_status_code         => array(
134
+				__('failed', 'event_espresso'),
135
+				__('failed', 'event_espresso'),
136
+			),
137
+			EEM_Transaction::abandoned_status_code      => array(
138
+				__('abandoned', 'event_espresso'),
139
+				__('abandoned', 'event_espresso'),
140
+			),
141
+			EEM_Payment::status_id_approved             => array(
142
+				__('accepted', 'event_espresso'),
143
+				__('accepted', 'event_espresso'),
144
+			),
145
+			EEM_Payment::status_id_pending              => array(
146
+				__('pending', 'event_espresso'),
147
+				__('pending', 'event_espresso'),
148
+			),
149
+			EEM_Payment::status_id_cancelled            => array(
150
+				__('cancelled', 'event_espresso'),
151
+				__('cancelled', 'event_espresso'),
152
+			),
153
+			EEM_Payment::status_id_declined             => array(
154
+				__('declined', 'event_espresso'),
155
+				__('declined', 'event_espresso'),
156
+			),
157
+			EEM_Payment::status_id_failed               => array(
158
+				__('failed', 'event_espresso'),
159
+				__('failed', 'event_espresso'),
160
+			),
161
+			//following statuses are NOT part of the EEM_Status but to keep things centralized we include in here.
162
+			EEM_Event::sold_out                         => array(
163
+				__('sold out', 'event_espresso'),
164
+				__('sold out', 'event_espresso'),
165
+			),
166
+			EEM_Event::postponed                        => array(
167
+				__('postponed', 'event_espresso'),
168
+				__('Postponed', 'event_espresso'),
169
+			),
170
+			EEM_Event::cancelled                        => array(
171
+				__('cancelled', 'event_espresso'),
172
+				__('cancelled', 'event_espresso'),
173
+			),
174
+			EE_Ticket::archived                         => array(
175
+				__('archived', 'event_espresso'),
176
+				__('archived', 'event_espresso'),
177
+			),
178
+			EE_Ticket::expired                          => array(
179
+				__('expired', 'event_espresso'),
180
+				__('expired', 'event_espresso'),
181
+			),
182
+			EE_Ticket::sold_out                         => array(
183
+				__('sold out', 'event_espresso'),
184
+				__('sold out', 'event_espresso'),
185
+			),
186
+			EE_Ticket::pending                          => array(
187
+				__('upcoming', 'event_espresso'),
188
+				__('upcoming', 'event_espresso'),
189
+			),
190
+			EE_Ticket::onsale                           => array(
191
+				__('on sale', 'event_espresso'),
192
+				__('on sale', 'event_espresso'),
193
+			),
194
+			EE_Datetime::cancelled                      => array(
195
+				__('cancelled', 'event_espresso'),
196
+				__('cancelled', 'event_espresso'),
197
+			),
198
+			EE_Datetime::sold_out                       => array(
199
+				__('sold out', 'event_espresso'),
200
+				__('sold out', 'event_espresso'),
201
+			),
202
+			EE_Datetime::expired                        => array(
203
+				__('expired', 'event_espresso'),
204
+				__('expired', 'event_espresso'),
205
+			),
206
+			EE_Datetime::inactive                       => array(
207
+				__('inactive', 'event_espresso'),
208
+				__('inactive', 'event_espresso'),
209
+			),
210
+			EE_Datetime::upcoming                       => array(
211
+				__('upcoming', 'event_espresso'),
212
+				__('upcoming', 'event_espresso'),
213
+			),
214
+			EE_Datetime::active                         => array(
215
+				__('active', 'event_espresso'),
216
+				__('active', 'event_espresso'),
217
+			),
218
+			EE_Datetime::postponed                      => array(
219
+				__('postponed', 'event_espresso'),
220
+				__('postponed', 'event_espresso'),
221
+			),
222
+			//messages related
223
+			EEM_Message::status_sent                    => array(
224
+				__('sent', 'event_espresso'),
225
+				__('sent', 'event_espresso'),
226
+			),
227
+			EEM_Message::status_idle                    => array(
228
+				__('queued for sending', 'event_espresso'),
229
+				__('queued for sending', 'event_espresso'),
230
+			),
231
+			EEM_Message::status_failed                  => array(
232
+				__('failed', 'event_espresso'),
233
+				__('failed', 'event_espresso'),
234
+			),
235
+			EEM_Message::status_debug_only              => array(
236
+				__('debug only', 'event_espresso'),
237
+				__('debug only', 'event_espresso'),
238
+			),
239
+			EEM_Message::status_messenger_executing     => array(
240
+				__('messenger is executing', 'event_espresso'),
241
+				__('messenger is executing', 'event_espresso'),
242
+			),
243
+			EEM_Message::status_resend                  => array(
244
+				__('queued for resending', 'event_espresso'),
245
+				__('queued for resending', 'event_espresso'),
246
+			),
247
+			EEM_Message::status_incomplete              => array(
248
+				__('queued for generating', 'event_espresso'),
249
+				__('queued for generating', 'event_espresso'),
250
+			),
251
+			EEM_Message::status_retry                   => array(
252
+				__('failed sending, can be retried', 'event_espresso'),
253
+				__('failed sending, can be retried', 'event_espresso'),
254
+			),
255
+			EEM_CPT_Base::post_status_publish           => array(
256
+				__('published', 'event_espresso'),
257
+				__('published', 'event_espresso'),
258
+			),
259
+			EEM_CPT_Base::post_status_future            => array(
260
+				__('scheduled', 'event_espresso'),
261
+				__('scheduled', 'event_espresso'),
262
+			),
263
+			EEM_CPT_Base::post_status_draft             => array(
264
+				__('draft', 'event_espresso'),
265
+				__('draft', 'event_espresso'),
266
+			),
267
+			EEM_CPT_Base::post_status_pending           => array(
268
+				__('pending', 'event_espresso'),
269
+				__('pending', 'event_espresso'),
270
+			),
271
+			EEM_CPT_Base::post_status_private           => array(
272
+				__('private', 'event_espresso'),
273
+				__('private', 'event_espresso'),
274
+			),
275
+			EEM_CPT_Base::post_status_trashed           => array(
276
+				__('trashed', 'event_espresso'),
277
+				__('trashed', 'event_espresso'),
278
+			),
279
+		);
280 280
 
281
-        $translation_array = apply_filters('FHEE__EEM_Status__localized_status__translation_array', $translation_array);
281
+		$translation_array = apply_filters('FHEE__EEM_Status__localized_status__translation_array', $translation_array);
282 282
 
283
-        if ( ! is_array($statuses)) {
284
-            throw new EE_Error(__('The incoming statuses argument must be an array with keys as the $status_id and values as the $status_code',
285
-                'event_espresso'));
286
-        }
283
+		if ( ! is_array($statuses)) {
284
+			throw new EE_Error(__('The incoming statuses argument must be an array with keys as the $status_id and values as the $status_code',
285
+				'event_espresso'));
286
+		}
287 287
 
288
-        $translation = array();
288
+		$translation = array();
289 289
 
290
-        foreach ($statuses as $id => $code) {
291
-            if (isset($translation_array[$id])) {
292
-                $translation[$id] = $plural ? $translation_array[$id][1] : $translation_array[$id][0];
293
-            } else {
294
-                $translation[$id] = $code;
295
-            }
290
+		foreach ($statuses as $id => $code) {
291
+			if (isset($translation_array[$id])) {
292
+				$translation[$id] = $plural ? $translation_array[$id][1] : $translation_array[$id][0];
293
+			} else {
294
+				$translation[$id] = $code;
295
+			}
296 296
 
297
-            //schema
298
-            switch ($schema) {
299
-                case 'lower' :
300
-                    $translation[$id] = strtolower($translation[$id]); //even though these start in lower case, this will catch any statuses added via filter.
301
-                    break;
302
-                case 'sentence' :
303
-                    $translation[$id] = ucwords($translation[$id]);
304
-                    break;
305
-                case 'upper' :
306
-                    $translation[$id] = strtoupper($translation[$id]);
307
-                    break;
308
-            }
309
-        }
297
+			//schema
298
+			switch ($schema) {
299
+				case 'lower' :
300
+					$translation[$id] = strtolower($translation[$id]); //even though these start in lower case, this will catch any statuses added via filter.
301
+					break;
302
+				case 'sentence' :
303
+					$translation[$id] = ucwords($translation[$id]);
304
+					break;
305
+				case 'upper' :
306
+					$translation[$id] = strtoupper($translation[$id]);
307
+					break;
308
+			}
309
+		}
310 310
 
311
-        return $translation;
312
-    }
311
+		return $translation;
312
+	}
313 313
 
314 314
 
315 315
 }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Message_Repository.lib.php 2 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-if (! defined('EVENT_ESPRESSO_VERSION')) {
2
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
3 3
     exit('No direct script access allowed');
4 4
 }
5 5
 
@@ -38,7 +38,7 @@  discard block
 block discarded – undo
38 38
     {
39 39
         $attached = parent::add($message);
40 40
         //ensure $info is an array if not already
41
-        $info = $info === null ? $info = array() : (array)$info;
41
+        $info = $info === null ? $info = array() : (array) $info;
42 42
         $data = $this->_init_data($info, $attached, $message);
43 43
         if ($attached) {
44 44
             $this->set_info($message, $data);
@@ -103,10 +103,10 @@  discard block
 block discarded – undo
103 103
     {
104 104
         $save_tracking = array('updated' => 0, 'notupdated' => 0, 'errors' => array());
105 105
 
106
-        if (! $do_hooks_only) {
106
+        if ( ! $do_hooks_only) {
107 107
             $this->rewind();
108 108
             //exit early if there is nothing to save.
109
-            if (! $this->count() > 0) {
109
+            if ( ! $this->count() > 0) {
110 110
                 return $save_tracking;
111 111
             }
112 112
 
Please login to merge, or discard this patch.
Indentation   +251 added lines, -251 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if (! defined('EVENT_ESPRESSO_VERSION')) {
3
-    exit('No direct script access allowed');
3
+	exit('No direct script access allowed');
4 4
 }
5 5
 
6 6
 
@@ -16,256 +16,256 @@  discard block
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     *    EE_Message_Repository constructor
21
-     */
22
-    public function __construct()
23
-    {
24
-        $this->interface = 'EE_Message';
25
-        parent::__construct();
26
-    }
27
-
28
-
29
-    /**
30
-     * Add the EE_Message to the repository.
31
-     * This also ensures that the MSG_token is saves as a part of the info for retrieval.
32
-     *
33
-     * @param EE_Message $message
34
-     * @param mixed      $info Any included data is saved in the attached object info array indexed by 'data'
35
-     * @return bool
36
-     */
37
-    public function add($message, $info = null)
38
-    {
39
-        $attached = parent::add($message);
40
-        //ensure $info is an array if not already
41
-        $info = $info === null ? $info = array() : (array)$info;
42
-        $data = $this->_init_data($info, $attached, $message);
43
-        if ($attached) {
44
-            $this->set_info($message, $data);
45
-        }
46
-        return $attached;
47
-    }
48
-
49
-
50
-    /**
51
-     * Initializes the data from the incoming info.
52
-     *
53
-     * @param array      $info     incoming data.
54
-     * @param bool       $attached Indicates whether the object was attached successfully.
55
-     * @param EE_Message $message
56
-     * @return array
57
-     */
58
-    protected function _init_data($info, $attached, $message)
59
-    {
60
-        $data = array(
61
-            'test_send'               => false,
62
-            'preview'                 => false,
63
-            'data_handler_class_name' => '',
64
-            'data'                    => array(
65
-                'MSG_generation_data' => array(),
66
-            ),
67
-        );
68
-        if (isset($info['preview'])) {
69
-            $data['preview'] = $info['preview'];
70
-            unset($info['preview']);
71
-        }
72
-        if (isset($info['test_send'])) {
73
-            $data['test_send'] = $info['test_send'];
74
-            unset($info['test_send']);
75
-        }
76
-        if (isset($info['data_handler_class_name'])) {
77
-            $data['data_handler_class_name'] = $info['data_handler_class_name'];
78
-            unset($info['data_handler_class_name']);
79
-        }
80
-        if ($attached && $message->STS_ID() === EEM_Message::status_incomplete) {
81
-            $generation_data = isset($info['MSG_generation_data']) ? $info['MSG_generation_data'] : array();
82
-            //if data isn't in $info...let's see if its available via the message object
83
-            $generation_data = ! $generation_data ? $message->get_generation_data() : $generation_data;
84
-            //still empty then let's just use info
85
-            $generation_data                     = ! $generation_data ? $info : $generation_data;
86
-            $data['data']['MSG_generation_data'] = $generation_data;
87
-        }
88
-        return $data;
89
-    }
90
-
91
-
92
-    /**
93
-     * Save all EE_Message objects to the db.
94
-     *
95
-     * @param bool $do_hooks_only  When true, only the hooks related to saving are fired.
96
-     * @return array array(
97
-     *                  'updated' => 0, //count of how many messages updated
98
-     *                  'notupdated' => 0, //count of how many messages not updated.
99
-     *                  'errors' => array( $token ), //array of message object tokens that had errors in saving
100
-     *                  )
101
-     */
102
-    public function saveAll($do_hooks_only = false)
103
-    {
104
-        $save_tracking = array('updated' => 0, 'notupdated' => 0, 'errors' => array());
105
-
106
-        if (! $do_hooks_only) {
107
-            $this->rewind();
108
-            //exit early if there is nothing to save.
109
-            if (! $this->count() > 0) {
110
-                return $save_tracking;
111
-            }
112
-
113
-            while ($this->valid()) {
114
-                $saved = $this->current()->save();
115
-                if ($saved === false) {
116
-                    $save_tracking['errors'][] = $this->current()->MSG_token();
117
-                } elseif ($saved) {
118
-                    $save_tracking['updated']++;
119
-                } else {
120
-                    $save_tracking['notupdated']++;
121
-                }
122
-                //maybe persist generation data if this is an incomplete EE_Message.
123
-                $this->_maybe_persist_attached_data();
124
-
125
-                $this->next();
126
-            }
127
-        }
128
-        do_action('AHEE__EE_Message_Repository__saveAll__after', $save_tracking, $this, $do_hooks_only);
129
-        return $save_tracking;
130
-    }
131
-
132
-
133
-    /**
134
-     * Retrieves a EE_Message from the repository that matches the given token.
135
-     *
136
-     * @param string $token Token.
137
-     * @return EE_Message | null
138
-     */
139
-    public function getMessageByToken($token)
140
-    {
141
-        $this->rewind();
142
-        while ($this->valid()) {
143
-            if ($this->current()->MSG_token() === $token) {
144
-                $message = $this->current();
145
-                $this->rewind();
146
-                return $message;
147
-            }
148
-            $this->next();
149
-        }
150
-        return null;
151
-    }
152
-
153
-
154
-    /**
155
-     * This retrieves any data required for generation that may be saved with the current EE_Message in storage.
156
-     *
157
-     * @return array();
158
-     */
159
-    public function get_generation_data()
160
-    {
161
-        //first verify we're at a valid iterator point.
162
-        if ( ! $this->valid()) {
163
-            return array();
164
-        }
165
-        $info = $this->getInfo();
166
-        return isset($info['data']) && isset($info['data']['MSG_generation_data']) ? $info['data']['MSG_generation_data'] : array();
167
-    }
168
-
169
-
170
-    /**
171
-     * Retrieves the data_handler_class_name or reference associated with the current EE_Message object in the iterator.
172
-     *
173
-     * @return string
174
-     */
175
-    public function get_data_handler()
176
-    {
177
-        if ( ! $this->valid()) {
178
-            return '';
179
-        }
180
-        $info = $this->getInfo();
181
-        return isset($info['data_handler_class_name']) ? $info['data_handler_class_name'] : '';
182
-    }
183
-
184
-
185
-    /**
186
-     * Returns whether this EE_Message is for a preview or not.
187
-     *
188
-     * @return bool
189
-     */
190
-    public function is_preview()
191
-    {
192
-        if ( ! $this->valid()) {
193
-            return false;
194
-        }
195
-        $info = $this->getInfo();
196
-        return $info['preview'];
197
-    }
198
-
199
-
200
-    /**
201
-     * Returns whether the current message pointed to is for a test send.
202
-     *
203
-     * @return bool
204
-     */
205
-    public function is_test_send()
206
-    {
207
-        if ( ! $this->valid()) {
208
-            return false;
209
-        }
210
-        $info = $this->getInfo();
211
-        return $info['test_send'];
212
-    }
213
-
214
-
215
-    /**
216
-     *  This checks if the current EE_Message in the iterator is incomplete. If it is, then
217
-     *  data is attached for later retrieval (batch generation).
218
-     */
219
-    protected function _maybe_persist_attached_data()
220
-    {
221
-        if ( ! $this->valid()) {
222
-            return;
223
-        }
224
-
225
-        $info                    = $this->getInfo();
226
-        $data_handler_class_name = isset($info['data_handler_class_name']) ? $info['data_handler_class_name'] : '';
227
-        $data                    = isset($info['data']) && isset($info['data']['MSG_generation_data']) ? $info['data']['MSG_generation_data'] : array();
228
-        if ($data && $this->current()->STS_ID() === EEM_Message::status_incomplete) {
229
-            $this->current()->set_generation_data($data);
230
-            $this->current()->set_field_or_extra_meta('data_handler_class_name', $data_handler_class_name);
231
-        }
232
-    }
233
-
234
-
235
-    /**
236
-     * This method returns a count of messages in the repository that have a given priority.
237
-     *
238
-     * @param int   $priority the priority that is being filtered for the count.
239
-     * @param array $status   the optional status(es) that will also be filtered by when priority matches.
240
-     * @return int  count of messages in the queue matching the conditions.
241
-     */
242
-    public function count_by_priority_and_status($priority, $status = array())
243
-    {
244
-        if ( ! empty($status)) {
245
-            $status = is_array($status) ? $status : array($status);
246
-        }
247
-
248
-        $count = 0;
249
-        $this->rewind();
250
-        while ($this->valid()) {
251
-            if ($this->current()->priority() === $priority && (($status && in_array($this->current()->STS_ID(),
252
-                            $status)) || ! $status)
253
-            ) {
254
-                $count++;
255
-            }
256
-            $this->next();
257
-        }
258
-        return $count;
259
-    }
260
-
261
-
262
-    /**
263
-     * @return EE_Message
264
-     */
265
-    public function current()
266
-    {
267
-        return parent::current();
268
-    }
19
+	/**
20
+	 *    EE_Message_Repository constructor
21
+	 */
22
+	public function __construct()
23
+	{
24
+		$this->interface = 'EE_Message';
25
+		parent::__construct();
26
+	}
27
+
28
+
29
+	/**
30
+	 * Add the EE_Message to the repository.
31
+	 * This also ensures that the MSG_token is saves as a part of the info for retrieval.
32
+	 *
33
+	 * @param EE_Message $message
34
+	 * @param mixed      $info Any included data is saved in the attached object info array indexed by 'data'
35
+	 * @return bool
36
+	 */
37
+	public function add($message, $info = null)
38
+	{
39
+		$attached = parent::add($message);
40
+		//ensure $info is an array if not already
41
+		$info = $info === null ? $info = array() : (array)$info;
42
+		$data = $this->_init_data($info, $attached, $message);
43
+		if ($attached) {
44
+			$this->set_info($message, $data);
45
+		}
46
+		return $attached;
47
+	}
48
+
49
+
50
+	/**
51
+	 * Initializes the data from the incoming info.
52
+	 *
53
+	 * @param array      $info     incoming data.
54
+	 * @param bool       $attached Indicates whether the object was attached successfully.
55
+	 * @param EE_Message $message
56
+	 * @return array
57
+	 */
58
+	protected function _init_data($info, $attached, $message)
59
+	{
60
+		$data = array(
61
+			'test_send'               => false,
62
+			'preview'                 => false,
63
+			'data_handler_class_name' => '',
64
+			'data'                    => array(
65
+				'MSG_generation_data' => array(),
66
+			),
67
+		);
68
+		if (isset($info['preview'])) {
69
+			$data['preview'] = $info['preview'];
70
+			unset($info['preview']);
71
+		}
72
+		if (isset($info['test_send'])) {
73
+			$data['test_send'] = $info['test_send'];
74
+			unset($info['test_send']);
75
+		}
76
+		if (isset($info['data_handler_class_name'])) {
77
+			$data['data_handler_class_name'] = $info['data_handler_class_name'];
78
+			unset($info['data_handler_class_name']);
79
+		}
80
+		if ($attached && $message->STS_ID() === EEM_Message::status_incomplete) {
81
+			$generation_data = isset($info['MSG_generation_data']) ? $info['MSG_generation_data'] : array();
82
+			//if data isn't in $info...let's see if its available via the message object
83
+			$generation_data = ! $generation_data ? $message->get_generation_data() : $generation_data;
84
+			//still empty then let's just use info
85
+			$generation_data                     = ! $generation_data ? $info : $generation_data;
86
+			$data['data']['MSG_generation_data'] = $generation_data;
87
+		}
88
+		return $data;
89
+	}
90
+
91
+
92
+	/**
93
+	 * Save all EE_Message objects to the db.
94
+	 *
95
+	 * @param bool $do_hooks_only  When true, only the hooks related to saving are fired.
96
+	 * @return array array(
97
+	 *                  'updated' => 0, //count of how many messages updated
98
+	 *                  'notupdated' => 0, //count of how many messages not updated.
99
+	 *                  'errors' => array( $token ), //array of message object tokens that had errors in saving
100
+	 *                  )
101
+	 */
102
+	public function saveAll($do_hooks_only = false)
103
+	{
104
+		$save_tracking = array('updated' => 0, 'notupdated' => 0, 'errors' => array());
105
+
106
+		if (! $do_hooks_only) {
107
+			$this->rewind();
108
+			//exit early if there is nothing to save.
109
+			if (! $this->count() > 0) {
110
+				return $save_tracking;
111
+			}
112
+
113
+			while ($this->valid()) {
114
+				$saved = $this->current()->save();
115
+				if ($saved === false) {
116
+					$save_tracking['errors'][] = $this->current()->MSG_token();
117
+				} elseif ($saved) {
118
+					$save_tracking['updated']++;
119
+				} else {
120
+					$save_tracking['notupdated']++;
121
+				}
122
+				//maybe persist generation data if this is an incomplete EE_Message.
123
+				$this->_maybe_persist_attached_data();
124
+
125
+				$this->next();
126
+			}
127
+		}
128
+		do_action('AHEE__EE_Message_Repository__saveAll__after', $save_tracking, $this, $do_hooks_only);
129
+		return $save_tracking;
130
+	}
131
+
132
+
133
+	/**
134
+	 * Retrieves a EE_Message from the repository that matches the given token.
135
+	 *
136
+	 * @param string $token Token.
137
+	 * @return EE_Message | null
138
+	 */
139
+	public function getMessageByToken($token)
140
+	{
141
+		$this->rewind();
142
+		while ($this->valid()) {
143
+			if ($this->current()->MSG_token() === $token) {
144
+				$message = $this->current();
145
+				$this->rewind();
146
+				return $message;
147
+			}
148
+			$this->next();
149
+		}
150
+		return null;
151
+	}
152
+
153
+
154
+	/**
155
+	 * This retrieves any data required for generation that may be saved with the current EE_Message in storage.
156
+	 *
157
+	 * @return array();
158
+	 */
159
+	public function get_generation_data()
160
+	{
161
+		//first verify we're at a valid iterator point.
162
+		if ( ! $this->valid()) {
163
+			return array();
164
+		}
165
+		$info = $this->getInfo();
166
+		return isset($info['data']) && isset($info['data']['MSG_generation_data']) ? $info['data']['MSG_generation_data'] : array();
167
+	}
168
+
169
+
170
+	/**
171
+	 * Retrieves the data_handler_class_name or reference associated with the current EE_Message object in the iterator.
172
+	 *
173
+	 * @return string
174
+	 */
175
+	public function get_data_handler()
176
+	{
177
+		if ( ! $this->valid()) {
178
+			return '';
179
+		}
180
+		$info = $this->getInfo();
181
+		return isset($info['data_handler_class_name']) ? $info['data_handler_class_name'] : '';
182
+	}
183
+
184
+
185
+	/**
186
+	 * Returns whether this EE_Message is for a preview or not.
187
+	 *
188
+	 * @return bool
189
+	 */
190
+	public function is_preview()
191
+	{
192
+		if ( ! $this->valid()) {
193
+			return false;
194
+		}
195
+		$info = $this->getInfo();
196
+		return $info['preview'];
197
+	}
198
+
199
+
200
+	/**
201
+	 * Returns whether the current message pointed to is for a test send.
202
+	 *
203
+	 * @return bool
204
+	 */
205
+	public function is_test_send()
206
+	{
207
+		if ( ! $this->valid()) {
208
+			return false;
209
+		}
210
+		$info = $this->getInfo();
211
+		return $info['test_send'];
212
+	}
213
+
214
+
215
+	/**
216
+	 *  This checks if the current EE_Message in the iterator is incomplete. If it is, then
217
+	 *  data is attached for later retrieval (batch generation).
218
+	 */
219
+	protected function _maybe_persist_attached_data()
220
+	{
221
+		if ( ! $this->valid()) {
222
+			return;
223
+		}
224
+
225
+		$info                    = $this->getInfo();
226
+		$data_handler_class_name = isset($info['data_handler_class_name']) ? $info['data_handler_class_name'] : '';
227
+		$data                    = isset($info['data']) && isset($info['data']['MSG_generation_data']) ? $info['data']['MSG_generation_data'] : array();
228
+		if ($data && $this->current()->STS_ID() === EEM_Message::status_incomplete) {
229
+			$this->current()->set_generation_data($data);
230
+			$this->current()->set_field_or_extra_meta('data_handler_class_name', $data_handler_class_name);
231
+		}
232
+	}
233
+
234
+
235
+	/**
236
+	 * This method returns a count of messages in the repository that have a given priority.
237
+	 *
238
+	 * @param int   $priority the priority that is being filtered for the count.
239
+	 * @param array $status   the optional status(es) that will also be filtered by when priority matches.
240
+	 * @return int  count of messages in the queue matching the conditions.
241
+	 */
242
+	public function count_by_priority_and_status($priority, $status = array())
243
+	{
244
+		if ( ! empty($status)) {
245
+			$status = is_array($status) ? $status : array($status);
246
+		}
247
+
248
+		$count = 0;
249
+		$this->rewind();
250
+		while ($this->valid()) {
251
+			if ($this->current()->priority() === $priority && (($status && in_array($this->current()->STS_ID(),
252
+							$status)) || ! $status)
253
+			) {
254
+				$count++;
255
+			}
256
+			$this->next();
257
+		}
258
+		return $count;
259
+	}
260
+
261
+
262
+	/**
263
+	 * @return EE_Message
264
+	 */
265
+	public function current()
266
+	{
267
+		return parent::current();
268
+	}
269 269
 
270 270
 
271 271
 }
272 272
\ No newline at end of file
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Queue.lib.php 2 patches
Indentation   +677 added lines, -677 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use \EventEspresso\core\exceptions\SendMessageException;
3 3
 
4 4
 if (! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 
8 8
 /**
@@ -18,681 +18,681 @@  discard block
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * @type    string  reference for sending action
23
-     */
24
-    const action_sending = 'sending';
25
-
26
-    /**
27
-     * @type    string  reference for generation action
28
-     */
29
-    const action_generating = 'generation';
30
-
31
-
32
-    /**
33
-     * @type EE_Message_Repository $_message_repository
34
-     */
35
-    protected $_message_repository;
36
-
37
-    /**
38
-     * Sets the limit of how many messages are generated per process.
39
-     *
40
-     * @type int
41
-     */
42
-    protected $_batch_count;
43
-
44
-    /**
45
-     * Sets the limit of how many messages can be sent per hour.
46
-     *
47
-     * @type int
48
-     */
49
-    protected $_rate_limit;
50
-
51
-    /**
52
-     * This is an array of cached queue items being stored in this object.
53
-     * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
54
-     * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
55
-     *
56
-     * @type EE_Message[]
57
-     */
58
-    protected $_cached_queue_items;
59
-
60
-    /**
61
-     * Tracks the number of unsaved queue items.
62
-     *
63
-     * @type int
64
-     */
65
-    protected $_unsaved_count = 0;
66
-
67
-    /**
68
-     * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
69
-     * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
70
-     *
71
-     * @type array
72
-     */
73
-    protected $_did_hook = array();
74
-
75
-
76
-    /**
77
-     * Constructor.
78
-     * Setup all the initial properties and load a EE_Message_Repository.
79
-     *
80
-     * @param \EE_Message_Repository $message_repository
81
-     */
82
-    public function __construct(EE_Message_Repository $message_repository)
83
-    {
84
-        $this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
85
-        $this->_rate_limit         = $this->get_rate_limit();
86
-        $this->_message_repository = $message_repository;
87
-    }
88
-
89
-
90
-    /**
91
-     * Add a EE_Message object to the queue
92
-     *
93
-     * @param EE_Message $message
94
-     * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
95
-     *                                 object is persisted, this data will be saved on an extra_meta object related to
96
-     *                                 EE_Message.
97
-     * @param  bool      $preview      Whether this EE_Message represents a preview or not.
98
-     * @param  bool      $test_send    This indicates whether to do a test send instead of actual send. A test send will
99
-     *                                 use the messenger send method but typically is based on preview data.
100
-     * @return bool          Whether the message was successfully added to the repository or not.
101
-     */
102
-    public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false)
103
-    {
104
-        $data['preview']   = $preview;
105
-        $data['test_send'] = $test_send;
106
-        return $this->_message_repository->add($message, $data);
107
-    }
108
-
109
-
110
-    /**
111
-     * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
112
-     *
113
-     * @param EE_Message $message The message to detach from the queue
114
-     * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
115
-     * @return bool
116
-     */
117
-    public function remove(EE_Message $message, $persist = false)
118
-    {
119
-        if ($persist && $this->_message_repository->current() !== $message) {
120
-            //get pointer on right message
121
-            if ($this->_message_repository->has($message)) {
122
-                $this->_message_repository->rewind();
123
-                while ($this->_message_repository->valid()) {
124
-                    if ($this->_message_repository->current() === $message) {
125
-                        break;
126
-                    }
127
-                    $this->_message_repository->next();
128
-                }
129
-            } else {
130
-                return false;
131
-            }
132
-        }
133
-        return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
134
-    }
135
-
136
-
137
-    /**
138
-     * Persists all queued EE_Message objects to the db.
139
-     *
140
-     * @param bool $do_hooks_only       @see EE_Message_Repository::saveAll
141
-     * @return array @see EE_Messages_Repository::saveAll() for return values.
142
-     */
143
-    public function save($do_hooks_only = false)
144
-    {
145
-        return $this->_message_repository->saveAll($do_hooks_only);
146
-    }
147
-
148
-
149
-    /**
150
-     * @return EE_Message_Repository
151
-     */
152
-    public function get_message_repository()
153
-    {
154
-        return $this->_message_repository;
155
-    }
156
-
157
-
158
-    /**
159
-     * This does the following things:
160
-     * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
161
-     * false).
162
-     * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
163
-     * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
164
-     * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
165
-     * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
166
-     * removed.
167
-     *
168
-     * @return bool  true if successfully retrieved batch, false no batch ready.
169
-     */
170
-    public function get_batch_to_generate()
171
-    {
172
-        if ($this->is_locked(EE_Messages_Queue::action_generating)) {
173
-            return false;
174
-        }
175
-
176
-        //lock batch generation to prevent race conditions.
177
-        $this->lock_queue(EE_Messages_Queue::action_generating);
178
-
179
-        $query_args = array(
180
-            // key 0 = where conditions
181
-            0          => array('STS_ID' => EEM_Message::status_incomplete),
182
-            'order_by' => $this->_get_priority_orderby(),
183
-            'limit'    => $this->_batch_count,
184
-        );
185
-        $messages   = EEM_Message::instance()->get_all($query_args);
186
-
187
-        if ( ! $messages) {
188
-            return false; //nothing to generate
189
-        }
190
-
191
-        foreach ($messages as $message) {
192
-            if ($message instanceof EE_Message) {
193
-                $data = $message->all_extra_meta_array();
194
-                $this->add($message, $data);
195
-            }
196
-        }
197
-        return true;
198
-    }
199
-
200
-
201
-    /**
202
-     * This does the following things:
203
-     * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
204
-     * false).
205
-     * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
206
-     * return false.
207
-     * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
208
-     * 3. On success or unsuccessful send, sets status appropriately.
209
-     * 4. Saves messages via the queue
210
-     * 5. Releases lock.
211
-     *
212
-     * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
213
-     *               necessarily mean that all messages were successfully sent.  It just means that this method
214
-     *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
215
-     *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
216
-     *               will also have a saved error message on it to assist with notifying user.
217
-     */
218
-    public function get_to_send_batch_and_send()
219
-    {
220
-        if ($this->is_locked(EE_Messages_Queue::action_sending) || $this->_rate_limit < 1) {
221
-            return false;
222
-        }
223
-
224
-        $this->lock_queue(EE_Messages_Queue::action_sending);
225
-
226
-        $batch = $this->_batch_count < $this->_rate_limit ? $this->_batch_count : $this->_rate_limit;
227
-
228
-        $query_args = array(
229
-            // key 0 = where conditions
230
-            0          => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())),
231
-            'order_by' => $this->_get_priority_orderby(),
232
-            'limit'    => $batch,
233
-        );
234
-
235
-        $messages_to_send = EEM_Message::instance()->get_all($query_args);
236
-
237
-
238
-        //any to send?
239
-        if ( ! $messages_to_send) {
240
-            $this->unlock_queue(EE_Messages_Queue::action_sending);
241
-            return false;
242
-        }
243
-
244
-        //add to queue.
245
-        foreach ($messages_to_send as $message) {
246
-            if ($message instanceof EE_Message) {
247
-                $this->add($message);
248
-            }
249
-        }
250
-
251
-        //send messages  (this also updates the rate limit)
252
-        $this->execute();
253
-
254
-        //release lock
255
-        $this->unlock_queue(EE_Messages_Queue::action_sending);
256
-        return true;
257
-    }
258
-
259
-
260
-    /**
261
-     * Locks the queue so that no other queues can call the "batch" methods.
262
-     *
263
-     * @param   string $type The type of queue being locked.
264
-     */
265
-    public function lock_queue($type = EE_Messages_Queue::action_generating)
266
-    {
267
-        set_transient($this->_get_lock_key($type), 1, $this->_get_lock_expiry($type));
268
-    }
269
-
270
-
271
-    /**
272
-     * Unlocks the queue so that batch methods can be used.
273
-     *
274
-     * @param   string $type The type of queue being unlocked.
275
-     */
276
-    public function unlock_queue($type = EE_Messages_Queue::action_generating)
277
-    {
278
-        delete_transient($this->_get_lock_key($type));
279
-    }
280
-
281
-
282
-    /**
283
-     * Retrieve the key used for the lock transient.
284
-     *
285
-     * @param string $type The type of lock.
286
-     * @return string
287
-     */
288
-    protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
289
-    {
290
-        return '_ee_lock_' . $type;
291
-    }
292
-
293
-
294
-    /**
295
-     * Retrieve the expiry time for the lock transient.
296
-     *
297
-     * @param string $type The type of lock
298
-     * @return int   time to expiry in seconds.
299
-     */
300
-    protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
301
-    {
302
-        return (int)apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
303
-    }
304
-
305
-
306
-    /**
307
-     * Returns the key used for rate limit transient.
308
-     *
309
-     * @return string
310
-     */
311
-    protected function _get_rate_limit_key()
312
-    {
313
-        return '_ee_rate_limit';
314
-    }
315
-
316
-
317
-    /**
318
-     * Returns the rate limit expiry time.
319
-     *
320
-     * @return int
321
-     */
322
-    protected function _get_rate_limit_expiry()
323
-    {
324
-        return (int)apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
325
-    }
326
-
327
-
328
-    /**
329
-     * Returns the default rate limit for sending messages.
330
-     *
331
-     * @return int
332
-     */
333
-    protected function _default_rate_limit()
334
-    {
335
-        return (int)apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
336
-    }
337
-
338
-
339
-    /**
340
-     * Return the orderby array for priority.
341
-     *
342
-     * @return array
343
-     */
344
-    protected function _get_priority_orderby()
345
-    {
346
-        return array(
347
-            'MSG_priority' => 'ASC',
348
-            'MSG_modified' => 'DESC',
349
-        );
350
-    }
351
-
352
-
353
-    /**
354
-     * Returns whether batch methods are "locked" or not.
355
-     *
356
-     * @param  string $type The type of lock being checked for.
357
-     * @return bool
358
-     */
359
-    public function is_locked($type = EE_Messages_Queue::action_generating)
360
-    {
361
-        /**
362
-         * This filters the default is_locked behaviour.
363
-         */
364
-        $is_locked = filter_var(
365
-            apply_filters(
366
-                'FHEE__EE_Messages_Queue__is_locked',
367
-                get_transient($this->_get_lock_key($type)),
368
-                $this
369
-            ),
370
-            FILTER_VALIDATE_BOOLEAN
371
-        );
372
-
373
-        /**
374
-         * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
375
-         *            Also implemented here because messages processed on the same request should not have any locks applied.
376
-         */
377
-        if (
378
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
379
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
380
-        ) {
381
-            $is_locked = false;
382
-        }
383
-
384
-
385
-        return $is_locked;
386
-    }
387
-
388
-
389
-    /**
390
-     * Retrieves the rate limit that may be cached as a transient.
391
-     * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
392
-     *
393
-     * @return int
394
-     */
395
-    public function get_rate_limit()
396
-    {
397
-        if ( ! $rate_limit = get_transient($this->_get_rate_limit_key())) {
398
-            $rate_limit = $this->_default_rate_limit();
399
-            set_transient($this->_get_rate_limit_key(), $rate_limit, $this->_get_rate_limit_key());
400
-        }
401
-        return $rate_limit;
402
-    }
403
-
404
-
405
-    /**
406
-     * This updates existing rate limit with the new limit which is the old minus the batch.
407
-     *
408
-     * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
409
-     */
410
-    public function set_rate_limit($batch_completed)
411
-    {
412
-        //first get the most up to date rate limit (in case its expired and reset)
413
-        $rate_limit = $this->get_rate_limit();
414
-        $new_limit  = $rate_limit - $batch_completed;
415
-        //updating the transient option directly to avoid resetting the expiry.
416
-        update_option('_transient_' . $this->_get_rate_limit_key(), $new_limit);
417
-    }
418
-
419
-
420
-    /**
421
-     * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
422
-     * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
423
-     * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
424
-     * request running on a queue for the given task.
425
-     *
426
-     * @param string $task     This indicates what type of request is going to be initiated.
427
-     * @param int    $priority This indicates the priority that triggers initiating the request.
428
-     */
429
-    public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
430
-    {
431
-        //determine what status is matched with the priority as part of the trigger conditions.
432
-        $status = $task == 'generate'
433
-            ? EEM_Message::status_incomplete
434
-            : EEM_Message::instance()->stati_indicating_to_send();
435
-        // always make sure we save because either this will get executed immediately on a separate request
436
-        // or remains in the queue for the regularly scheduled queue batch.
437
-        $this->save();
438
-        /**
439
-         * This filter/option allows users to override processing of messages on separate requests and instead have everything
440
-         * happen on the same request.  If this is utilized remember:
441
-         * - message priorities don't matter
442
-         * - existing unprocessed messages in the queue will not get processed unless manually triggered.
443
-         * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
444
-         *   processing happening on the same request.
445
-         * - any race condition protection (locks) are removed because they don't apply when things are processed on
446
-         *   the same request.
447
-         */
448
-        if (
449
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
450
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
451
-        ) {
452
-            $messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
453
-            if ($messages_processor instanceof EE_Messages_Processor) {
454
-                return $messages_processor->process_immediately_from_queue($this);
455
-            }
456
-            //if we get here then that means the messages processor couldn't be loaded so messages will just remain
457
-            //queued for manual triggering by end user.
458
-        }
459
-
460
-        if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
461
-            EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
462
-        }
463
-    }
464
-
465
-
466
-    /**
467
-     *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
468
-     *
469
-     * @param   bool     $save                    Used to indicate whether to save the message queue after sending
470
-     *                                            (default will save).
471
-     * @param   mixed    $sending_messenger       (optional) When the sending messenger is different than
472
-     *                                            what is on the EE_Message object in the queue.
473
-     *                                            For instance, showing the browser view of an email message,
474
-     *                                            or giving a pdf generated view of an html document.
475
-     *                                            This should be an instance of EE_messenger but if you call this
476
-     *                                            method
477
-     *                                            intending it to be a sending messenger but a valid one could not be
478
-     *                                            retrieved then send in an instance of EE_Error that contains the
479
-     *                                            related error message.
480
-     * @param   bool|int $by_priority             When set, this indicates that only messages
481
-     *                                            matching the given priority should be executed.
482
-     * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
483
-     *                                            Also, if the messenger is an request type messenger (or a preview),
484
-     *                                            its entirely possible that the messenger will exit before
485
-     */
486
-    public function execute($save = true, $sending_messenger = null, $by_priority = false)
487
-    {
488
-        $messages_sent   = 0;
489
-        $this->_did_hook = array();
490
-        $this->_message_repository->rewind();
491
-
492
-        while ($this->_message_repository->valid()) {
493
-            $error_messages = array();
494
-            /** @type EE_Message $message */
495
-            $message = $this->_message_repository->current();
496
-            //only process things that are queued for sending
497
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
498
-                $this->_message_repository->next();
499
-                continue;
500
-            }
501
-            //if $by_priority is set and does not match then continue;
502
-            if ($by_priority && $by_priority != $message->priority()) {
503
-                $this->_message_repository->next();
504
-                continue;
505
-            }
506
-            //error checking
507
-            if (! $message->valid_messenger()) {
508
-                $error_messages[] = sprintf(
509
-                    __('The %s messenger is not active at time of sending.', 'event_espresso'),
510
-                    $message->messenger()
511
-                );
512
-            }
513
-            if (! $message->valid_message_type()) {
514
-                $error_messages[] = sprintf(
515
-                    __('The %s message type is not active at the time of sending.', 'event_espresso'),
516
-                    $message->message_type()
517
-                );
518
-            }
519
-            // if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
520
-            // then it will instead be an EE_Error object, so let's check for that
521
-            if ($sending_messenger instanceof EE_Error) {
522
-                $error_messages[] = $sending_messenger->getMessage();
523
-            }
524
-            // if there are no errors, then let's process the message
525
-            if (empty($error_messages)) {
526
-                if ($save) {
527
-                    $message->set_messenger_is_executing();
528
-                }
529
-                if ($this->_process_message($message, $sending_messenger)) {
530
-                    $messages_sent++;
531
-                }
532
-            }
533
-            $this->_set_error_message($message, $error_messages);
534
-            //add modified time
535
-            $message->set_modified(time());
536
-            //we save each message after its processed to make sure its status persists in case PHP times-out or runs
537
-            //out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
538
-            if ($save) {
539
-                $message->save();
540
-            }
541
-
542
-            $this->_message_repository->next();
543
-        }
544
-        if ($save) {
545
-            $this->save(true);
546
-        }
547
-        return $messages_sent;
548
-    }
549
-
550
-
551
-    /**
552
-     * _process_message
553
-     *
554
-     * @param EE_Message $message
555
-     * @param mixed      $sending_messenger (optional)
556
-     * @return bool
557
-     */
558
-    protected function _process_message(EE_Message $message, $sending_messenger = null)
559
-    {
560
-        // these *should* have been validated in the execute() method above
561
-        $messenger    = $message->messenger_object();
562
-        $message_type = $message->message_type_object();
563
-        //do actions for sending messenger if it differs from generating messenger and swap values.
564
-        if (
565
-            $sending_messenger instanceof EE_messenger
566
-            && $messenger instanceof EE_messenger
567
-            && $sending_messenger->name != $messenger->name
568
-        ) {
569
-            $messenger->do_secondary_messenger_hooks($sending_messenger->name);
570
-            $messenger = $sending_messenger;
571
-        }
572
-        // send using messenger, but double check objects
573
-        if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
574
-            //set hook for message type (but only if not using another messenger to send).
575
-            if ( ! isset($this->_did_hook[$message_type->name])) {
576
-                $message_type->do_messenger_hooks($messenger);
577
-                $this->_did_hook[$message_type->name] = 1;
578
-            }
579
-            //if preview then use preview method
580
-            return $this->_message_repository->is_preview()
581
-                ? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
582
-                : $this->_do_send($message, $messenger, $message_type);
583
-        }
584
-        return false;
585
-    }
586
-
587
-
588
-    /**
589
-     * The intention of this method is to count how many EE_Message objects
590
-     * are in the queue with a given status.
591
-     * Example usage:
592
-     * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
593
-     * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
594
-     *
595
-     * @param array $status Stati to check for in queue
596
-     * @return int  Count of EE_Message's matching the given status.
597
-     */
598
-    public function count_STS_in_queue($status)
599
-    {
600
-        $count  = 0;
601
-        $status = is_array($status) ? $status : array($status);
602
-        $this->_message_repository->rewind();
603
-        foreach ($this->_message_repository as $message) {
604
-            if (in_array($message->STS_ID(), $status)) {
605
-                $count++;
606
-            }
607
-        }
608
-        return $count;
609
-    }
610
-
611
-
612
-    /**
613
-     * Executes the get_preview method on the provided messenger.
614
-     *
615
-     * @param EE_Message      $message
616
-     * @param EE_messenger    $messenger
617
-     * @param EE_message_type $message_type
618
-     * @param                 $test_send
619
-     * @return bool   true means all went well, false means, not so much.
620
-     */
621
-    protected function _do_preview(
622
-        EE_Message $message,
623
-        EE_messenger $messenger,
624
-        EE_message_type $message_type,
625
-        $test_send
626
-    ) {
627
-        if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
628
-            if ( ! $test_send) {
629
-                $message->set_content($preview);
630
-            }
631
-            $message->set_STS_ID(EEM_Message::status_sent);
632
-            return true;
633
-        } else {
634
-            $message->set_STS_ID(EEM_Message::status_failed);
635
-            return false;
636
-        }
637
-    }
638
-
639
-
640
-    /**
641
-     * Executes the send method on the provided messenger
642
-     * EE_Messengers are expected to:
643
-     * - return true if the send was successful.
644
-     * - return false if the send was unsuccessful but can be tried again.
645
-     * - throw an Exception if the send was unsuccessful and cannot be tried again.
646
-     *
647
-     * @param EE_Message      $message
648
-     * @param EE_messenger    $messenger
649
-     * @param EE_message_type $message_type
650
-     * @return bool true means all went well, false means, not so much.
651
-     */
652
-    protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
653
-    {
654
-        try {
655
-            if ($messenger->send_message($message, $message_type)) {
656
-                $message->set_STS_ID(EEM_Message::status_sent);
657
-                return true;
658
-            } else {
659
-                $message->set_STS_ID(EEM_Message::status_retry);
660
-                return false;
661
-            }
662
-        } catch (SendMessageException $e) {
663
-            $message->set_STS_ID(EEM_Message::status_failed);
664
-            $message->set_error_message($e->getMessage());
665
-            return false;
666
-        }
667
-    }
668
-
669
-
670
-    /**
671
-     * This sets any necessary error messages on the message object and its status to failed.
672
-     *
673
-     * @param EE_Message $message
674
-     * @param array      $error_messages the response from the messenger.
675
-     */
676
-    protected function _set_error_message(EE_Message $message, $error_messages)
677
-    {
678
-        $error_messages = (array)$error_messages;
679
-        if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
680
-            $notices          = EE_Error::has_notices();
681
-            $error_messages[] = __(
682
-                'Messenger and Message Type were valid and active, but the messenger send method failed.',
683
-                'event_espresso'
684
-            );
685
-            if ($notices === 1) {
686
-                $notices           = EE_Error::get_vanilla_notices();
687
-                $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array();
688
-                $error_messages[]  = implode("\n", $notices['errors']);
689
-            }
690
-        }
691
-        if (count($error_messages) > 0) {
692
-            $msg = __('Message was not executed successfully.', 'event_espresso');
693
-            $msg = $msg . "\n" . implode("\n", $error_messages);
694
-            $message->set_error_message($msg);
695
-        }
696
-    }
21
+	/**
22
+	 * @type    string  reference for sending action
23
+	 */
24
+	const action_sending = 'sending';
25
+
26
+	/**
27
+	 * @type    string  reference for generation action
28
+	 */
29
+	const action_generating = 'generation';
30
+
31
+
32
+	/**
33
+	 * @type EE_Message_Repository $_message_repository
34
+	 */
35
+	protected $_message_repository;
36
+
37
+	/**
38
+	 * Sets the limit of how many messages are generated per process.
39
+	 *
40
+	 * @type int
41
+	 */
42
+	protected $_batch_count;
43
+
44
+	/**
45
+	 * Sets the limit of how many messages can be sent per hour.
46
+	 *
47
+	 * @type int
48
+	 */
49
+	protected $_rate_limit;
50
+
51
+	/**
52
+	 * This is an array of cached queue items being stored in this object.
53
+	 * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
54
+	 * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
55
+	 *
56
+	 * @type EE_Message[]
57
+	 */
58
+	protected $_cached_queue_items;
59
+
60
+	/**
61
+	 * Tracks the number of unsaved queue items.
62
+	 *
63
+	 * @type int
64
+	 */
65
+	protected $_unsaved_count = 0;
66
+
67
+	/**
68
+	 * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
69
+	 * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
70
+	 *
71
+	 * @type array
72
+	 */
73
+	protected $_did_hook = array();
74
+
75
+
76
+	/**
77
+	 * Constructor.
78
+	 * Setup all the initial properties and load a EE_Message_Repository.
79
+	 *
80
+	 * @param \EE_Message_Repository $message_repository
81
+	 */
82
+	public function __construct(EE_Message_Repository $message_repository)
83
+	{
84
+		$this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
85
+		$this->_rate_limit         = $this->get_rate_limit();
86
+		$this->_message_repository = $message_repository;
87
+	}
88
+
89
+
90
+	/**
91
+	 * Add a EE_Message object to the queue
92
+	 *
93
+	 * @param EE_Message $message
94
+	 * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
95
+	 *                                 object is persisted, this data will be saved on an extra_meta object related to
96
+	 *                                 EE_Message.
97
+	 * @param  bool      $preview      Whether this EE_Message represents a preview or not.
98
+	 * @param  bool      $test_send    This indicates whether to do a test send instead of actual send. A test send will
99
+	 *                                 use the messenger send method but typically is based on preview data.
100
+	 * @return bool          Whether the message was successfully added to the repository or not.
101
+	 */
102
+	public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false)
103
+	{
104
+		$data['preview']   = $preview;
105
+		$data['test_send'] = $test_send;
106
+		return $this->_message_repository->add($message, $data);
107
+	}
108
+
109
+
110
+	/**
111
+	 * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
112
+	 *
113
+	 * @param EE_Message $message The message to detach from the queue
114
+	 * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
115
+	 * @return bool
116
+	 */
117
+	public function remove(EE_Message $message, $persist = false)
118
+	{
119
+		if ($persist && $this->_message_repository->current() !== $message) {
120
+			//get pointer on right message
121
+			if ($this->_message_repository->has($message)) {
122
+				$this->_message_repository->rewind();
123
+				while ($this->_message_repository->valid()) {
124
+					if ($this->_message_repository->current() === $message) {
125
+						break;
126
+					}
127
+					$this->_message_repository->next();
128
+				}
129
+			} else {
130
+				return false;
131
+			}
132
+		}
133
+		return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
134
+	}
135
+
136
+
137
+	/**
138
+	 * Persists all queued EE_Message objects to the db.
139
+	 *
140
+	 * @param bool $do_hooks_only       @see EE_Message_Repository::saveAll
141
+	 * @return array @see EE_Messages_Repository::saveAll() for return values.
142
+	 */
143
+	public function save($do_hooks_only = false)
144
+	{
145
+		return $this->_message_repository->saveAll($do_hooks_only);
146
+	}
147
+
148
+
149
+	/**
150
+	 * @return EE_Message_Repository
151
+	 */
152
+	public function get_message_repository()
153
+	{
154
+		return $this->_message_repository;
155
+	}
156
+
157
+
158
+	/**
159
+	 * This does the following things:
160
+	 * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
161
+	 * false).
162
+	 * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
163
+	 * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
164
+	 * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
165
+	 * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
166
+	 * removed.
167
+	 *
168
+	 * @return bool  true if successfully retrieved batch, false no batch ready.
169
+	 */
170
+	public function get_batch_to_generate()
171
+	{
172
+		if ($this->is_locked(EE_Messages_Queue::action_generating)) {
173
+			return false;
174
+		}
175
+
176
+		//lock batch generation to prevent race conditions.
177
+		$this->lock_queue(EE_Messages_Queue::action_generating);
178
+
179
+		$query_args = array(
180
+			// key 0 = where conditions
181
+			0          => array('STS_ID' => EEM_Message::status_incomplete),
182
+			'order_by' => $this->_get_priority_orderby(),
183
+			'limit'    => $this->_batch_count,
184
+		);
185
+		$messages   = EEM_Message::instance()->get_all($query_args);
186
+
187
+		if ( ! $messages) {
188
+			return false; //nothing to generate
189
+		}
190
+
191
+		foreach ($messages as $message) {
192
+			if ($message instanceof EE_Message) {
193
+				$data = $message->all_extra_meta_array();
194
+				$this->add($message, $data);
195
+			}
196
+		}
197
+		return true;
198
+	}
199
+
200
+
201
+	/**
202
+	 * This does the following things:
203
+	 * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
204
+	 * false).
205
+	 * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
206
+	 * return false.
207
+	 * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
208
+	 * 3. On success or unsuccessful send, sets status appropriately.
209
+	 * 4. Saves messages via the queue
210
+	 * 5. Releases lock.
211
+	 *
212
+	 * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
213
+	 *               necessarily mean that all messages were successfully sent.  It just means that this method
214
+	 *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
215
+	 *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
216
+	 *               will also have a saved error message on it to assist with notifying user.
217
+	 */
218
+	public function get_to_send_batch_and_send()
219
+	{
220
+		if ($this->is_locked(EE_Messages_Queue::action_sending) || $this->_rate_limit < 1) {
221
+			return false;
222
+		}
223
+
224
+		$this->lock_queue(EE_Messages_Queue::action_sending);
225
+
226
+		$batch = $this->_batch_count < $this->_rate_limit ? $this->_batch_count : $this->_rate_limit;
227
+
228
+		$query_args = array(
229
+			// key 0 = where conditions
230
+			0          => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())),
231
+			'order_by' => $this->_get_priority_orderby(),
232
+			'limit'    => $batch,
233
+		);
234
+
235
+		$messages_to_send = EEM_Message::instance()->get_all($query_args);
236
+
237
+
238
+		//any to send?
239
+		if ( ! $messages_to_send) {
240
+			$this->unlock_queue(EE_Messages_Queue::action_sending);
241
+			return false;
242
+		}
243
+
244
+		//add to queue.
245
+		foreach ($messages_to_send as $message) {
246
+			if ($message instanceof EE_Message) {
247
+				$this->add($message);
248
+			}
249
+		}
250
+
251
+		//send messages  (this also updates the rate limit)
252
+		$this->execute();
253
+
254
+		//release lock
255
+		$this->unlock_queue(EE_Messages_Queue::action_sending);
256
+		return true;
257
+	}
258
+
259
+
260
+	/**
261
+	 * Locks the queue so that no other queues can call the "batch" methods.
262
+	 *
263
+	 * @param   string $type The type of queue being locked.
264
+	 */
265
+	public function lock_queue($type = EE_Messages_Queue::action_generating)
266
+	{
267
+		set_transient($this->_get_lock_key($type), 1, $this->_get_lock_expiry($type));
268
+	}
269
+
270
+
271
+	/**
272
+	 * Unlocks the queue so that batch methods can be used.
273
+	 *
274
+	 * @param   string $type The type of queue being unlocked.
275
+	 */
276
+	public function unlock_queue($type = EE_Messages_Queue::action_generating)
277
+	{
278
+		delete_transient($this->_get_lock_key($type));
279
+	}
280
+
281
+
282
+	/**
283
+	 * Retrieve the key used for the lock transient.
284
+	 *
285
+	 * @param string $type The type of lock.
286
+	 * @return string
287
+	 */
288
+	protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
289
+	{
290
+		return '_ee_lock_' . $type;
291
+	}
292
+
293
+
294
+	/**
295
+	 * Retrieve the expiry time for the lock transient.
296
+	 *
297
+	 * @param string $type The type of lock
298
+	 * @return int   time to expiry in seconds.
299
+	 */
300
+	protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
301
+	{
302
+		return (int)apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
303
+	}
304
+
305
+
306
+	/**
307
+	 * Returns the key used for rate limit transient.
308
+	 *
309
+	 * @return string
310
+	 */
311
+	protected function _get_rate_limit_key()
312
+	{
313
+		return '_ee_rate_limit';
314
+	}
315
+
316
+
317
+	/**
318
+	 * Returns the rate limit expiry time.
319
+	 *
320
+	 * @return int
321
+	 */
322
+	protected function _get_rate_limit_expiry()
323
+	{
324
+		return (int)apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
325
+	}
326
+
327
+
328
+	/**
329
+	 * Returns the default rate limit for sending messages.
330
+	 *
331
+	 * @return int
332
+	 */
333
+	protected function _default_rate_limit()
334
+	{
335
+		return (int)apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
336
+	}
337
+
338
+
339
+	/**
340
+	 * Return the orderby array for priority.
341
+	 *
342
+	 * @return array
343
+	 */
344
+	protected function _get_priority_orderby()
345
+	{
346
+		return array(
347
+			'MSG_priority' => 'ASC',
348
+			'MSG_modified' => 'DESC',
349
+		);
350
+	}
351
+
352
+
353
+	/**
354
+	 * Returns whether batch methods are "locked" or not.
355
+	 *
356
+	 * @param  string $type The type of lock being checked for.
357
+	 * @return bool
358
+	 */
359
+	public function is_locked($type = EE_Messages_Queue::action_generating)
360
+	{
361
+		/**
362
+		 * This filters the default is_locked behaviour.
363
+		 */
364
+		$is_locked = filter_var(
365
+			apply_filters(
366
+				'FHEE__EE_Messages_Queue__is_locked',
367
+				get_transient($this->_get_lock_key($type)),
368
+				$this
369
+			),
370
+			FILTER_VALIDATE_BOOLEAN
371
+		);
372
+
373
+		/**
374
+		 * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
375
+		 *            Also implemented here because messages processed on the same request should not have any locks applied.
376
+		 */
377
+		if (
378
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
379
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
380
+		) {
381
+			$is_locked = false;
382
+		}
383
+
384
+
385
+		return $is_locked;
386
+	}
387
+
388
+
389
+	/**
390
+	 * Retrieves the rate limit that may be cached as a transient.
391
+	 * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
392
+	 *
393
+	 * @return int
394
+	 */
395
+	public function get_rate_limit()
396
+	{
397
+		if ( ! $rate_limit = get_transient($this->_get_rate_limit_key())) {
398
+			$rate_limit = $this->_default_rate_limit();
399
+			set_transient($this->_get_rate_limit_key(), $rate_limit, $this->_get_rate_limit_key());
400
+		}
401
+		return $rate_limit;
402
+	}
403
+
404
+
405
+	/**
406
+	 * This updates existing rate limit with the new limit which is the old minus the batch.
407
+	 *
408
+	 * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
409
+	 */
410
+	public function set_rate_limit($batch_completed)
411
+	{
412
+		//first get the most up to date rate limit (in case its expired and reset)
413
+		$rate_limit = $this->get_rate_limit();
414
+		$new_limit  = $rate_limit - $batch_completed;
415
+		//updating the transient option directly to avoid resetting the expiry.
416
+		update_option('_transient_' . $this->_get_rate_limit_key(), $new_limit);
417
+	}
418
+
419
+
420
+	/**
421
+	 * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
422
+	 * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
423
+	 * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
424
+	 * request running on a queue for the given task.
425
+	 *
426
+	 * @param string $task     This indicates what type of request is going to be initiated.
427
+	 * @param int    $priority This indicates the priority that triggers initiating the request.
428
+	 */
429
+	public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
430
+	{
431
+		//determine what status is matched with the priority as part of the trigger conditions.
432
+		$status = $task == 'generate'
433
+			? EEM_Message::status_incomplete
434
+			: EEM_Message::instance()->stati_indicating_to_send();
435
+		// always make sure we save because either this will get executed immediately on a separate request
436
+		// or remains in the queue for the regularly scheduled queue batch.
437
+		$this->save();
438
+		/**
439
+		 * This filter/option allows users to override processing of messages on separate requests and instead have everything
440
+		 * happen on the same request.  If this is utilized remember:
441
+		 * - message priorities don't matter
442
+		 * - existing unprocessed messages in the queue will not get processed unless manually triggered.
443
+		 * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
444
+		 *   processing happening on the same request.
445
+		 * - any race condition protection (locks) are removed because they don't apply when things are processed on
446
+		 *   the same request.
447
+		 */
448
+		if (
449
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
450
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
451
+		) {
452
+			$messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
453
+			if ($messages_processor instanceof EE_Messages_Processor) {
454
+				return $messages_processor->process_immediately_from_queue($this);
455
+			}
456
+			//if we get here then that means the messages processor couldn't be loaded so messages will just remain
457
+			//queued for manual triggering by end user.
458
+		}
459
+
460
+		if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
461
+			EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
462
+		}
463
+	}
464
+
465
+
466
+	/**
467
+	 *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
468
+	 *
469
+	 * @param   bool     $save                    Used to indicate whether to save the message queue after sending
470
+	 *                                            (default will save).
471
+	 * @param   mixed    $sending_messenger       (optional) When the sending messenger is different than
472
+	 *                                            what is on the EE_Message object in the queue.
473
+	 *                                            For instance, showing the browser view of an email message,
474
+	 *                                            or giving a pdf generated view of an html document.
475
+	 *                                            This should be an instance of EE_messenger but if you call this
476
+	 *                                            method
477
+	 *                                            intending it to be a sending messenger but a valid one could not be
478
+	 *                                            retrieved then send in an instance of EE_Error that contains the
479
+	 *                                            related error message.
480
+	 * @param   bool|int $by_priority             When set, this indicates that only messages
481
+	 *                                            matching the given priority should be executed.
482
+	 * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
483
+	 *                                            Also, if the messenger is an request type messenger (or a preview),
484
+	 *                                            its entirely possible that the messenger will exit before
485
+	 */
486
+	public function execute($save = true, $sending_messenger = null, $by_priority = false)
487
+	{
488
+		$messages_sent   = 0;
489
+		$this->_did_hook = array();
490
+		$this->_message_repository->rewind();
491
+
492
+		while ($this->_message_repository->valid()) {
493
+			$error_messages = array();
494
+			/** @type EE_Message $message */
495
+			$message = $this->_message_repository->current();
496
+			//only process things that are queued for sending
497
+			if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
498
+				$this->_message_repository->next();
499
+				continue;
500
+			}
501
+			//if $by_priority is set and does not match then continue;
502
+			if ($by_priority && $by_priority != $message->priority()) {
503
+				$this->_message_repository->next();
504
+				continue;
505
+			}
506
+			//error checking
507
+			if (! $message->valid_messenger()) {
508
+				$error_messages[] = sprintf(
509
+					__('The %s messenger is not active at time of sending.', 'event_espresso'),
510
+					$message->messenger()
511
+				);
512
+			}
513
+			if (! $message->valid_message_type()) {
514
+				$error_messages[] = sprintf(
515
+					__('The %s message type is not active at the time of sending.', 'event_espresso'),
516
+					$message->message_type()
517
+				);
518
+			}
519
+			// if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
520
+			// then it will instead be an EE_Error object, so let's check for that
521
+			if ($sending_messenger instanceof EE_Error) {
522
+				$error_messages[] = $sending_messenger->getMessage();
523
+			}
524
+			// if there are no errors, then let's process the message
525
+			if (empty($error_messages)) {
526
+				if ($save) {
527
+					$message->set_messenger_is_executing();
528
+				}
529
+				if ($this->_process_message($message, $sending_messenger)) {
530
+					$messages_sent++;
531
+				}
532
+			}
533
+			$this->_set_error_message($message, $error_messages);
534
+			//add modified time
535
+			$message->set_modified(time());
536
+			//we save each message after its processed to make sure its status persists in case PHP times-out or runs
537
+			//out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
538
+			if ($save) {
539
+				$message->save();
540
+			}
541
+
542
+			$this->_message_repository->next();
543
+		}
544
+		if ($save) {
545
+			$this->save(true);
546
+		}
547
+		return $messages_sent;
548
+	}
549
+
550
+
551
+	/**
552
+	 * _process_message
553
+	 *
554
+	 * @param EE_Message $message
555
+	 * @param mixed      $sending_messenger (optional)
556
+	 * @return bool
557
+	 */
558
+	protected function _process_message(EE_Message $message, $sending_messenger = null)
559
+	{
560
+		// these *should* have been validated in the execute() method above
561
+		$messenger    = $message->messenger_object();
562
+		$message_type = $message->message_type_object();
563
+		//do actions for sending messenger if it differs from generating messenger and swap values.
564
+		if (
565
+			$sending_messenger instanceof EE_messenger
566
+			&& $messenger instanceof EE_messenger
567
+			&& $sending_messenger->name != $messenger->name
568
+		) {
569
+			$messenger->do_secondary_messenger_hooks($sending_messenger->name);
570
+			$messenger = $sending_messenger;
571
+		}
572
+		// send using messenger, but double check objects
573
+		if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
574
+			//set hook for message type (but only if not using another messenger to send).
575
+			if ( ! isset($this->_did_hook[$message_type->name])) {
576
+				$message_type->do_messenger_hooks($messenger);
577
+				$this->_did_hook[$message_type->name] = 1;
578
+			}
579
+			//if preview then use preview method
580
+			return $this->_message_repository->is_preview()
581
+				? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
582
+				: $this->_do_send($message, $messenger, $message_type);
583
+		}
584
+		return false;
585
+	}
586
+
587
+
588
+	/**
589
+	 * The intention of this method is to count how many EE_Message objects
590
+	 * are in the queue with a given status.
591
+	 * Example usage:
592
+	 * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
593
+	 * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
594
+	 *
595
+	 * @param array $status Stati to check for in queue
596
+	 * @return int  Count of EE_Message's matching the given status.
597
+	 */
598
+	public function count_STS_in_queue($status)
599
+	{
600
+		$count  = 0;
601
+		$status = is_array($status) ? $status : array($status);
602
+		$this->_message_repository->rewind();
603
+		foreach ($this->_message_repository as $message) {
604
+			if (in_array($message->STS_ID(), $status)) {
605
+				$count++;
606
+			}
607
+		}
608
+		return $count;
609
+	}
610
+
611
+
612
+	/**
613
+	 * Executes the get_preview method on the provided messenger.
614
+	 *
615
+	 * @param EE_Message      $message
616
+	 * @param EE_messenger    $messenger
617
+	 * @param EE_message_type $message_type
618
+	 * @param                 $test_send
619
+	 * @return bool   true means all went well, false means, not so much.
620
+	 */
621
+	protected function _do_preview(
622
+		EE_Message $message,
623
+		EE_messenger $messenger,
624
+		EE_message_type $message_type,
625
+		$test_send
626
+	) {
627
+		if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
628
+			if ( ! $test_send) {
629
+				$message->set_content($preview);
630
+			}
631
+			$message->set_STS_ID(EEM_Message::status_sent);
632
+			return true;
633
+		} else {
634
+			$message->set_STS_ID(EEM_Message::status_failed);
635
+			return false;
636
+		}
637
+	}
638
+
639
+
640
+	/**
641
+	 * Executes the send method on the provided messenger
642
+	 * EE_Messengers are expected to:
643
+	 * - return true if the send was successful.
644
+	 * - return false if the send was unsuccessful but can be tried again.
645
+	 * - throw an Exception if the send was unsuccessful and cannot be tried again.
646
+	 *
647
+	 * @param EE_Message      $message
648
+	 * @param EE_messenger    $messenger
649
+	 * @param EE_message_type $message_type
650
+	 * @return bool true means all went well, false means, not so much.
651
+	 */
652
+	protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
653
+	{
654
+		try {
655
+			if ($messenger->send_message($message, $message_type)) {
656
+				$message->set_STS_ID(EEM_Message::status_sent);
657
+				return true;
658
+			} else {
659
+				$message->set_STS_ID(EEM_Message::status_retry);
660
+				return false;
661
+			}
662
+		} catch (SendMessageException $e) {
663
+			$message->set_STS_ID(EEM_Message::status_failed);
664
+			$message->set_error_message($e->getMessage());
665
+			return false;
666
+		}
667
+	}
668
+
669
+
670
+	/**
671
+	 * This sets any necessary error messages on the message object and its status to failed.
672
+	 *
673
+	 * @param EE_Message $message
674
+	 * @param array      $error_messages the response from the messenger.
675
+	 */
676
+	protected function _set_error_message(EE_Message $message, $error_messages)
677
+	{
678
+		$error_messages = (array)$error_messages;
679
+		if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
680
+			$notices          = EE_Error::has_notices();
681
+			$error_messages[] = __(
682
+				'Messenger and Message Type were valid and active, but the messenger send method failed.',
683
+				'event_espresso'
684
+			);
685
+			if ($notices === 1) {
686
+				$notices           = EE_Error::get_vanilla_notices();
687
+				$notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array();
688
+				$error_messages[]  = implode("\n", $notices['errors']);
689
+			}
690
+		}
691
+		if (count($error_messages) > 0) {
692
+			$msg = __('Message was not executed successfully.', 'event_espresso');
693
+			$msg = $msg . "\n" . implode("\n", $error_messages);
694
+			$message->set_error_message($msg);
695
+		}
696
+	}
697 697
 
698 698
 } //end EE_Messages_Queue class
699 699
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 use \EventEspresso\core\exceptions\SendMessageException;
3 3
 
4
-if (! defined('EVENT_ESPRESSO_VERSION')) {
4
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5 5
     exit('No direct script access allowed');
6 6
 }
7 7
 
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
             'order_by' => $this->_get_priority_orderby(),
183 183
             'limit'    => $this->_batch_count,
184 184
         );
185
-        $messages   = EEM_Message::instance()->get_all($query_args);
185
+        $messages = EEM_Message::instance()->get_all($query_args);
186 186
 
187 187
         if ( ! $messages) {
188 188
             return false; //nothing to generate
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
      */
288 288
     protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
289 289
     {
290
-        return '_ee_lock_' . $type;
290
+        return '_ee_lock_'.$type;
291 291
     }
292 292
 
293 293
 
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
      */
300 300
     protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
301 301
     {
302
-        return (int)apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
302
+        return (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
303 303
     }
304 304
 
305 305
 
@@ -321,7 +321,7 @@  discard block
 block discarded – undo
321 321
      */
322 322
     protected function _get_rate_limit_expiry()
323 323
     {
324
-        return (int)apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
324
+        return (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
325 325
     }
326 326
 
327 327
 
@@ -332,7 +332,7 @@  discard block
 block discarded – undo
332 332
      */
333 333
     protected function _default_rate_limit()
334 334
     {
335
-        return (int)apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
335
+        return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
336 336
     }
337 337
 
338 338
 
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
         $rate_limit = $this->get_rate_limit();
414 414
         $new_limit  = $rate_limit - $batch_completed;
415 415
         //updating the transient option directly to avoid resetting the expiry.
416
-        update_option('_transient_' . $this->_get_rate_limit_key(), $new_limit);
416
+        update_option('_transient_'.$this->_get_rate_limit_key(), $new_limit);
417 417
     }
418 418
 
419 419
 
@@ -494,7 +494,7 @@  discard block
 block discarded – undo
494 494
             /** @type EE_Message $message */
495 495
             $message = $this->_message_repository->current();
496 496
             //only process things that are queued for sending
497
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
497
+            if ( ! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
498 498
                 $this->_message_repository->next();
499 499
                 continue;
500 500
             }
@@ -504,13 +504,13 @@  discard block
 block discarded – undo
504 504
                 continue;
505 505
             }
506 506
             //error checking
507
-            if (! $message->valid_messenger()) {
507
+            if ( ! $message->valid_messenger()) {
508 508
                 $error_messages[] = sprintf(
509 509
                     __('The %s messenger is not active at time of sending.', 'event_espresso'),
510 510
                     $message->messenger()
511 511
                 );
512 512
             }
513
-            if (! $message->valid_message_type()) {
513
+            if ( ! $message->valid_message_type()) {
514 514
                 $error_messages[] = sprintf(
515 515
                     __('The %s message type is not active at the time of sending.', 'event_espresso'),
516 516
                     $message->message_type()
@@ -675,7 +675,7 @@  discard block
 block discarded – undo
675 675
      */
676 676
     protected function _set_error_message(EE_Message $message, $error_messages)
677 677
     {
678
-        $error_messages = (array)$error_messages;
678
+        $error_messages = (array) $error_messages;
679 679
         if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
680 680
             $notices          = EE_Error::has_notices();
681 681
             $error_messages[] = __(
@@ -690,7 +690,7 @@  discard block
 block discarded – undo
690 690
         }
691 691
         if (count($error_messages) > 0) {
692 692
             $msg = __('Message was not executed successfully.', 'event_espresso');
693
-            $msg = $msg . "\n" . implode("\n", $error_messages);
693
+            $msg = $msg."\n".implode("\n", $error_messages);
694 694
             $message->set_error_message($msg);
695 695
         }
696 696
     }
Please login to merge, or discard this patch.
core/db_classes/EE_Message.class.php 2 patches
Indentation   +856 added lines, -856 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
 /**
@@ -12,865 +12,865 @@  discard block
 block discarded – undo
12 12
 class EE_Message extends EE_Base_Class implements EEI_Admin_Links
13 13
 {
14 14
 
15
-    /**
16
-     * @deprecated 4.9.0  Added for backward compat with add-on's
17
-     * @type null
18
-     */
19
-    public $template_pack;
20
-
21
-    /**
22
-     * @deprecated 4.9.0 Added for backward compat with add-on's
23
-     * @type null
24
-     */
25
-    public $template_variation;
26
-
27
-    /**
28
-     * @deprecated 4.9.0 Added for backward compat with add-on's
29
-     * @type string
30
-     */
31
-    public $content = '';
32
-
33
-
34
-    /**
35
-     * @type EE_messenger $_messenger
36
-     */
37
-    protected $_messenger = null;
38
-
39
-    /**
40
-     * @type EE_message_type $_message_type
41
-     */
42
-    protected $_message_type = null;
43
-
44
-
45
-    /**
46
-     * @param array  $props_n_values
47
-     * @param string $timezone
48
-     * @param array  $date_formats incoming date formats in an array.  First value is the date_format, second is time
49
-     *                             format.
50
-     * @return EE_Message
51
-     */
52
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
53
-    {
54
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
55
-        //if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
56
-        if ( ! $has_object) {
57
-            EE_Registry::instance()->load_helper('URL');
58
-            $props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
59
-        }
60
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
61
-    }
62
-
63
-
64
-    /**
65
-     * @param array  $props_n_values
66
-     * @param string $timezone
67
-     * @return EE_Message
68
-     */
69
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
70
-    {
71
-        return new self($props_n_values, true, $timezone);
72
-    }
73
-
74
-
75
-    /**
76
-     * Gets MSG_token
77
-     *
78
-     * @return int
79
-     */
80
-    public function MSG_token()
81
-    {
82
-        return $this->get('MSG_token');
83
-    }
84
-
85
-
86
-    /**
87
-     * Sets MSG_token
88
-     *
89
-     * @param int $MSG_token
90
-     */
91
-    public function set_MSG_token($MSG_token)
92
-    {
93
-        $this->set('MSG_token', $MSG_token);
94
-    }
95
-
96
-
97
-    /**
98
-     * Gets GRP_ID
99
-     *
100
-     * @return int
101
-     */
102
-    public function GRP_ID()
103
-    {
104
-        return $this->get('GRP_ID');
105
-    }
106
-
107
-
108
-    /**
109
-     * Sets GRP_ID
110
-     *
111
-     * @param int $GRP_ID
112
-     */
113
-    public function set_GRP_ID($GRP_ID)
114
-    {
115
-        $this->set('GRP_ID', $GRP_ID);
116
-    }
117
-
118
-
119
-    /**
120
-     * Gets TXN_ID
121
-     *
122
-     * @return int
123
-     */
124
-    public function TXN_ID()
125
-    {
126
-        return $this->get('TXN_ID');
127
-    }
128
-
129
-
130
-    /**
131
-     * Sets TXN_ID
132
-     *
133
-     * @param int $TXN_ID
134
-     */
135
-    public function set_TXN_ID($TXN_ID)
136
-    {
137
-        $this->set('TXN_ID', $TXN_ID);
138
-    }
139
-
140
-
141
-    /**
142
-     * Gets messenger
143
-     *
144
-     * @return string
145
-     */
146
-    public function messenger()
147
-    {
148
-        return $this->get('MSG_messenger');
149
-    }
150
-
151
-
152
-    /**
153
-     * Sets messenger
154
-     *
155
-     * @param string $messenger
156
-     */
157
-    public function set_messenger($messenger)
158
-    {
159
-        $this->set('MSG_messenger', $messenger);
160
-    }
161
-
162
-
163
-    /**
164
-     * Returns corresponding messenger object for the set messenger on this message
165
-     *
166
-     * @return EE_messenger | null
167
-     */
168
-    public function messenger_object()
169
-    {
170
-        return $this->_messenger;
171
-    }
172
-
173
-
174
-    /**
175
-     * Sets messenger
176
-     *
177
-     * @param EE_messenger $messenger
178
-     */
179
-    public function set_messenger_object(EE_messenger $messenger)
180
-    {
181
-        $this->_messenger = $messenger;
182
-    }
183
-
184
-
185
-    /**
186
-     * validates messenger
187
-     *
188
-     * @param bool $throw_exceptions
189
-     * @return bool
190
-     * @throws \EE_Error
191
-     */
192
-    public function valid_messenger($throw_exceptions = false)
193
-    {
194
-        if ($this->_messenger instanceof EE_messenger) {
195
-            return true;
196
-        }
197
-        if ($throw_exceptions) {
198
-            throw new EE_Error(
199
-                sprintf(
200
-                    __(
201
-                        'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
202
-                        'event_espresso'
203
-                    ),
204
-                    $this->messenger()
205
-                )
206
-            );
207
-        }
208
-        return false;
209
-    }
210
-
211
-
212
-    /**
213
-     * This returns the set localized label for the messenger on this message.
214
-     * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved
215
-     * with this message.
216
-     *
217
-     * @param   bool $plural whether to return the plural label or not.
218
-     * @return string
219
-     */
220
-    public function messenger_label($plural = false)
221
-    {
222
-        $label_type = $plural ? 'plural' : 'singular';
223
-        $messenger  = $this->messenger_object();
224
-        return $messenger instanceof EE_messenger ? $messenger->label[$label_type] : $this->messenger();
225
-    }
226
-
227
-
228
-    /**
229
-     * Gets message_type
230
-     *
231
-     * @return string
232
-     */
233
-    public function message_type()
234
-    {
235
-        return $this->get('MSG_message_type');
236
-    }
237
-
238
-
239
-    /**
240
-     * Sets message_type
241
-     *
242
-     * @param string $message_type
243
-     */
244
-    public function set_message_type($message_type)
245
-    {
246
-        $this->set('MSG_message_type', $message_type);
247
-    }
248
-
249
-
250
-    /**
251
-     * Returns the message type object for the set message type on this message
252
-     *
253
-     * @return EE_message_type | null
254
-     */
255
-    public function message_type_object()
256
-    {
257
-        return $this->_message_type;
258
-    }
259
-
260
-
261
-    /**
262
-     * Sets message_type
263
-     *
264
-     * @param EE_message_type $message_type
265
-     * @param bool            $set_priority   This indicates whether to set the priority to whatever the priority is on
266
-     *                                        the message type or not.
267
-     */
268
-    public function set_message_type_object(EE_message_type $message_type, $set_priority = false)
269
-    {
270
-        $this->_message_type = $message_type;
271
-        if ($set_priority) {
272
-            $this->set_priority($this->_message_type->get_priority());
273
-        }
274
-    }
275
-
276
-
277
-    /**
278
-     * validates message_type
279
-     *
280
-     * @param bool $throw_exceptions
281
-     * @return bool
282
-     * @throws \EE_Error
283
-     */
284
-    public function valid_message_type($throw_exceptions = false)
285
-    {
286
-        if ($this->_message_type instanceof EE_message_type) {
287
-            return true;
288
-        }
289
-        if ($throw_exceptions) {
290
-            throw new EE_Error(
291
-                sprintf(
292
-                    __(
293
-                        'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
294
-                        'event_espresso'
295
-                    ),
296
-                    $this->message_type()
297
-                )
298
-            );
299
-        }
300
-        return false;
301
-    }
302
-
303
-
304
-    /**
305
-     * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects).
306
-     *
307
-     * @param bool $throw_exceptions
308
-     * @return bool
309
-     * @throws \EE_Error
310
-     */
311
-    public function is_valid($throw_exceptions = false)
312
-    {
313
-        if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) {
314
-            return true;
315
-        }
316
-        return false;
317
-    }
318
-
319
-
320
-    /**
321
-     * This validates whether the internal messenger and message type objects are valid for sending.
322
-     * Three checks are done:
323
-     * 1. There is a valid messenger object.
324
-     * 2. There is a valid message type object.
325
-     * 3. The message type object is active for the messenger.
326
-     *
327
-     * @throws EE_Error  But only if $throw_exceptions is set to true.
328
-     * @param bool $throw_exceptions
329
-     * @return bool
330
-     */
331
-    public function is_valid_for_sending_or_generation($throw_exceptions = false)
332
-    {
333
-        $valid = false;
334
-        if ($this->is_valid($throw_exceptions)) {
335
-            /** @var EE_Message_Resource_Manager $message_resource_manager */
336
-            $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
337
-            $valid                    = $message_resource_manager->is_message_type_active_for_messenger($this->messenger(),
338
-                $this->message_type());
339
-            if ( ! $valid && $throw_exceptions) {
340
-                throw new EE_Error(
341
-                    sprintf(
342
-                        __('The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.',
343
-                            'event_espresso'),
344
-                        $this->message_type(),
345
-                        $this->messenger()
346
-                    )
347
-                );
348
-            }
349
-        }
350
-        return $valid;
351
-    }
352
-
353
-
354
-    /**
355
-     * This returns the set localized label for the message type on this message.
356
-     * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved
357
-     * with this message.
358
-     *
359
-     * @param   bool $plural whether to return the plural label or not.
360
-     * @return string
361
-     */
362
-    public function message_type_label($plural = false)
363
-    {
364
-        $label_type   = $plural ? 'plural' : 'singular';
365
-        $message_type = $this->message_type_object();
366
-        return $message_type instanceof EE_message_type ? $message_type->label[$label_type] : $this->message_type();
367
-    }
368
-
369
-
370
-    /**
371
-     * Gets context
372
-     *
373
-     * @return string
374
-     */
375
-    public function context()
376
-    {
377
-        return $this->get('MSG_context');
378
-    }
379
-
380
-
381
-    /**
382
-     * This returns the corresponding localized label for the given context slug, if possible from installed message
383
-     * types. Otherwise, this will just return the set context slug on this object.
384
-     *
385
-     * @return string
386
-     */
387
-    public function context_label()
388
-    {
389
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
390
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
391
-        $contexts                 = $message_resource_manager->get_all_contexts();
392
-        return isset($contexts[$this->context()]) ? $contexts[$this->context()] : $this->context();
393
-    }
394
-
395
-
396
-    /**
397
-     * Sets context
398
-     *
399
-     * @param string $context
400
-     */
401
-    public function set_context($context)
402
-    {
403
-        $this->set('MSG_context', $context);
404
-    }
405
-
406
-
407
-    /**
408
-     * Gets recipient_ID
409
-     *
410
-     * @return int
411
-     */
412
-    public function recipient_ID()
413
-    {
414
-        return $this->get('MSG_recipient_ID');
415
-    }
416
-
417
-
418
-    /**
419
-     * Sets recipient_ID
420
-     *
421
-     * @param string $recipient_ID
422
-     */
423
-    public function set_recipient_ID($recipient_ID)
424
-    {
425
-        $this->set('MSG_recipient_ID', $recipient_ID);
426
-    }
427
-
428
-
429
-    /**
430
-     * Gets recipient_type
431
-     *
432
-     * @return string
433
-     */
434
-    public function recipient_type()
435
-    {
436
-        return $this->get('MSG_recipient_type');
437
-    }
438
-
439
-
440
-    /**
441
-     * Return the related object matching the recipient type and ID.
442
-     *
443
-     * @return EE_Base_Class | null
444
-     */
445
-    public function recipient_object()
446
-    {
447
-        if ( ! $this->recipient_type() || ! $this->recipient_ID()) {
448
-            return null;
449
-        }
450
-
451
-        return $this->get_first_related($this->recipient_type());
452
-    }
453
-
454
-
455
-    /**
456
-     * Sets recipient_type
457
-     *
458
-     * @param string $recipient_type
459
-     */
460
-    public function set_recipient_type($recipient_type)
461
-    {
462
-        $this->set('MSG_recipient_type', $recipient_type);
463
-    }
464
-
465
-
466
-    /**
467
-     * Gets content
468
-     *
469
-     * @return string
470
-     */
471
-    public function content()
472
-    {
473
-        return $this->get('MSG_content');
474
-    }
475
-
476
-
477
-    /**
478
-     * Sets content
479
-     *
480
-     * @param string $content
481
-     */
482
-    public function set_content($content)
483
-    {
484
-        $this->set('MSG_content', $content);
485
-    }
486
-
487
-
488
-    /**
489
-     * Gets subject
490
-     *
491
-     * @return string
492
-     */
493
-    public function subject()
494
-    {
495
-        return $this->get('MSG_subject');
496
-    }
497
-
498
-
499
-    /**
500
-     * Sets subject
501
-     *
502
-     * @param string $subject
503
-     */
504
-    public function set_subject($subject)
505
-    {
506
-        $this->set('MSG_subject', $subject);
507
-    }
508
-
509
-
510
-    /**
511
-     * Gets to
512
-     *
513
-     * @return string
514
-     */
515
-    public function to()
516
-    {
517
-        $to = $this->get('MSG_to');
518
-        return empty($to) ? __('No recipient', 'event_espresso') : $to;
519
-    }
520
-
521
-
522
-    /**
523
-     * Sets to
524
-     *
525
-     * @param string $to
526
-     */
527
-    public function set_to($to)
528
-    {
529
-        $this->set('MSG_to', $to);
530
-    }
531
-
532
-
533
-    /**
534
-     * Gets from
535
-     *
536
-     * @return string
537
-     */
538
-    public function from()
539
-    {
540
-        return $this->get('MSG_from');
541
-    }
542
-
543
-
544
-    /**
545
-     * Sets from
546
-     *
547
-     * @param string $from
548
-     */
549
-    public function set_from($from)
550
-    {
551
-        $this->set('MSG_from', $from);
552
-    }
553
-
554
-
555
-    /**
556
-     * Gets priority
557
-     *
558
-     * @return int
559
-     */
560
-    public function priority()
561
-    {
562
-        return $this->get('MSG_priority');
563
-    }
564
-
565
-
566
-    /**
567
-     * Sets priority
568
-     * Note.  Send Now Messengers always override any priority that may be set on a Message.  So
569
-     * this method calls the send_now method to verify that.
570
-     *
571
-     * @param int $priority
572
-     */
573
-    public function set_priority($priority)
574
-    {
575
-        $priority = $this->send_now() ? EEM_Message::priority_high : $priority;
576
-        parent::set('MSG_priority', $priority);
577
-    }
578
-
579
-
580
-    /**
581
-     * Overrides parent::set method so we can capture any sets for priority.
582
-     *
583
-     * @see parent::set() for phpdocs
584
-     * @param string $field_name
585
-     * @param mixed  $field_value
586
-     * @param bool   $use_default
587
-     * @throws EE_Error
588
-     */
589
-    public function set($field_name, $field_value, $use_default = false)
590
-    {
591
-        if ($field_name === 'MSG_priority') {
592
-            $this->set_priority($field_value);
593
-        }
594
-        parent::set($field_name, $field_value, $use_default);
595
-    }
596
-
597
-
598
-    /**
599
-     * @return bool
600
-     * @throws \EE_Error
601
-     */
602
-    public function send_now()
603
-    {
604
-        $send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high : $this->priority();
605
-        return $send_now === EEM_Message::priority_high ? true : false;
606
-    }
607
-
608
-
609
-    /**
610
-     * Gets STS_ID
611
-     *
612
-     * @return string
613
-     */
614
-    public function STS_ID()
615
-    {
616
-        return $this->get('STS_ID');
617
-    }
618
-
619
-
620
-    /**
621
-     * Sets STS_ID
622
-     *
623
-     * @param string $STS_ID
624
-     */
625
-    public function set_STS_ID($STS_ID)
626
-    {
627
-        $this->set('STS_ID', $STS_ID);
628
-    }
629
-
630
-
631
-    /**
632
-     * Gets created
633
-     *
634
-     * @return string
635
-     */
636
-    public function created()
637
-    {
638
-        return $this->get('MSG_created');
639
-    }
640
-
641
-
642
-    /**
643
-     * Sets created
644
-     *
645
-     * @param string $created
646
-     */
647
-    public function set_created($created)
648
-    {
649
-        $this->set('MSG_created', $created);
650
-    }
651
-
652
-
653
-    /**
654
-     * Gets modified
655
-     *
656
-     * @return string
657
-     */
658
-    public function modified()
659
-    {
660
-        return $this->get('MSG_modified');
661
-    }
662
-
663
-
664
-    /**
665
-     * Sets modified
666
-     *
667
-     * @param string $modified
668
-     */
669
-    public function set_modified($modified)
670
-    {
671
-        $this->set('MSG_modified', $modified);
672
-    }
673
-
674
-
675
-    /**
676
-     * Sets generation data for this message.
677
-     *
678
-     * @param mixed $data
679
-     */
680
-    public function set_generation_data($data)
681
-    {
682
-        $this->set_field_or_extra_meta('MSG_generation_data', $data);
683
-    }
684
-
685
-
686
-    /**
687
-     * Returns any set generation data for this message.
688
-     *
689
-     * @return mixed|null
690
-     */
691
-    public function get_generation_data()
692
-    {
693
-        return $this->get_field_or_extra_meta('MSG_generation_data');
694
-    }
695
-
696
-
697
-    /**
698
-     * Gets any error message.
699
-     *
700
-     * @return mixed|null
701
-     */
702
-    public function error_message()
703
-    {
704
-        return $this->get_field_or_extra_meta('MSG_error');
705
-    }
706
-
707
-
708
-    /**
709
-     * Sets an error message.
710
-     *
711
-     * @param $message
712
-     * @return bool|int
713
-     */
714
-    public function set_error_message($message)
715
-    {
716
-        return $this->set_field_or_extra_meta('MSG_error', $message);
717
-    }
718
-
719
-
720
-    /**
721
-     * This retrieves the associated template pack with this message.
722
-     *
723
-     * @return EE_Messages_Template_Pack | null
724
-     */
725
-    public function get_template_pack()
726
-    {
727
-        /**
728
-         * This is deprecated functionality that will be removed eventually but included here now for backward compat.
729
-         */
730
-        if ( ! empty($this->template_pack)) {
731
-            return $this->template_pack;
732
-        }
733
-        /** @type EE_Message_Template_Group $grp */
734
-        $grp = $this->get_first_related('Message_Template_Group');
735
-        //if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
736
-        if ( ! $grp instanceof EE_Message_Template_Group) {
737
-            $grp = EEM_Message_Template_Group::instance()->get_one(
738
-                array(
739
-                    array(
740
-                        'MTP_messenger'    => $this->messenger(),
741
-                        'MTP_message_type' => $this->message_type(),
742
-                        'MTP_is_global'    => true,
743
-                    ),
744
-                )
745
-            );
746
-        }
747
-
748
-        return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null;
749
-    }
750
-
751
-
752
-    /**
753
-     * Retrieves the variation used for generating this message.
754
-     *
755
-     * @return string
756
-     */
757
-    public function get_template_pack_variation()
758
-    {
759
-        /**
760
-         * This is deprecated functionality that will be removed eventually but included here now for backward compat.
761
-         */
762
-        if ( ! empty($this->template_variation)) {
763
-            return $this->template_variation;
764
-        }
765
-
766
-        /** @type EE_Message_Template_Group $grp */
767
-        $grp = $this->get_first_related('Message_Template_Group');
768
-
769
-        //if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
770
-        if ( ! $grp instanceof EE_Message_Template_Group) {
771
-            $grp = EEM_Message_Template_Group::instance()->get_one(
772
-                array(
773
-                    array(
774
-                        'MTP_messenger'    => $this->messenger(),
775
-                        'MTP_message_type' => $this->message_type(),
776
-                        'MTP_is_global'    => true,
777
-                    ),
778
-                )
779
-            );
780
-        }
781
-
782
-        return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : '';
783
-    }
784
-
785
-    /**
786
-     * Return the link to the admin details for the object.
787
-     *
788
-     * @return string
789
-     */
790
-    public function get_admin_details_link()
791
-    {
792
-        EE_Registry::instance()->load_helper('URL');
793
-        EE_Registry::instance()->load_helper('MSG_Template');
794
-        switch ($this->STS_ID()) {
795
-            case EEM_Message::status_failed :
796
-            case EEM_Message::status_debug_only :
797
-                return EEH_MSG_Template::generate_error_display_trigger($this);
798
-                break;
799
-
800
-            case EEM_Message::status_sent :
801
-                return EEH_MSG_Template::generate_browser_trigger($this);
802
-                break;
803
-
804
-            default :
805
-                return '';
806
-        }
807
-    }
808
-
809
-    /**
810
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
811
-     *
812
-     * @return string
813
-     */
814
-    public function get_admin_edit_link()
815
-    {
816
-        return $this->get_admin_details_link();
817
-    }
818
-
819
-    /**
820
-     * Returns the link to a settings page for the object.
821
-     *
822
-     * @return string
823
-     */
824
-    public function get_admin_settings_link()
825
-    {
826
-        EE_Registry::instance()->load_helper('URL');
827
-        return EEH_URL::add_query_args_and_nonce(
828
-            array(
829
-                'page'   => 'espresso_messages',
830
-                'action' => 'settings',
831
-            ),
832
-            admin_url('admin.php')
833
-        );
834
-    }
835
-
836
-    /**
837
-     * Returns the link to the "overview" for the object (typically the "list table" view).
838
-     *
839
-     * @return string
840
-     */
841
-    public function get_admin_overview_link()
842
-    {
843
-        EE_Registry::instance()->load_helper('URL');
844
-        return EEH_URL::add_query_args_and_nonce(
845
-            array(
846
-                'page'   => 'espresso_messages',
847
-                'action' => 'default',
848
-            ),
849
-            admin_url('admin.php')
850
-        );
851
-    }
852
-
853
-
854
-    /**
855
-     * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for
856
-     * it.
857
-     * Note this also SAVES the current message object to the db because it adds an error message to accompany the status.
858
-     *
859
-     */
860
-    public function set_messenger_is_executing()
861
-    {
862
-        $this->set_STS_ID( EEM_Message::status_messenger_executing );
863
-        $this->set_error_message(
864
-            esc_html__(
865
-                'A message with this status indicates that there was a problem that occurred while the message was being
15
+	/**
16
+	 * @deprecated 4.9.0  Added for backward compat with add-on's
17
+	 * @type null
18
+	 */
19
+	public $template_pack;
20
+
21
+	/**
22
+	 * @deprecated 4.9.0 Added for backward compat with add-on's
23
+	 * @type null
24
+	 */
25
+	public $template_variation;
26
+
27
+	/**
28
+	 * @deprecated 4.9.0 Added for backward compat with add-on's
29
+	 * @type string
30
+	 */
31
+	public $content = '';
32
+
33
+
34
+	/**
35
+	 * @type EE_messenger $_messenger
36
+	 */
37
+	protected $_messenger = null;
38
+
39
+	/**
40
+	 * @type EE_message_type $_message_type
41
+	 */
42
+	protected $_message_type = null;
43
+
44
+
45
+	/**
46
+	 * @param array  $props_n_values
47
+	 * @param string $timezone
48
+	 * @param array  $date_formats incoming date formats in an array.  First value is the date_format, second is time
49
+	 *                             format.
50
+	 * @return EE_Message
51
+	 */
52
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
53
+	{
54
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
55
+		//if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
56
+		if ( ! $has_object) {
57
+			EE_Registry::instance()->load_helper('URL');
58
+			$props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
59
+		}
60
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
61
+	}
62
+
63
+
64
+	/**
65
+	 * @param array  $props_n_values
66
+	 * @param string $timezone
67
+	 * @return EE_Message
68
+	 */
69
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
70
+	{
71
+		return new self($props_n_values, true, $timezone);
72
+	}
73
+
74
+
75
+	/**
76
+	 * Gets MSG_token
77
+	 *
78
+	 * @return int
79
+	 */
80
+	public function MSG_token()
81
+	{
82
+		return $this->get('MSG_token');
83
+	}
84
+
85
+
86
+	/**
87
+	 * Sets MSG_token
88
+	 *
89
+	 * @param int $MSG_token
90
+	 */
91
+	public function set_MSG_token($MSG_token)
92
+	{
93
+		$this->set('MSG_token', $MSG_token);
94
+	}
95
+
96
+
97
+	/**
98
+	 * Gets GRP_ID
99
+	 *
100
+	 * @return int
101
+	 */
102
+	public function GRP_ID()
103
+	{
104
+		return $this->get('GRP_ID');
105
+	}
106
+
107
+
108
+	/**
109
+	 * Sets GRP_ID
110
+	 *
111
+	 * @param int $GRP_ID
112
+	 */
113
+	public function set_GRP_ID($GRP_ID)
114
+	{
115
+		$this->set('GRP_ID', $GRP_ID);
116
+	}
117
+
118
+
119
+	/**
120
+	 * Gets TXN_ID
121
+	 *
122
+	 * @return int
123
+	 */
124
+	public function TXN_ID()
125
+	{
126
+		return $this->get('TXN_ID');
127
+	}
128
+
129
+
130
+	/**
131
+	 * Sets TXN_ID
132
+	 *
133
+	 * @param int $TXN_ID
134
+	 */
135
+	public function set_TXN_ID($TXN_ID)
136
+	{
137
+		$this->set('TXN_ID', $TXN_ID);
138
+	}
139
+
140
+
141
+	/**
142
+	 * Gets messenger
143
+	 *
144
+	 * @return string
145
+	 */
146
+	public function messenger()
147
+	{
148
+		return $this->get('MSG_messenger');
149
+	}
150
+
151
+
152
+	/**
153
+	 * Sets messenger
154
+	 *
155
+	 * @param string $messenger
156
+	 */
157
+	public function set_messenger($messenger)
158
+	{
159
+		$this->set('MSG_messenger', $messenger);
160
+	}
161
+
162
+
163
+	/**
164
+	 * Returns corresponding messenger object for the set messenger on this message
165
+	 *
166
+	 * @return EE_messenger | null
167
+	 */
168
+	public function messenger_object()
169
+	{
170
+		return $this->_messenger;
171
+	}
172
+
173
+
174
+	/**
175
+	 * Sets messenger
176
+	 *
177
+	 * @param EE_messenger $messenger
178
+	 */
179
+	public function set_messenger_object(EE_messenger $messenger)
180
+	{
181
+		$this->_messenger = $messenger;
182
+	}
183
+
184
+
185
+	/**
186
+	 * validates messenger
187
+	 *
188
+	 * @param bool $throw_exceptions
189
+	 * @return bool
190
+	 * @throws \EE_Error
191
+	 */
192
+	public function valid_messenger($throw_exceptions = false)
193
+	{
194
+		if ($this->_messenger instanceof EE_messenger) {
195
+			return true;
196
+		}
197
+		if ($throw_exceptions) {
198
+			throw new EE_Error(
199
+				sprintf(
200
+					__(
201
+						'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
202
+						'event_espresso'
203
+					),
204
+					$this->messenger()
205
+				)
206
+			);
207
+		}
208
+		return false;
209
+	}
210
+
211
+
212
+	/**
213
+	 * This returns the set localized label for the messenger on this message.
214
+	 * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved
215
+	 * with this message.
216
+	 *
217
+	 * @param   bool $plural whether to return the plural label or not.
218
+	 * @return string
219
+	 */
220
+	public function messenger_label($plural = false)
221
+	{
222
+		$label_type = $plural ? 'plural' : 'singular';
223
+		$messenger  = $this->messenger_object();
224
+		return $messenger instanceof EE_messenger ? $messenger->label[$label_type] : $this->messenger();
225
+	}
226
+
227
+
228
+	/**
229
+	 * Gets message_type
230
+	 *
231
+	 * @return string
232
+	 */
233
+	public function message_type()
234
+	{
235
+		return $this->get('MSG_message_type');
236
+	}
237
+
238
+
239
+	/**
240
+	 * Sets message_type
241
+	 *
242
+	 * @param string $message_type
243
+	 */
244
+	public function set_message_type($message_type)
245
+	{
246
+		$this->set('MSG_message_type', $message_type);
247
+	}
248
+
249
+
250
+	/**
251
+	 * Returns the message type object for the set message type on this message
252
+	 *
253
+	 * @return EE_message_type | null
254
+	 */
255
+	public function message_type_object()
256
+	{
257
+		return $this->_message_type;
258
+	}
259
+
260
+
261
+	/**
262
+	 * Sets message_type
263
+	 *
264
+	 * @param EE_message_type $message_type
265
+	 * @param bool            $set_priority   This indicates whether to set the priority to whatever the priority is on
266
+	 *                                        the message type or not.
267
+	 */
268
+	public function set_message_type_object(EE_message_type $message_type, $set_priority = false)
269
+	{
270
+		$this->_message_type = $message_type;
271
+		if ($set_priority) {
272
+			$this->set_priority($this->_message_type->get_priority());
273
+		}
274
+	}
275
+
276
+
277
+	/**
278
+	 * validates message_type
279
+	 *
280
+	 * @param bool $throw_exceptions
281
+	 * @return bool
282
+	 * @throws \EE_Error
283
+	 */
284
+	public function valid_message_type($throw_exceptions = false)
285
+	{
286
+		if ($this->_message_type instanceof EE_message_type) {
287
+			return true;
288
+		}
289
+		if ($throw_exceptions) {
290
+			throw new EE_Error(
291
+				sprintf(
292
+					__(
293
+						'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
294
+						'event_espresso'
295
+					),
296
+					$this->message_type()
297
+				)
298
+			);
299
+		}
300
+		return false;
301
+	}
302
+
303
+
304
+	/**
305
+	 * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects).
306
+	 *
307
+	 * @param bool $throw_exceptions
308
+	 * @return bool
309
+	 * @throws \EE_Error
310
+	 */
311
+	public function is_valid($throw_exceptions = false)
312
+	{
313
+		if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) {
314
+			return true;
315
+		}
316
+		return false;
317
+	}
318
+
319
+
320
+	/**
321
+	 * This validates whether the internal messenger and message type objects are valid for sending.
322
+	 * Three checks are done:
323
+	 * 1. There is a valid messenger object.
324
+	 * 2. There is a valid message type object.
325
+	 * 3. The message type object is active for the messenger.
326
+	 *
327
+	 * @throws EE_Error  But only if $throw_exceptions is set to true.
328
+	 * @param bool $throw_exceptions
329
+	 * @return bool
330
+	 */
331
+	public function is_valid_for_sending_or_generation($throw_exceptions = false)
332
+	{
333
+		$valid = false;
334
+		if ($this->is_valid($throw_exceptions)) {
335
+			/** @var EE_Message_Resource_Manager $message_resource_manager */
336
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
337
+			$valid                    = $message_resource_manager->is_message_type_active_for_messenger($this->messenger(),
338
+				$this->message_type());
339
+			if ( ! $valid && $throw_exceptions) {
340
+				throw new EE_Error(
341
+					sprintf(
342
+						__('The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.',
343
+							'event_espresso'),
344
+						$this->message_type(),
345
+						$this->messenger()
346
+					)
347
+				);
348
+			}
349
+		}
350
+		return $valid;
351
+	}
352
+
353
+
354
+	/**
355
+	 * This returns the set localized label for the message type on this message.
356
+	 * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved
357
+	 * with this message.
358
+	 *
359
+	 * @param   bool $plural whether to return the plural label or not.
360
+	 * @return string
361
+	 */
362
+	public function message_type_label($plural = false)
363
+	{
364
+		$label_type   = $plural ? 'plural' : 'singular';
365
+		$message_type = $this->message_type_object();
366
+		return $message_type instanceof EE_message_type ? $message_type->label[$label_type] : $this->message_type();
367
+	}
368
+
369
+
370
+	/**
371
+	 * Gets context
372
+	 *
373
+	 * @return string
374
+	 */
375
+	public function context()
376
+	{
377
+		return $this->get('MSG_context');
378
+	}
379
+
380
+
381
+	/**
382
+	 * This returns the corresponding localized label for the given context slug, if possible from installed message
383
+	 * types. Otherwise, this will just return the set context slug on this object.
384
+	 *
385
+	 * @return string
386
+	 */
387
+	public function context_label()
388
+	{
389
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
390
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
391
+		$contexts                 = $message_resource_manager->get_all_contexts();
392
+		return isset($contexts[$this->context()]) ? $contexts[$this->context()] : $this->context();
393
+	}
394
+
395
+
396
+	/**
397
+	 * Sets context
398
+	 *
399
+	 * @param string $context
400
+	 */
401
+	public function set_context($context)
402
+	{
403
+		$this->set('MSG_context', $context);
404
+	}
405
+
406
+
407
+	/**
408
+	 * Gets recipient_ID
409
+	 *
410
+	 * @return int
411
+	 */
412
+	public function recipient_ID()
413
+	{
414
+		return $this->get('MSG_recipient_ID');
415
+	}
416
+
417
+
418
+	/**
419
+	 * Sets recipient_ID
420
+	 *
421
+	 * @param string $recipient_ID
422
+	 */
423
+	public function set_recipient_ID($recipient_ID)
424
+	{
425
+		$this->set('MSG_recipient_ID', $recipient_ID);
426
+	}
427
+
428
+
429
+	/**
430
+	 * Gets recipient_type
431
+	 *
432
+	 * @return string
433
+	 */
434
+	public function recipient_type()
435
+	{
436
+		return $this->get('MSG_recipient_type');
437
+	}
438
+
439
+
440
+	/**
441
+	 * Return the related object matching the recipient type and ID.
442
+	 *
443
+	 * @return EE_Base_Class | null
444
+	 */
445
+	public function recipient_object()
446
+	{
447
+		if ( ! $this->recipient_type() || ! $this->recipient_ID()) {
448
+			return null;
449
+		}
450
+
451
+		return $this->get_first_related($this->recipient_type());
452
+	}
453
+
454
+
455
+	/**
456
+	 * Sets recipient_type
457
+	 *
458
+	 * @param string $recipient_type
459
+	 */
460
+	public function set_recipient_type($recipient_type)
461
+	{
462
+		$this->set('MSG_recipient_type', $recipient_type);
463
+	}
464
+
465
+
466
+	/**
467
+	 * Gets content
468
+	 *
469
+	 * @return string
470
+	 */
471
+	public function content()
472
+	{
473
+		return $this->get('MSG_content');
474
+	}
475
+
476
+
477
+	/**
478
+	 * Sets content
479
+	 *
480
+	 * @param string $content
481
+	 */
482
+	public function set_content($content)
483
+	{
484
+		$this->set('MSG_content', $content);
485
+	}
486
+
487
+
488
+	/**
489
+	 * Gets subject
490
+	 *
491
+	 * @return string
492
+	 */
493
+	public function subject()
494
+	{
495
+		return $this->get('MSG_subject');
496
+	}
497
+
498
+
499
+	/**
500
+	 * Sets subject
501
+	 *
502
+	 * @param string $subject
503
+	 */
504
+	public function set_subject($subject)
505
+	{
506
+		$this->set('MSG_subject', $subject);
507
+	}
508
+
509
+
510
+	/**
511
+	 * Gets to
512
+	 *
513
+	 * @return string
514
+	 */
515
+	public function to()
516
+	{
517
+		$to = $this->get('MSG_to');
518
+		return empty($to) ? __('No recipient', 'event_espresso') : $to;
519
+	}
520
+
521
+
522
+	/**
523
+	 * Sets to
524
+	 *
525
+	 * @param string $to
526
+	 */
527
+	public function set_to($to)
528
+	{
529
+		$this->set('MSG_to', $to);
530
+	}
531
+
532
+
533
+	/**
534
+	 * Gets from
535
+	 *
536
+	 * @return string
537
+	 */
538
+	public function from()
539
+	{
540
+		return $this->get('MSG_from');
541
+	}
542
+
543
+
544
+	/**
545
+	 * Sets from
546
+	 *
547
+	 * @param string $from
548
+	 */
549
+	public function set_from($from)
550
+	{
551
+		$this->set('MSG_from', $from);
552
+	}
553
+
554
+
555
+	/**
556
+	 * Gets priority
557
+	 *
558
+	 * @return int
559
+	 */
560
+	public function priority()
561
+	{
562
+		return $this->get('MSG_priority');
563
+	}
564
+
565
+
566
+	/**
567
+	 * Sets priority
568
+	 * Note.  Send Now Messengers always override any priority that may be set on a Message.  So
569
+	 * this method calls the send_now method to verify that.
570
+	 *
571
+	 * @param int $priority
572
+	 */
573
+	public function set_priority($priority)
574
+	{
575
+		$priority = $this->send_now() ? EEM_Message::priority_high : $priority;
576
+		parent::set('MSG_priority', $priority);
577
+	}
578
+
579
+
580
+	/**
581
+	 * Overrides parent::set method so we can capture any sets for priority.
582
+	 *
583
+	 * @see parent::set() for phpdocs
584
+	 * @param string $field_name
585
+	 * @param mixed  $field_value
586
+	 * @param bool   $use_default
587
+	 * @throws EE_Error
588
+	 */
589
+	public function set($field_name, $field_value, $use_default = false)
590
+	{
591
+		if ($field_name === 'MSG_priority') {
592
+			$this->set_priority($field_value);
593
+		}
594
+		parent::set($field_name, $field_value, $use_default);
595
+	}
596
+
597
+
598
+	/**
599
+	 * @return bool
600
+	 * @throws \EE_Error
601
+	 */
602
+	public function send_now()
603
+	{
604
+		$send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high : $this->priority();
605
+		return $send_now === EEM_Message::priority_high ? true : false;
606
+	}
607
+
608
+
609
+	/**
610
+	 * Gets STS_ID
611
+	 *
612
+	 * @return string
613
+	 */
614
+	public function STS_ID()
615
+	{
616
+		return $this->get('STS_ID');
617
+	}
618
+
619
+
620
+	/**
621
+	 * Sets STS_ID
622
+	 *
623
+	 * @param string $STS_ID
624
+	 */
625
+	public function set_STS_ID($STS_ID)
626
+	{
627
+		$this->set('STS_ID', $STS_ID);
628
+	}
629
+
630
+
631
+	/**
632
+	 * Gets created
633
+	 *
634
+	 * @return string
635
+	 */
636
+	public function created()
637
+	{
638
+		return $this->get('MSG_created');
639
+	}
640
+
641
+
642
+	/**
643
+	 * Sets created
644
+	 *
645
+	 * @param string $created
646
+	 */
647
+	public function set_created($created)
648
+	{
649
+		$this->set('MSG_created', $created);
650
+	}
651
+
652
+
653
+	/**
654
+	 * Gets modified
655
+	 *
656
+	 * @return string
657
+	 */
658
+	public function modified()
659
+	{
660
+		return $this->get('MSG_modified');
661
+	}
662
+
663
+
664
+	/**
665
+	 * Sets modified
666
+	 *
667
+	 * @param string $modified
668
+	 */
669
+	public function set_modified($modified)
670
+	{
671
+		$this->set('MSG_modified', $modified);
672
+	}
673
+
674
+
675
+	/**
676
+	 * Sets generation data for this message.
677
+	 *
678
+	 * @param mixed $data
679
+	 */
680
+	public function set_generation_data($data)
681
+	{
682
+		$this->set_field_or_extra_meta('MSG_generation_data', $data);
683
+	}
684
+
685
+
686
+	/**
687
+	 * Returns any set generation data for this message.
688
+	 *
689
+	 * @return mixed|null
690
+	 */
691
+	public function get_generation_data()
692
+	{
693
+		return $this->get_field_or_extra_meta('MSG_generation_data');
694
+	}
695
+
696
+
697
+	/**
698
+	 * Gets any error message.
699
+	 *
700
+	 * @return mixed|null
701
+	 */
702
+	public function error_message()
703
+	{
704
+		return $this->get_field_or_extra_meta('MSG_error');
705
+	}
706
+
707
+
708
+	/**
709
+	 * Sets an error message.
710
+	 *
711
+	 * @param $message
712
+	 * @return bool|int
713
+	 */
714
+	public function set_error_message($message)
715
+	{
716
+		return $this->set_field_or_extra_meta('MSG_error', $message);
717
+	}
718
+
719
+
720
+	/**
721
+	 * This retrieves the associated template pack with this message.
722
+	 *
723
+	 * @return EE_Messages_Template_Pack | null
724
+	 */
725
+	public function get_template_pack()
726
+	{
727
+		/**
728
+		 * This is deprecated functionality that will be removed eventually but included here now for backward compat.
729
+		 */
730
+		if ( ! empty($this->template_pack)) {
731
+			return $this->template_pack;
732
+		}
733
+		/** @type EE_Message_Template_Group $grp */
734
+		$grp = $this->get_first_related('Message_Template_Group');
735
+		//if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
736
+		if ( ! $grp instanceof EE_Message_Template_Group) {
737
+			$grp = EEM_Message_Template_Group::instance()->get_one(
738
+				array(
739
+					array(
740
+						'MTP_messenger'    => $this->messenger(),
741
+						'MTP_message_type' => $this->message_type(),
742
+						'MTP_is_global'    => true,
743
+					),
744
+				)
745
+			);
746
+		}
747
+
748
+		return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null;
749
+	}
750
+
751
+
752
+	/**
753
+	 * Retrieves the variation used for generating this message.
754
+	 *
755
+	 * @return string
756
+	 */
757
+	public function get_template_pack_variation()
758
+	{
759
+		/**
760
+		 * This is deprecated functionality that will be removed eventually but included here now for backward compat.
761
+		 */
762
+		if ( ! empty($this->template_variation)) {
763
+			return $this->template_variation;
764
+		}
765
+
766
+		/** @type EE_Message_Template_Group $grp */
767
+		$grp = $this->get_first_related('Message_Template_Group');
768
+
769
+		//if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
770
+		if ( ! $grp instanceof EE_Message_Template_Group) {
771
+			$grp = EEM_Message_Template_Group::instance()->get_one(
772
+				array(
773
+					array(
774
+						'MTP_messenger'    => $this->messenger(),
775
+						'MTP_message_type' => $this->message_type(),
776
+						'MTP_is_global'    => true,
777
+					),
778
+				)
779
+			);
780
+		}
781
+
782
+		return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : '';
783
+	}
784
+
785
+	/**
786
+	 * Return the link to the admin details for the object.
787
+	 *
788
+	 * @return string
789
+	 */
790
+	public function get_admin_details_link()
791
+	{
792
+		EE_Registry::instance()->load_helper('URL');
793
+		EE_Registry::instance()->load_helper('MSG_Template');
794
+		switch ($this->STS_ID()) {
795
+			case EEM_Message::status_failed :
796
+			case EEM_Message::status_debug_only :
797
+				return EEH_MSG_Template::generate_error_display_trigger($this);
798
+				break;
799
+
800
+			case EEM_Message::status_sent :
801
+				return EEH_MSG_Template::generate_browser_trigger($this);
802
+				break;
803
+
804
+			default :
805
+				return '';
806
+		}
807
+	}
808
+
809
+	/**
810
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
811
+	 *
812
+	 * @return string
813
+	 */
814
+	public function get_admin_edit_link()
815
+	{
816
+		return $this->get_admin_details_link();
817
+	}
818
+
819
+	/**
820
+	 * Returns the link to a settings page for the object.
821
+	 *
822
+	 * @return string
823
+	 */
824
+	public function get_admin_settings_link()
825
+	{
826
+		EE_Registry::instance()->load_helper('URL');
827
+		return EEH_URL::add_query_args_and_nonce(
828
+			array(
829
+				'page'   => 'espresso_messages',
830
+				'action' => 'settings',
831
+			),
832
+			admin_url('admin.php')
833
+		);
834
+	}
835
+
836
+	/**
837
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
838
+	 *
839
+	 * @return string
840
+	 */
841
+	public function get_admin_overview_link()
842
+	{
843
+		EE_Registry::instance()->load_helper('URL');
844
+		return EEH_URL::add_query_args_and_nonce(
845
+			array(
846
+				'page'   => 'espresso_messages',
847
+				'action' => 'default',
848
+			),
849
+			admin_url('admin.php')
850
+		);
851
+	}
852
+
853
+
854
+	/**
855
+	 * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for
856
+	 * it.
857
+	 * Note this also SAVES the current message object to the db because it adds an error message to accompany the status.
858
+	 *
859
+	 */
860
+	public function set_messenger_is_executing()
861
+	{
862
+		$this->set_STS_ID( EEM_Message::status_messenger_executing );
863
+		$this->set_error_message(
864
+			esc_html__(
865
+				'A message with this status indicates that there was a problem that occurred while the message was being
866 866
                 processed by the messenger.  It is still possible that the message was sent successfully, but at some
867 867
                 point during the processing there was a failure.  This usually is indicative of a timeout issue with PHP 
868 868
                 or memory limits being reached.  If you see this repeatedly you may want to consider upgrading the memory 
869 869
                 available to PHP on your server.',
870
-                'event_espresso'
871
-            )
872
-        );
873
-    }
870
+				'event_espresso'
871
+			)
872
+		);
873
+	}
874 874
 }
875 875
 /* End of file EE_Message.class.php */
876 876
 /* Location: /core/db_classes/EE_Message.class.php */
877 877
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 
@@ -859,7 +859,7 @@  discard block
 block discarded – undo
859 859
      */
860 860
     public function set_messenger_is_executing()
861 861
     {
862
-        $this->set_STS_ID( EEM_Message::status_messenger_executing );
862
+        $this->set_STS_ID(EEM_Message::status_messenger_executing);
863 863
         $this->set_error_message(
864 864
             esc_html__(
865 865
                 'A message with this status indicates that there was a problem that occurred while the message was being
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +215 added lines, -215 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('ABSPATH')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /*
5 5
   Plugin Name:		Event Espresso
@@ -40,239 +40,239 @@  discard block
 block discarded – undo
40 40
  * @since            4.0
41 41
  */
42 42
 if (function_exists('espresso_version')) {
43
-    /**
44
-     *    espresso_duplicate_plugin_error
45
-     *    displays if more than one version of EE is activated at the same time
46
-     */
47
-    function espresso_duplicate_plugin_error()
48
-    {
49
-        ?>
43
+	/**
44
+	 *    espresso_duplicate_plugin_error
45
+	 *    displays if more than one version of EE is activated at the same time
46
+	 */
47
+	function espresso_duplicate_plugin_error()
48
+	{
49
+		?>
50 50
         <div class="error">
51 51
             <p>
52 52
                 <?php echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                ); ?>
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+				); ?>
56 56
             </p>
57 57
         </div>
58 58
         <?php
59
-        espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-    }
59
+		espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+	}
61 61
 
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
-    if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
+	if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                            esc_html__(
79
-                                    'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                                    'event_espresso'
81
-                            ),
82
-                            EE_MIN_PHP_VER_REQUIRED,
83
-                            PHP_VERSION,
84
-                            '<br/>',
85
-                            '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+							esc_html__(
79
+									'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+									'event_espresso'
81
+							),
82
+							EE_MIN_PHP_VER_REQUIRED,
83
+							PHP_VERSION,
84
+							'<br/>',
85
+							'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        /**
97
-         * espresso_version
98
-         * Returns the plugin version
99
-         *
100
-         * @return string
101
-         */
102
-        function espresso_version()
103
-        {
104
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.24.rc.017');
105
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		/**
97
+		 * espresso_version
98
+		 * Returns the plugin version
99
+		 *
100
+		 * @return string
101
+		 */
102
+		function espresso_version()
103
+		{
104
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.24.rc.017');
105
+		}
106 106
 
107
-        // define versions
108
-        define('EVENT_ESPRESSO_VERSION', espresso_version());
109
-        define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
-        define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
-        define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
-        //used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
-        if ( ! defined('DS')) {
115
-            define('DS', '/');
116
-        }
117
-        if ( ! defined('PS')) {
118
-            define('PS', PATH_SEPARATOR);
119
-        }
120
-        if ( ! defined('SP')) {
121
-            define('SP', ' ');
122
-        }
123
-        if ( ! defined('EENL')) {
124
-            define('EENL', "\n");
125
-        }
126
-        define('EE_SUPPORT_EMAIL', '[email protected]');
127
-        // define the plugin directory and URL
128
-        define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
-        define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
-        define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
-        // main root folder paths
132
-        define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
-        define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
-        define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
-        define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
-        define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
-        define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
-        define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
-        define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
-        // core system paths
141
-        define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
-        define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
-        define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
-        define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
-        define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
-        define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
-        define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
-        define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
-        define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
-        define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
-        define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
-        define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
-        // gateways
154
-        define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
-        define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
-        // asset URL paths
157
-        define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
-        define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
-        define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
-        define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
-        define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
-        define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
-        // define upload paths
164
-        $uploads = wp_upload_dir();
165
-        // define the uploads directory and URL
166
-        define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
-        define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
-        // define the templates directory and URL
169
-        define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
-        define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
-        // define the gateway directory and URL
172
-        define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
-        define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
-        // languages folder/path
175
-        define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
-        define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
-        //check for dompdf fonts in uploads
178
-        if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
-            define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
-        }
181
-        //ajax constants
182
-        define(
183
-                'EE_FRONT_AJAX',
184
-                isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
-        );
186
-        define(
187
-                'EE_ADMIN_AJAX',
188
-                isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
-        );
190
-        //just a handy constant occasionally needed for finding values representing infinity in the DB
191
-        //you're better to use this than its straight value (currently -1) in case you ever
192
-        //want to change its default value! or find when -1 means infinity
193
-        define('EE_INF_IN_DB', -1);
194
-        define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
-        define('EE_DEBUG', false);
196
-        /**
197
-         *    espresso_plugin_activation
198
-         *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
199
-         */
200
-        function espresso_plugin_activation()
201
-        {
202
-            update_option('ee_espresso_activation', true);
203
-        }
107
+		// define versions
108
+		define('EVENT_ESPRESSO_VERSION', espresso_version());
109
+		define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
+		define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
+		define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
+		//used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
+		if ( ! defined('DS')) {
115
+			define('DS', '/');
116
+		}
117
+		if ( ! defined('PS')) {
118
+			define('PS', PATH_SEPARATOR);
119
+		}
120
+		if ( ! defined('SP')) {
121
+			define('SP', ' ');
122
+		}
123
+		if ( ! defined('EENL')) {
124
+			define('EENL', "\n");
125
+		}
126
+		define('EE_SUPPORT_EMAIL', '[email protected]');
127
+		// define the plugin directory and URL
128
+		define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
+		define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
+		define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
+		// main root folder paths
132
+		define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
+		define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
+		define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
+		define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
+		define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
+		define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
+		define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
+		define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
+		// core system paths
141
+		define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
+		define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
+		define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
+		define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
+		define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
+		define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
+		define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
+		define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
+		define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
+		define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
+		define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
+		define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
+		// gateways
154
+		define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
+		define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
+		// asset URL paths
157
+		define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
+		define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
+		define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
+		define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
+		define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
+		define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
+		// define upload paths
164
+		$uploads = wp_upload_dir();
165
+		// define the uploads directory and URL
166
+		define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
+		define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
+		// define the templates directory and URL
169
+		define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
+		define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
+		// define the gateway directory and URL
172
+		define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
+		define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
+		// languages folder/path
175
+		define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
+		define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
+		//check for dompdf fonts in uploads
178
+		if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
+			define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
+		}
181
+		//ajax constants
182
+		define(
183
+				'EE_FRONT_AJAX',
184
+				isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
+		);
186
+		define(
187
+				'EE_ADMIN_AJAX',
188
+				isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
+		);
190
+		//just a handy constant occasionally needed for finding values representing infinity in the DB
191
+		//you're better to use this than its straight value (currently -1) in case you ever
192
+		//want to change its default value! or find when -1 means infinity
193
+		define('EE_INF_IN_DB', -1);
194
+		define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
+		define('EE_DEBUG', false);
196
+		/**
197
+		 *    espresso_plugin_activation
198
+		 *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
199
+		 */
200
+		function espresso_plugin_activation()
201
+		{
202
+			update_option('ee_espresso_activation', true);
203
+		}
204 204
 
205
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
206
-        /**
207
-         *    espresso_load_error_handling
208
-         *    this function loads EE's class for handling exceptions and errors
209
-         */
210
-        function espresso_load_error_handling()
211
-        {
212
-            // load debugging tools
213
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
214
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
215
-                EEH_Debug_Tools::instance();
216
-            }
217
-            // load error handling
218
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
219
-                require_once(EE_CORE . 'EE_Error.core.php');
220
-            } else {
221
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
222
-            }
223
-        }
205
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
206
+		/**
207
+		 *    espresso_load_error_handling
208
+		 *    this function loads EE's class for handling exceptions and errors
209
+		 */
210
+		function espresso_load_error_handling()
211
+		{
212
+			// load debugging tools
213
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
214
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
215
+				EEH_Debug_Tools::instance();
216
+			}
217
+			// load error handling
218
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
219
+				require_once(EE_CORE . 'EE_Error.core.php');
220
+			} else {
221
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
222
+			}
223
+		}
224 224
 
225
-        /**
226
-         *    espresso_load_required
227
-         *    given a class name and path, this function will load that file or throw an exception
228
-         *
229
-         * @param    string $classname
230
-         * @param    string $full_path_to_file
231
-         * @throws    EE_Error
232
-         */
233
-        function espresso_load_required($classname, $full_path_to_file)
234
-        {
235
-            static $error_handling_loaded = false;
236
-            if ( ! $error_handling_loaded) {
237
-                espresso_load_error_handling();
238
-                $error_handling_loaded = true;
239
-            }
240
-            if (is_readable($full_path_to_file)) {
241
-                require_once($full_path_to_file);
242
-            } else {
243
-                throw new EE_Error (
244
-                        sprintf(
245
-                                esc_html__(
246
-                                        'The %s class file could not be located or is not readable due to file permissions.',
247
-                                        'event_espresso'
248
-                                ),
249
-                                $classname
250
-                        )
251
-                );
252
-            }
253
-        }
225
+		/**
226
+		 *    espresso_load_required
227
+		 *    given a class name and path, this function will load that file or throw an exception
228
+		 *
229
+		 * @param    string $classname
230
+		 * @param    string $full_path_to_file
231
+		 * @throws    EE_Error
232
+		 */
233
+		function espresso_load_required($classname, $full_path_to_file)
234
+		{
235
+			static $error_handling_loaded = false;
236
+			if ( ! $error_handling_loaded) {
237
+				espresso_load_error_handling();
238
+				$error_handling_loaded = true;
239
+			}
240
+			if (is_readable($full_path_to_file)) {
241
+				require_once($full_path_to_file);
242
+			} else {
243
+				throw new EE_Error (
244
+						sprintf(
245
+								esc_html__(
246
+										'The %s class file could not be located or is not readable due to file permissions.',
247
+										'event_espresso'
248
+								),
249
+								$classname
250
+						)
251
+				);
252
+			}
253
+		}
254 254
 
255
-        espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
256
-        espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
257
-        espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
258
-        new EE_Bootstrap();
259
-    }
255
+		espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
256
+		espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
257
+		espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
258
+		new EE_Bootstrap();
259
+	}
260 260
 }
261 261
 if ( ! function_exists('espresso_deactivate_plugin')) {
262
-    /**
263
-     *    deactivate_plugin
264
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
265
-     *
266
-     * @access public
267
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
268
-     * @return    void
269
-     */
270
-    function espresso_deactivate_plugin($plugin_basename = '')
271
-    {
272
-        if ( ! function_exists('deactivate_plugins')) {
273
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
274
-        }
275
-        unset($_GET['activate'], $_REQUEST['activate']);
276
-        deactivate_plugins($plugin_basename);
277
-    }
262
+	/**
263
+	 *    deactivate_plugin
264
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
265
+	 *
266
+	 * @access public
267
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
268
+	 * @return    void
269
+	 */
270
+	function espresso_deactivate_plugin($plugin_basename = '')
271
+	{
272
+		if ( ! function_exists('deactivate_plugins')) {
273
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
274
+		}
275
+		unset($_GET['activate'], $_REQUEST['activate']);
276
+		deactivate_plugins($plugin_basename);
277
+	}
278 278
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 1 patch
Indentation   +3268 added lines, -3268 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
  * Event Espresso
@@ -28,2119 +28,2119 @@  discard block
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    //set in _init_page_props()
32
-    public $page_slug;
31
+	//set in _init_page_props()
32
+	public $page_slug;
33 33
 
34
-    public $page_label;
34
+	public $page_label;
35 35
 
36
-    public $page_folder;
36
+	public $page_folder;
37 37
 
38
-    //set in define_page_props()
39
-    protected $_admin_base_url;
38
+	//set in define_page_props()
39
+	protected $_admin_base_url;
40 40
 
41
-    protected $_admin_base_path;
41
+	protected $_admin_base_path;
42 42
 
43
-    protected $_admin_page_title;
43
+	protected $_admin_page_title;
44 44
 
45
-    protected $_labels;
45
+	protected $_labels;
46 46
 
47 47
 
48
-    //set early within EE_Admin_Init
49
-    protected $_wp_page_slug;
48
+	//set early within EE_Admin_Init
49
+	protected $_wp_page_slug;
50 50
 
51
-    //navtabs
52
-    protected $_nav_tabs;
51
+	//navtabs
52
+	protected $_nav_tabs;
53 53
 
54
-    protected $_default_nav_tab_name;
54
+	protected $_default_nav_tab_name;
55 55
 
56
-    //helptourstops
57
-    protected $_help_tour = array();
56
+	//helptourstops
57
+	protected $_help_tour = array();
58 58
 
59 59
 
60
-    //template variables (used by templates)
61
-    protected $_template_path;
60
+	//template variables (used by templates)
61
+	protected $_template_path;
62 62
 
63
-    protected $_column_template_path;
63
+	protected $_column_template_path;
64 64
 
65
-    /**
66
-     * @var array $_template_args
67
-     */
68
-    protected $_template_args = array();
65
+	/**
66
+	 * @var array $_template_args
67
+	 */
68
+	protected $_template_args = array();
69 69
 
70
-    /**
71
-     * this will hold the list table object for a given view.
72
-     *
73
-     * @var EE_Admin_List_Table $_list_table_object
74
-     */
75
-    protected $_list_table_object;
70
+	/**
71
+	 * this will hold the list table object for a given view.
72
+	 *
73
+	 * @var EE_Admin_List_Table $_list_table_object
74
+	 */
75
+	protected $_list_table_object;
76 76
 
77
-    //bools
78
-    protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
77
+	//bools
78
+	protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
79 79
 
80
-    protected $_routing;
80
+	protected $_routing;
81 81
 
82
-    //list table args
83
-    protected $_view;
82
+	//list table args
83
+	protected $_view;
84 84
 
85
-    protected $_views;
85
+	protected $_views;
86 86
 
87 87
 
88
-    //action => method pairs used for routing incoming requests
89
-    protected $_page_routes;
88
+	//action => method pairs used for routing incoming requests
89
+	protected $_page_routes;
90 90
 
91
-    protected $_page_config;
91
+	protected $_page_config;
92 92
 
93
-    //the current page route and route config
94
-    protected $_route;
93
+	//the current page route and route config
94
+	protected $_route;
95 95
 
96
-    protected $_route_config;
96
+	protected $_route_config;
97 97
 
98
-    /**
99
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
100
-     * actions.
101
-     *
102
-     * @since 4.6.x
103
-     * @var array.
104
-     */
105
-    protected $_default_route_query_args;
98
+	/**
99
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
100
+	 * actions.
101
+	 *
102
+	 * @since 4.6.x
103
+	 * @var array.
104
+	 */
105
+	protected $_default_route_query_args;
106 106
 
107
-    //set via request page and action args.
108
-    protected $_current_page;
107
+	//set via request page and action args.
108
+	protected $_current_page;
109 109
 
110
-    protected $_current_view;
110
+	protected $_current_view;
111 111
 
112
-    protected $_current_page_view_url;
112
+	protected $_current_page_view_url;
113 113
 
114
-    //sanitized request action (and nonce)
115
-    /**
116
-     * @var string $_req_action
117
-     */
118
-    protected $_req_action;
114
+	//sanitized request action (and nonce)
115
+	/**
116
+	 * @var string $_req_action
117
+	 */
118
+	protected $_req_action;
119 119
 
120
-    /**
121
-     * @var string $_req_nonce
122
-     */
123
-    protected $_req_nonce;
120
+	/**
121
+	 * @var string $_req_nonce
122
+	 */
123
+	protected $_req_nonce;
124 124
 
125
-    //search related
126
-    protected $_search_btn_label;
125
+	//search related
126
+	protected $_search_btn_label;
127 127
 
128
-    protected $_search_box_callback;
128
+	protected $_search_box_callback;
129 129
 
130
-    /**
131
-     * WP Current Screen object
132
-     *
133
-     * @var WP_Screen
134
-     */
135
-    protected $_current_screen;
130
+	/**
131
+	 * WP Current Screen object
132
+	 *
133
+	 * @var WP_Screen
134
+	 */
135
+	protected $_current_screen;
136 136
 
137
-    //for holding EE_Admin_Hooks object when needed (set via set_hook_object())
138
-    protected $_hook_obj;
137
+	//for holding EE_Admin_Hooks object when needed (set via set_hook_object())
138
+	protected $_hook_obj;
139 139
 
140
-    //for holding incoming request data
141
-    protected $_req_data;
140
+	//for holding incoming request data
141
+	protected $_req_data;
142 142
 
143
-    // yes / no array for admin form fields
144
-    protected $_yes_no_values = array();
145
-
146
-    //some default things shared by all child classes
147
-    protected $_default_espresso_metaboxes;
148
-
149
-    /**
150
-     *    EE_Registry Object
151
-     *
152
-     * @var    EE_Registry
153
-     * @access    protected
154
-     */
155
-    protected $EE = null;
156
-
157
-
158
-
159
-    /**
160
-     * This is just a property that flags whether the given route is a caffeinated route or not.
161
-     *
162
-     * @var boolean
163
-     */
164
-    protected $_is_caf = false;
165
-
166
-
167
-
168
-    /**
169
-     * @Constructor
170
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
171
-     * @access public
172
-     */
173
-    public function __construct($routing = true)
174
-    {
175
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
176
-            $this->_is_caf = true;
177
-        }
178
-        $this->_yes_no_values = array(
179
-                array('id' => true, 'text' => __('Yes', 'event_espresso')),
180
-                array('id' => false, 'text' => __('No', 'event_espresso')),
181
-        );
182
-        //set the _req_data property.
183
-        $this->_req_data = array_merge($_GET, $_POST);
184
-        //routing enabled?
185
-        $this->_routing = $routing;
186
-        //set initial page props (child method)
187
-        $this->_init_page_props();
188
-        //set global defaults
189
-        $this->_set_defaults();
190
-        //set early because incoming requests could be ajax related and we need to register those hooks.
191
-        $this->_global_ajax_hooks();
192
-        $this->_ajax_hooks();
193
-        //other_page_hooks have to be early too.
194
-        $this->_do_other_page_hooks();
195
-        //This just allows us to have extending clases do something specific before the parent constructor runs _page_setup.
196
-        if (method_exists($this, '_before_page_setup')) {
197
-            $this->_before_page_setup();
198
-        }
199
-        //set up page dependencies
200
-        $this->_page_setup();
201
-    }
202
-
203
-
204
-
205
-    /**
206
-     * _init_page_props
207
-     * Child classes use to set at least the following properties:
208
-     * $page_slug.
209
-     * $page_label.
210
-     *
211
-     * @abstract
212
-     * @access protected
213
-     * @return void
214
-     */
215
-    abstract protected function _init_page_props();
216
-
217
-
218
-
219
-    /**
220
-     * _ajax_hooks
221
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
222
-     * Note: within the ajax callback methods.
223
-     *
224
-     * @abstract
225
-     * @access protected
226
-     * @return void
227
-     */
228
-    abstract protected function _ajax_hooks();
229
-
230
-
231
-
232
-    /**
233
-     * _define_page_props
234
-     * child classes define page properties in here.  Must include at least:
235
-     * $_admin_base_url = base_url for all admin pages
236
-     * $_admin_page_title = default admin_page_title for admin pages
237
-     * $_labels = array of default labels for various automatically generated elements:
238
-     *    array(
239
-     *        'buttons' => array(
240
-     *            'add' => __('label for add new button'),
241
-     *            'edit' => __('label for edit button'),
242
-     *            'delete' => __('label for delete button')
243
-     *            )
244
-     *        )
245
-     *
246
-     * @abstract
247
-     * @access protected
248
-     * @return void
249
-     */
250
-    abstract protected function _define_page_props();
251
-
252
-
253
-
254
-    /**
255
-     * _set_page_routes
256
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also have a 'default'
257
-     * route. Here's the format
258
-     * $this->_page_routes = array(
259
-     *        'default' => array(
260
-     *            'func' => '_default_method_handling_route',
261
-     *            'args' => array('array','of','args'),
262
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e. ajax request, backend processing)
263
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a headers route after.  The string you enter here should match the defined route reference for a headers sent route.
264
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access this route.
265
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability checks).
266
-     *        ),
267
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a handling method.
268
-     *        )
269
-     * )
270
-     *
271
-     * @abstract
272
-     * @access protected
273
-     * @return void
274
-     */
275
-    abstract protected function _set_page_routes();
276
-
277
-
278
-
279
-    /**
280
-     * _set_page_config
281
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the array corresponds to the page_route for the loaded page.
282
-     * Format:
283
-     * $this->_page_config = array(
284
-     *        'default' => array(
285
-     *            'labels' => array(
286
-     *                'buttons' => array(
287
-     *                    'add' => __('label for adding item'),
288
-     *                    'edit' => __('label for editing item'),
289
-     *                    'delete' => __('label for deleting item')
290
-     *                ),
291
-     *                'publishbox' => __('Localized Title for Publish metabox', 'event_espresso')
292
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the page. If this isn't present then the defaults will be used as set for the $this->_labels in _define_page_props() method
293
-     *            'nav' => array(
294
-     *                'label' => __('Label for Tab', 'event_espresso').
295
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
296
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
297
-     *                'order' => 10, //required to indicate tab position.
298
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is displayed then add this parameter.
299
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
300
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load metaboxes set for eventespresso admin pages.
301
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added later.  We just use
302
-     *            this flag to make sure the necessary js gets enqueued on page load.
303
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
304
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The array indicates the max number of columns (4) and the default number of columns on page load (2).  There is an option
305
-     *            in the "screen_options" dropdown that is setup so users can pick what columns they want to display.
306
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
307
-     *                'tab_id' => array(
308
-     *                    'title' => 'tab_title',
309
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting help tab content.  The fallback if it isn't present is to try a the callback.  Filename should match a file in the admin
310
-     *                    folder's "help_tabs" dir (ie.. events/help_tabs/name_of_file_containing_content.help_tab.php)
311
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will attempt to use the callback which should match the name of a method in the class
312
-     *                    ),
313
-     *                'tab2_id' => array(
314
-     *                    'title' => 'tab2 title',
315
-     *                    'filename' => 'file_name_2'
316
-     *                    'callback' => 'callback_method_for_content',
317
-     *                 ),
318
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the help tab area on an admin page. @link http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
319
-     *            'help_tour' => array(
320
-     *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located in a folder for this admin page named "help_tours", a file name matching the key given here
321
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
322
-     *            ),
323
-     *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is true if it isn't present).  To remove the requirement for a nonce check when this route is visited just set
324
-     *            'require_nonce' to FALSE
325
-     *            )
326
-     * )
327
-     *
328
-     * @abstract
329
-     * @access protected
330
-     * @return void
331
-     */
332
-    abstract protected function _set_page_config();
333
-
334
-
335
-
336
-
337
-
338
-    /** end sample help_tour methods **/
339
-    /**
340
-     * _add_screen_options
341
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
342
-     * Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options to a particular view.
343
-     *
344
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
345
-     *         see also WP_Screen object documents...
346
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
347
-     * @abstract
348
-     * @access protected
349
-     * @return void
350
-     */
351
-    abstract protected function _add_screen_options();
352
-
353
-
354
-
355
-    /**
356
-     * _add_feature_pointers
357
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
358
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a particular view.
359
-     * Note: this is just a placeholder for now.  Implementation will come down the road
360
-     * See: WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
361
-     *
362
-     * @link   http://eamann.com/tech/wordpress-portland/
363
-     * @abstract
364
-     * @access protected
365
-     * @return void
366
-     */
367
-    abstract protected function _add_feature_pointers();
368
-
369
-
370
-
371
-    /**
372
-     * load_scripts_styles
373
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific scripts/styles
374
-     * per view by putting them in a dynamic function in this format (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
375
-     *
376
-     * @abstract
377
-     * @access public
378
-     * @return void
379
-     */
380
-    abstract public function load_scripts_styles();
381
-
382
-
383
-
384
-    /**
385
-     * admin_init
386
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to all pages/views loaded by child class.
387
-     *
388
-     * @abstract
389
-     * @access public
390
-     * @return void
391
-     */
392
-    abstract public function admin_init();
393
-
394
-
395
-
396
-    /**
397
-     * admin_notices
398
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to all pages/views loaded by child class.
399
-     *
400
-     * @abstract
401
-     * @access public
402
-     * @return void
403
-     */
404
-    abstract public function admin_notices();
405
-
406
-
407
-
408
-    /**
409
-     * admin_footer_scripts
410
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply to all pages/views loaded by child class.
411
-     *
412
-     * @access public
413
-     * @return void
414
-     */
415
-    abstract public function admin_footer_scripts();
416
-
417
-
418
-
419
-    /**
420
-     * admin_footer
421
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will apply to all pages/views loaded by child class.
422
-     *
423
-     * @access  public
424
-     * @return void
425
-     */
426
-    public function admin_footer()
427
-    {
428
-    }
429
-
430
-
431
-
432
-    /**
433
-     * _global_ajax_hooks
434
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
435
-     * Note: within the ajax callback methods.
436
-     *
437
-     * @abstract
438
-     * @access protected
439
-     * @return void
440
-     */
441
-    protected function _global_ajax_hooks()
442
-    {
443
-        //for lazy loading of metabox content
444
-        add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
445
-    }
446
-
447
-
448
-
449
-    public function ajax_metabox_content()
450
-    {
451
-        $contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
452
-        $url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
453
-        self::cached_rss_display($contentid, $url);
454
-        wp_die();
455
-    }
456
-
457
-
458
-
459
-    /**
460
-     * _page_setup
461
-     * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested doesn't match the object.
462
-     *
463
-     * @final
464
-     * @access protected
465
-     * @return void
466
-     */
467
-    final protected function _page_setup()
468
-    {
469
-        //requires?
470
-        //admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
471
-        add_action('admin_init', array($this, 'admin_init_global'), 5);
472
-        //next verify if we need to load anything...
473
-        $this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
474
-        $this->page_folder = strtolower(str_replace('_Admin_Page', '', str_replace('Extend_', '', get_class($this))));
475
-        global $ee_menu_slugs;
476
-        $ee_menu_slugs = (array)$ee_menu_slugs;
477
-        if (( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page])) && ! defined('DOING_AJAX')) {
478
-            return false;
479
-        }
480
-        // becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
481
-        if (isset($this->_req_data['action2']) && $this->_req_data['action'] == -1) {
482
-            $this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] != -1 ? $this->_req_data['action2'] : $this->_req_data['action'];
483
-        }
484
-        // then set blank or -1 action values to 'default'
485
-        $this->_req_action = isset($this->_req_data['action']) && ! empty($this->_req_data['action']) && $this->_req_data['action'] != -1 ? sanitize_key($this->_req_data['action']) : 'default';
486
-        //if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.  This covers cases where we're coming in from a list table that isn't on the default route.
487
-        $this->_req_action = $this->_req_action == 'default' && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
488
-        //however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
489
-        $this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
490
-        $this->_current_view = $this->_req_action;
491
-        $this->_req_nonce = $this->_req_action . '_nonce';
492
-        $this->_define_page_props();
493
-        $this->_current_page_view_url = add_query_arg(array('page' => $this->_current_page, 'action' => $this->_current_view), $this->_admin_base_url);
494
-        //default things
495
-        $this->_default_espresso_metaboxes = array('_espresso_news_post_box', '_espresso_links_post_box', '_espresso_ratings_request', '_espresso_sponsors_post_box');
496
-        //set page configs
497
-        $this->_set_page_routes();
498
-        $this->_set_page_config();
499
-        //let's include any referrer data in our default_query_args for this route for "stickiness".
500
-        if (isset($this->_req_data['wp_referer'])) {
501
-            $this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
502
-        }
503
-        //for caffeinated and other extended functionality.  If there is a _extend_page_config method then let's run that to modify the all the various page configuration arrays
504
-        if (method_exists($this, '_extend_page_config')) {
505
-            $this->_extend_page_config();
506
-        }
507
-        //for CPT and other extended functionality. If there is an _extend_page_config_for_cpt then let's run that to modify all the various page configuration arrays.
508
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
509
-            $this->_extend_page_config_for_cpt();
510
-        }
511
-        //filter routes and page_config so addons can add their stuff. Filtering done per class
512
-        $this->_page_routes = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_routes', $this->_page_routes, $this);
513
-        $this->_page_config = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_config', $this->_page_config, $this);
514
-        //if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
515
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
516
-            add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view), 10, 2);
517
-        }
518
-        //next route only if routing enabled
519
-        if ($this->_routing && ! defined('DOING_AJAX')) {
520
-            $this->_verify_routes();
521
-            //next let's just check user_access and kill if no access
522
-            $this->check_user_access();
523
-            if ($this->_is_UI_request) {
524
-                //admin_init stuff - global, all views for this page class, specific view
525
-                add_action('admin_init', array($this, 'admin_init'), 10);
526
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
527
-                    add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
528
-                }
529
-            } else {
530
-                //hijack regular WP loading and route admin request immediately
531
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
532
-                $this->route_admin_request();
533
-            }
534
-        }
535
-    }
536
-
537
-
538
-
539
-    /**
540
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
541
-     *
542
-     * @access private
543
-     * @return void
544
-     */
545
-    private function _do_other_page_hooks()
546
-    {
547
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
548
-        foreach ($registered_pages as $page) {
549
-            //now let's setup the file name and class that should be present
550
-            $classname = str_replace('.class.php', '', $page);
551
-            //autoloaders should take care of loading file
552
-            if ( ! class_exists($classname)) {
553
-                $error_msg[] = sprintf(__('Something went wrong with loading the %s admin hooks page.', 'event_espresso'), $page);
554
-                $error_msg[] = $error_msg[0]
555
-                               . "\r\n"
556
-                               . sprintf(__('There is no class in place for the %s admin hooks page.%sMake sure you have <strong>%s</strong> defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
557
-                                'event_espresso'), $page, '<br />', $classname);
558
-                throw new EE_Error(implode('||', $error_msg));
559
-            }
560
-            $a = new ReflectionClass($classname);
561
-            //notice we are passing the instance of this class to the hook object.
562
-            $hookobj[] = $a->newInstance($this);
563
-        }
564
-    }
565
-
566
-
567
-
568
-    public function load_page_dependencies()
569
-    {
570
-        try {
571
-            $this->_load_page_dependencies();
572
-        } catch (EE_Error $e) {
573
-            $e->get_error();
574
-        }
575
-    }
576
-
577
-
578
-
579
-    /**
580
-     * load_page_dependencies
581
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
582
-     *
583
-     * @access public
584
-     * @return void
585
-     */
586
-    protected function _load_page_dependencies()
587
-    {
588
-        //let's set the current_screen and screen options to override what WP set
589
-        $this->_current_screen = get_current_screen();
590
-        //load admin_notices - global, page class, and view specific
591
-        add_action('admin_notices', array($this, 'admin_notices_global'), 5);
592
-        add_action('admin_notices', array($this, 'admin_notices'), 10);
593
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
594
-            add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
595
-        }
596
-        //load network admin_notices - global, page class, and view specific
597
-        add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
598
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
599
-            add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
600
-        }
601
-        //this will save any per_page screen options if they are present
602
-        $this->_set_per_page_screen_options();
603
-        //setup list table properties
604
-        $this->_set_list_table();
605
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.  However in some cases the metaboxes will need to be added within a route handling callback.
606
-        $this->_add_registered_meta_boxes();
607
-        $this->_add_screen_columns();
608
-        //add screen options - global, page child class, and view specific
609
-        $this->_add_global_screen_options();
610
-        $this->_add_screen_options();
611
-        if (method_exists($this, '_add_screen_options_' . $this->_current_view)) {
612
-            call_user_func(array($this, '_add_screen_options_' . $this->_current_view));
613
-        }
614
-        //add help tab(s) and tours- set via page_config and qtips.
615
-        $this->_add_help_tour();
616
-        $this->_add_help_tabs();
617
-        $this->_add_qtips();
618
-        //add feature_pointers - global, page child class, and view specific
619
-        $this->_add_feature_pointers();
620
-        $this->_add_global_feature_pointers();
621
-        if (method_exists($this, '_add_feature_pointer_' . $this->_current_view)) {
622
-            call_user_func(array($this, '_add_feature_pointer_' . $this->_current_view));
623
-        }
624
-        //enqueue scripts/styles - global, page class, and view specific
625
-        add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
626
-        add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
627
-        if (method_exists($this, 'load_scripts_styles_' . $this->_current_view)) {
628
-            add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles_' . $this->_current_view), 15);
629
-        }
630
-        add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
631
-        //admin_print_footer_scripts - global, page child class, and view specific.  NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.  In most cases that's doing_it_wrong().  But adding hidden container elements etc. is a good use case. Notice the late priority we're giving these
632
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
633
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
634
-        if (method_exists($this, 'admin_footer_scripts_' . $this->_current_view)) {
635
-            add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_' . $this->_current_view), 101);
636
-        }
637
-        //admin footer scripts
638
-        add_action('admin_footer', array($this, 'admin_footer_global'), 99);
639
-        add_action('admin_footer', array($this, 'admin_footer'), 100);
640
-        if (method_exists($this, 'admin_footer_' . $this->_current_view)) {
641
-            add_action('admin_footer', array($this, 'admin_footer_' . $this->_current_view), 101);
642
-        }
643
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
644
-        //targeted hook
645
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load__' . $this->page_slug . '__' . $this->_req_action);
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * _set_defaults
652
-     * This sets some global defaults for class properties.
653
-     */
654
-    private function _set_defaults()
655
-    {
656
-        $this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = $this->_event = $this->_template_path = $this->_column_template_path = null;
657
-        $this->_nav_tabs = $this_views = $this->_page_routes = $this->_page_config = $this->_default_route_query_args = array();
658
-        $this->default_nav_tab_name = 'overview';
659
-        //init template args
660
-        $this->_template_args = array(
661
-                'admin_page_header'  => '',
662
-                'admin_page_content' => '',
663
-                'post_body_content'  => '',
664
-                'before_list_table'  => '',
665
-                'after_list_table'   => '',
666
-        );
667
-    }
668
-
669
-
670
-
671
-    /**
672
-     * route_admin_request
673
-     *
674
-     * @see    _route_admin_request()
675
-     * @access public
676
-     * @return void|exception error
677
-     */
678
-    public function route_admin_request()
679
-    {
680
-        try {
681
-            $this->_route_admin_request();
682
-        } catch (EE_Error $e) {
683
-            $e->get_error();
684
-        }
685
-    }
686
-
687
-
688
-
689
-    public function set_wp_page_slug($wp_page_slug)
690
-    {
691
-        $this->_wp_page_slug = $wp_page_slug;
692
-        //if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
693
-        if (is_network_admin()) {
694
-            $this->_wp_page_slug .= '-network';
695
-        }
696
-    }
697
-
698
-
699
-
700
-    /**
701
-     * _verify_routes
702
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so we know if we need to drop out.
703
-     *
704
-     * @access protected
705
-     * @return void
706
-     */
707
-    protected function _verify_routes()
708
-    {
709
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
710
-        if ( ! $this->_current_page && ! defined('DOING_AJAX')) {
711
-            return false;
712
-        }
713
-        $this->_route = false;
714
-        $func = false;
715
-        $args = array();
716
-        // check that the page_routes array is not empty
717
-        if (empty($this->_page_routes)) {
718
-            // user error msg
719
-            $error_msg = sprintf(__('No page routes have been set for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
720
-            // developer error msg
721
-            $error_msg .= '||' . $error_msg . __(' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.', 'event_espresso');
722
-            throw new EE_Error($error_msg);
723
-        }
724
-        // and that the requested page route exists
725
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
726
-            $this->_route = $this->_page_routes[$this->_req_action];
727
-            $this->_route_config = isset($this->_page_config[$this->_req_action]) ? $this->_page_config[$this->_req_action] : array();
728
-        } else {
729
-            // user error msg
730
-            $error_msg = sprintf(__('The requested page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
731
-            // developer error msg
732
-            $error_msg .= '||' . $error_msg . sprintf(__(' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.', 'event_espresso'), $this->_req_action);
733
-            throw new EE_Error($error_msg);
734
-        }
735
-        // and that a default route exists
736
-        if ( ! array_key_exists('default', $this->_page_routes)) {
737
-            // user error msg
738
-            $error_msg = sprintf(__('A default page route has not been set for the % admin page.', 'event_espresso'), $this->_admin_page_title);
739
-            // developer error msg
740
-            $error_msg .= '||' . $error_msg . __(' Create a key in the "_page_routes" array named "default" and set its value to your default page method.', 'event_espresso');
741
-            throw new EE_Error($error_msg);
742
-        }
743
-        //first lets' catch if the UI request has EVER been set.
744
-        if ($this->_is_UI_request === null) {
745
-            //lets set if this is a UI request or not.
746
-            $this->_is_UI_request = ( ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true) ? true : false;
747
-            //wait a minute... we might have a noheader in the route array
748
-            $this->_is_UI_request = is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader'] ? false : $this->_is_UI_request;
749
-        }
750
-        $this->_set_current_labels();
751
-    }
752
-
753
-
754
-
755
-    /**
756
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
757
-     *
758
-     * @param  string $route the route name we're verifying
759
-     * @return mixed  (bool|Exception)      we'll throw an exception if this isn't a valid route.
760
-     */
761
-    protected function _verify_route($route)
762
-    {
763
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
764
-            return true;
765
-        } else {
766
-            // user error msg
767
-            $error_msg = sprintf(__('The given page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
768
-            // developer error msg
769
-            $error_msg .= '||' . $error_msg . sprintf(__(' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property', 'event_espresso'), $route);
770
-            throw new EE_Error($error_msg);
771
-        }
772
-    }
773
-
774
-
775
-
776
-    /**
777
-     * perform nonce verification
778
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces using this method (and save retyping!)
779
-     *
780
-     * @param  string $nonce     The nonce sent
781
-     * @param  string $nonce_ref The nonce reference string (name0)
782
-     * @return mixed (bool|die)
783
-     */
784
-    protected function _verify_nonce($nonce, $nonce_ref)
785
-    {
786
-        // verify nonce against expected value
787
-        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
788
-            // these are not the droids you are looking for !!!
789
-            $msg = sprintf(__('%sNonce Fail.%s', 'event_espresso'), '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">', '</a>');
790
-            if (WP_DEBUG) {
791
-                $msg .= "\n  " . sprintf(__('In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!', 'event_espresso'), __CLASS__);
792
-            }
793
-            if ( ! defined('DOING_AJAX')) {
794
-                wp_die($msg);
795
-            } else {
796
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
797
-                $this->_return_json();
798
-            }
799
-        }
800
-    }
801
-
802
-
803
-
804
-    /**
805
-     * _route_admin_request()
806
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
807
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
808
-     * in the page routes and then will try to load the corresponding method.
809
-     *
810
-     * @access protected
811
-     * @return void
812
-     * @throws \EE_Error
813
-     */
814
-    protected function _route_admin_request()
815
-    {
816
-        if ( ! $this->_is_UI_request) {
817
-            $this->_verify_routes();
818
-        }
819
-        $nonce_check = isset($this->_route_config['require_nonce'])
820
-            ? $this->_route_config['require_nonce']
821
-            : true;
822
-        if ($this->_req_action !== 'default' && $nonce_check) {
823
-            // set nonce from post data
824
-            $nonce = isset($this->_req_data[$this->_req_nonce])
825
-                ? sanitize_text_field($this->_req_data[$this->_req_nonce])
826
-                : '';
827
-            $this->_verify_nonce($nonce, $this->_req_nonce);
828
-        }
829
-        //set the nav_tabs array but ONLY if this is  UI_request
830
-        if ($this->_is_UI_request) {
831
-            $this->_set_nav_tabs();
832
-        }
833
-        // grab callback function
834
-        $func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
835
-        // check if callback has args
836
-        $args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
837
-        $error_msg = '';
838
-        // action right before calling route
839
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
840
-        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
841
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
842
-        }
843
-        // right before calling the route, let's remove _wp_http_referer from the
844
-        // $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
845
-        $_SERVER['REQUEST_URI'] = remove_query_arg('_wp_http_referer', wp_unslash($_SERVER['REQUEST_URI']));
846
-        if ( ! empty($func)) {
847
-            if (is_array($func)) {
848
-                list($class, $method) = $func;
849
-            } else if (strpos($func, '::') !== false) {
850
-                list($class, $method) = explode('::', $func);
851
-            } else {
852
-                $class = $this;
853
-                $method = $func;
854
-            }
855
-            if ( ! (is_object($class) && $class === $this)) {
856
-                // send along this admin page object for access by addons.
857
-                $args['admin_page_object'] = $this;
858
-            }
859
-
860
-            if (
861
-                //is it a method on a class that doesn't work?
862
-                (
863
-                    (
864
-                        method_exists($class, $method)
865
-                        && call_user_func_array(array($class, $method), $args) === false
866
-                    )
867
-                    && (
868
-                        //is it a standalone function that doesn't work?
869
-                        function_exists($method)
870
-                        && call_user_func_array($func, array_merge(array('admin_page_object' => $this), $args)) === false
871
-                    )
872
-                )
873
-                || (
874
-                    //is it neither a class method NOR a standalone function?
875
-                    ! method_exists($class, $method)
876
-                    && ! function_exists($method)
877
-                )
878
-            ) {
879
-                // user error msg
880
-                $error_msg = __('An error occurred. The  requested page route could not be found.', 'event_espresso');
881
-                // developer error msg
882
-                $error_msg .= '||';
883
-                $error_msg .= sprintf(
884
-                    __(
885
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
886
-                        'event_espresso'
887
-                    ),
888
-                    $method
889
-                );
890
-            }
891
-            if ( ! empty($error_msg)) {
892
-                throw new EE_Error($error_msg);
893
-            }
894
-        }
895
-        //if we've routed and this route has a no headers route AND a sent_headers_route, then we need to reset the routing properties to the new route.
896
-        //now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
897
-        if ($this->_is_UI_request === false
898
-            && is_array($this->_route)
899
-            && ! empty($this->_route['headers_sent_route'])
900
-        ) {
901
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
902
-        }
903
-    }
904
-
905
-
906
-
907
-    /**
908
-     * This method just allows the resetting of page properties in the case where a no headers
909
-     * route redirects to a headers route in its route config.
910
-     *
911
-     * @since   4.3.0
912
-     * @param  string $new_route New (non header) route to redirect to.
913
-     * @return   void
914
-     */
915
-    protected function _reset_routing_properties($new_route)
916
-    {
917
-        $this->_is_UI_request = true;
918
-        //now we set the current route to whatever the headers_sent_route is set at
919
-        $this->_req_data['action'] = $new_route;
920
-        //rerun page setup
921
-        $this->_page_setup();
922
-    }
923
-
924
-
925
-
926
-    /**
927
-     * _add_query_arg
928
-     * adds nonce to array of arguments then calls WP add_query_arg function
929
-     *(internally just uses EEH_URL's function with the same name)
930
-     *
931
-     * @access public
932
-     * @param array  $args
933
-     * @param string $url
934
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the generated
935
-     *                                        url in an associative array indexed by the key 'wp_referer';
936
-     *                                        Example usage:
937
-     *                                        If the current page is:
938
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
939
-     *                                        &action=default&event_id=20&month_range=March%202015
940
-     *                                        &_wpnonce=5467821
941
-     *                                        and you call:
942
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
943
-     *                                        array(
944
-     *                                        'action' => 'resend_something',
945
-     *                                        'page=>espresso_registrations'
946
-     *                                        ),
947
-     *                                        $some_url,
948
-     *                                        true
949
-     *                                        );
950
-     *                                        It will produce a url in this structure:
951
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
952
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
953
-     *                                        month_range]=March%202015
954
-     * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
955
-     * @return string
956
-     */
957
-    public static function add_query_args_and_nonce($args = array(), $url = false, $sticky = false, $exclude_nonce = false)
958
-    {
959
-        //if there is a _wp_http_referer include the values from the request but only if sticky = true
960
-        if ($sticky) {
961
-            $request = $_REQUEST;
962
-            unset($request['_wp_http_referer']);
963
-            unset($request['wp_referer']);
964
-            foreach ($request as $key => $value) {
965
-                //do not add nonces
966
-                if (strpos($key, 'nonce') !== false) {
967
-                    continue;
968
-                }
969
-                $args['wp_referer[' . $key . ']'] = $value;
970
-            }
971
-        }
972
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
973
-    }
974
-
975
-
976
-
977
-    /**
978
-     * This returns a generated link that will load the related help tab.
979
-     *
980
-     * @param  string $help_tab_id the id for the connected help tab
981
-     * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
982
-     * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
983
-     * @uses EEH_Template::get_help_tab_link()
984
-     * @return string              generated link
985
-     */
986
-    protected function _get_help_tab_link($help_tab_id, $icon_style = false, $help_text = false)
987
-    {
988
-        return EEH_Template::get_help_tab_link($help_tab_id, $this->page_slug, $this->_req_action, $icon_style, $help_text);
989
-    }
990
-
991
-
992
-
993
-    /**
994
-     * _add_help_tabs
995
-     * Note child classes define their help tabs within the page_config array.
996
-     *
997
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
998
-     * @access protected
999
-     * @return void
1000
-     */
1001
-    protected function _add_help_tabs()
1002
-    {
1003
-        $tour_buttons = '';
1004
-        if (isset($this->_page_config[$this->_req_action])) {
1005
-            $config = $this->_page_config[$this->_req_action];
1006
-            //is there a help tour for the current route?  if there is let's setup the tour buttons
1007
-            if (isset($this->_help_tour[$this->_req_action])) {
1008
-                $tb = array();
1009
-                $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1010
-                foreach ($this->_help_tour['tours'] as $tour) {
1011
-                    //if this is the end tour then we don't need to setup a button
1012
-                    if ($tour instanceof EE_Help_Tour_final_stop) {
1013
-                        continue;
1014
-                    }
1015
-                    $tb[] = '<button id="trigger-tour-' . $tour->get_slug() . '" class="button-primary trigger-ee-help-tour">' . $tour->get_label() . '</button>';
1016
-                }
1017
-                $tour_buttons .= implode('<br />', $tb);
1018
-                $tour_buttons .= '</div></div>';
1019
-            }
1020
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1021
-            if (is_array($config) && isset($config['help_sidebar'])) {
1022
-                //check that the callback given is valid
1023
-                if ( ! method_exists($this, $config['help_sidebar'])) {
1024
-                    throw new EE_Error(sprintf(__('The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1025
-                            'event_espresso'), $config['help_sidebar'], get_class($this)));
1026
-                }
1027
-                $content = apply_filters('FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar', call_user_func(array($this, $config['help_sidebar'])));
1028
-                $content .= $tour_buttons; //add help tour buttons.
1029
-                //do we have any help tours setup?  Cause if we do we want to add the buttons
1030
-                $this->_current_screen->set_help_sidebar($content);
1031
-            }
1032
-            //if we DON'T have config help sidebar and there ARE toure buttons then we'll just add the tour buttons to the sidebar.
1033
-            if ( ! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1034
-                $this->_current_screen->set_help_sidebar($tour_buttons);
1035
-            }
1036
-            //handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1037
-            if ( ! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1038
-                $_ht['id'] = $this->page_slug;
1039
-                $_ht['title'] = __('Help Tours', 'event_espresso');
1040
-                $_ht['content'] = '<p>' . __('The buttons to the right allow you to start/restart any help tours available for this page', 'event_espresso') . '</p>';
1041
-                $this->_current_screen->add_help_tab($_ht);
1042
-            }/**/
1043
-            if ( ! isset($config['help_tabs'])) {
1044
-                return;
1045
-            } //no help tabs for this route
1046
-            foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1047
-                //we're here so there ARE help tabs!
1048
-                //make sure we've got what we need
1049
-                if ( ! isset($cfg['title'])) {
1050
-                    throw new EE_Error(__('The _page_config array is not set up properly for help tabs.  It is missing a title', 'event_espresso'));
1051
-                }
1052
-                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1053
-                    throw new EE_Error(__('The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1054
-                            'event_espresso'));
1055
-                }
1056
-                //first priority goes to content.
1057
-                if ( ! empty($cfg['content'])) {
1058
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1059
-                    //second priority goes to filename
1060
-                } else if ( ! empty($cfg['filename'])) {
1061
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1062
-                    //it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1063
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tabs/' . $cfg['filename'] . '.help_tab.php' : $file_path;
1064
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1065
-                    if ( ! is_readable($file_path) && ! isset($cfg['callback'])) {
1066
-                        EE_Error::add_error(sprintf(__('The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1067
-                                'event_espresso'), $tab_id, key($config), $file_path), __FILE__, __FUNCTION__, __LINE__);
1068
-                        return;
1069
-                    }
1070
-                    $template_args['admin_page_obj'] = $this;
1071
-                    $content = EEH_Template::display_template($file_path, $template_args, true);
1072
-                } else {
1073
-                    $content = '';
1074
-                }
1075
-                //check if callback is valid
1076
-                if (empty($content) && ( ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback']))) {
1077
-                    EE_Error::add_error(sprintf(__('The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1078
-                            'event_espresso'), $cfg['title']), __FILE__, __FUNCTION__, __LINE__);
1079
-                    return;
1080
-                }
1081
-                //setup config array for help tab method
1082
-                $id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1083
-                $_ht = array(
1084
-                        'id'       => $id,
1085
-                        'title'    => $cfg['title'],
1086
-                        'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1087
-                        'content'  => $content,
1088
-                );
1089
-                $this->_current_screen->add_help_tab($_ht);
1090
-            }
1091
-        }
1092
-    }
1093
-
1094
-
1095
-
1096
-    /**
1097
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is an array with properties for setting up usage of the joyride plugin
1098
-     *
1099
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1100
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the _set_page_config() comments
1101
-     * @access protected
1102
-     * @return void
1103
-     */
1104
-    protected function _add_help_tour()
1105
-    {
1106
-        $tours = array();
1107
-        $this->_help_tour = array();
1108
-        //exit early if help tours are turned off globally
1109
-        if ( ! EE_Registry::instance()->CFG->admin->help_tour_activation || (defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)) {
1110
-            return;
1111
-        }
1112
-        //loop through _page_config to find any help_tour defined
1113
-        foreach ($this->_page_config as $route => $config) {
1114
-            //we're only going to set things up for this route
1115
-            if ($route !== $this->_req_action) {
1116
-                continue;
1117
-            }
1118
-            if (isset($config['help_tour'])) {
1119
-                foreach ($config['help_tour'] as $tour) {
1120
-                    $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1121
-                    //let's see if we can get that file... if not its possible this is a decaf route not set in caffienated so lets try and get the caffeinated equivalent
1122
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tours/' . $tour . '.class.php' : $file_path;
1123
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1124
-                    if ( ! is_readable($file_path)) {
1125
-                        EE_Error::add_error(sprintf(__('The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling', 'event_espresso'),
1126
-                                $file_path, $tour), __FILE__, __FUNCTION__, __LINE__);
1127
-                        return;
1128
-                    }
1129
-                    require_once $file_path;
1130
-                    if ( ! class_exists($tour)) {
1131
-                        $error_msg[] = sprintf(__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'), $tour);
1132
-                        $error_msg[] = $error_msg[0] . "\r\n" . sprintf(__('There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1133
-                                        'event_espresso'), $tour, '<br />', $tour, $this->_req_action, get_class($this));
1134
-                        throw new EE_Error(implode('||', $error_msg));
1135
-                    }
1136
-                    $a = new ReflectionClass($tour);
1137
-                    $tour_obj = $a->newInstance($this->_is_caf);
1138
-                    $tours[] = $tour_obj;
1139
-                    $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1140
-                }
1141
-                //let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1142
-                $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1143
-                $tours[] = $end_stop_tour;
1144
-                $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1145
-            }
1146
-        }
1147
-        if ( ! empty($tours)) {
1148
-            $this->_help_tour['tours'] = $tours;
1149
-        }
1150
-        //thats it!  Now that the $_help_tours property is set (or not) the scripts and html should be taken care of automatically.
1151
-    }
1152
-
1153
-
1154
-
1155
-    /**
1156
-     * This simply sets up any qtips that have been defined in the page config
1157
-     *
1158
-     * @access protected
1159
-     * @return void
1160
-     */
1161
-    protected function _add_qtips()
1162
-    {
1163
-        if (isset($this->_route_config['qtips'])) {
1164
-            $qtips = (array)$this->_route_config['qtips'];
1165
-            //load qtip loader
1166
-            $path = array(
1167
-                    $this->_get_dir() . '/qtips/',
1168
-                    EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1169
-            );
1170
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1171
-        }
1172
-    }
1173
-
1174
-
1175
-
1176
-    /**
1177
-     * _set_nav_tabs
1178
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you wish to add additional tabs or modify accordingly.
1179
-     *
1180
-     * @access protected
1181
-     * @return void
1182
-     */
1183
-    protected function _set_nav_tabs()
1184
-    {
1185
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1186
-        $i = 0;
1187
-        foreach ($this->_page_config as $slug => $config) {
1188
-            if ( ! is_array($config) || (is_array($config) && (isset($config['nav']) && ! $config['nav']) || ! isset($config['nav']))) {
1189
-                continue;
1190
-            } //no nav tab for this config
1191
-            //check for persistent flag
1192
-            if (isset($config['nav']['persistent']) && ! $config['nav']['persistent'] && $slug !== $this->_req_action) {
1193
-                continue;
1194
-            } //nav tab is only to appear when route requested.
1195
-            if ( ! $this->check_user_access($slug, true)) {
1196
-                continue;
1197
-            } //no nav tab becasue current user does not have access.
1198
-            $css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1199
-            $this->_nav_tabs[$slug] = array(
1200
-                    'url'       => isset($config['nav']['url']) ? $config['nav']['url'] : self::add_query_args_and_nonce(array('action' => $slug), $this->_admin_base_url),
1201
-                    'link_text' => isset($config['nav']['label']) ? $config['nav']['label'] : ucwords(str_replace('_', ' ', $slug)),
1202
-                    'css_class' => $this->_req_action == $slug ? $css_class . 'nav-tab-active' : $css_class,
1203
-                    'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1204
-            );
1205
-            $i++;
1206
-        }
1207
-        //if $this->_nav_tabs is empty then lets set the default
1208
-        if (empty($this->_nav_tabs)) {
1209
-            $this->_nav_tabs[$this->default_nav_tab_name] = array(
1210
-                    'url'       => $this->admin_base_url,
1211
-                    'link_text' => ucwords(str_replace('_', ' ', $this->default_nav_tab_name)),
1212
-                    'css_class' => 'nav-tab-active',
1213
-                    'order'     => 10,
1214
-            );
1215
-        }
1216
-        //now let's sort the tabs according to order
1217
-        usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1218
-    }
1219
-
1220
-
1221
-
1222
-    /**
1223
-     * _set_current_labels
1224
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes property array
1225
-     *
1226
-     * @access private
1227
-     * @return void
1228
-     */
1229
-    private function _set_current_labels()
1230
-    {
1231
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1232
-            foreach ($this->_route_config['labels'] as $label => $text) {
1233
-                if (is_array($text)) {
1234
-                    foreach ($text as $sublabel => $subtext) {
1235
-                        $this->_labels[$label][$sublabel] = $subtext;
1236
-                    }
1237
-                } else {
1238
-                    $this->_labels[$label] = $text;
1239
-                }
1240
-            }
1241
-        }
1242
-    }
1243
-
1244
-
1245
-
1246
-    /**
1247
-     *        verifies user access for this admin page
1248
-     *
1249
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1250
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just return false if verify fail.
1251
-     * @return        BOOL|wp_die()
1252
-     */
1253
-    public function check_user_access($route_to_check = '', $verify_only = false)
1254
-    {
1255
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1256
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1257
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check]) && is_array($this->_page_routes[$route_to_check]) && ! empty($this->_page_routes[$route_to_check]['capability'])
1258
-                ? $this->_page_routes[$route_to_check]['capability'] : null;
1259
-        if (empty($capability) && empty($route_to_check)) {
1260
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options' : $this->_route['capability'];
1261
-        } else {
1262
-            $capability = empty($capability) ? 'manage_options' : $capability;
1263
-        }
1264
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1265
-        if (( ! function_exists('is_admin') || ! EE_Registry::instance()->CAP->current_user_can($capability, $this->page_slug . '_' . $route_to_check, $id)) && ! defined('DOING_AJAX')) {
1266
-            if ($verify_only) {
1267
-                return false;
1268
-            } else {
1269
-                if ( is_user_logged_in() ) {
1270
-                    wp_die(__('You do not have access to this route.', 'event_espresso'));
1271
-                } else {
1272
-                    return false;
1273
-                }
1274
-            }
1275
-        }
1276
-        return true;
1277
-    }
1278
-
1279
-
1280
-
1281
-    /**
1282
-     * admin_init_global
1283
-     * This runs all the code that we want executed within the WP admin_init hook.
1284
-     * This method executes for ALL EE Admin pages.
1285
-     *
1286
-     * @access public
1287
-     * @return void
1288
-     */
1289
-    public function admin_init_global()
1290
-    {
1291
-    }
1292
-
1293
-
1294
-
1295
-    /**
1296
-     * wp_loaded_global
1297
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an EE_Admin page and will execute on every EE Admin Page load
1298
-     *
1299
-     * @access public
1300
-     * @return void
1301
-     */
1302
-    public function wp_loaded()
1303
-    {
1304
-    }
1305
-
1306
-
1307
-
1308
-    /**
1309
-     * admin_notices
1310
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on ALL EE_Admin pages.
1311
-     *
1312
-     * @access public
1313
-     * @return void
1314
-     */
1315
-    public function admin_notices_global()
1316
-    {
1317
-        $this->_display_no_javascript_warning();
1318
-        $this->_display_espresso_notices();
1319
-    }
1320
-
1321
-
1322
-
1323
-    public function network_admin_notices_global()
1324
-    {
1325
-        $this->_display_no_javascript_warning();
1326
-        $this->_display_espresso_notices();
1327
-    }
1328
-
1329
-
1330
-
1331
-    /**
1332
-     * admin_footer_scripts_global
1333
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply on ALL EE_Admin pages.
1334
-     *
1335
-     * @access public
1336
-     * @return void
1337
-     */
1338
-    public function admin_footer_scripts_global()
1339
-    {
1340
-        $this->_add_admin_page_ajax_loading_img();
1341
-        $this->_add_admin_page_overlay();
1342
-        //if metaboxes are present we need to add the nonce field
1343
-        if ((isset($this->_route_config['metaboxes']) || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes']) || isset($this->_route_config['list_table']))) {
1344
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1345
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1346
-        }
1347
-    }
1348
-
1349
-
1350
-
1351
-    /**
1352
-     * admin_footer_global
1353
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particluar method will apply on ALL EE_Admin Pages.
1354
-     *
1355
-     * @access  public
1356
-     * @return  void
1357
-     */
1358
-    public function admin_footer_global()
1359
-    {
1360
-        //dialog container for dialog helper
1361
-        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1362
-        $d_cont .= '<div class="ee-notices"></div>';
1363
-        $d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1364
-        $d_cont .= '</div>';
1365
-        echo $d_cont;
1366
-        //help tour stuff?
1367
-        if (isset($this->_help_tour[$this->_req_action])) {
1368
-            echo implode('<br />', $this->_help_tour[$this->_req_action]);
1369
-        }
1370
-        //current set timezone for timezone js
1371
-        echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1372
-    }
1373
-
1374
-
1375
-
1376
-    /**
1377
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then we'll use the retrieved array to output the content using the template.
1378
-     * For child classes:
1379
-     * If you want to have help popups then in your templates or your content you set "triggers" for the content using the "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method for
1380
-     * the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content for the
1381
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1382
-     *    'help_trigger_id' => array(
1383
-     *        'title' => __('localized title for popup', 'event_espresso'),
1384
-     *        'content' => __('localized content for popup', 'event_espresso')
1385
-     *    )
1386
-     * );
1387
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1388
-     *
1389
-     * @access protected
1390
-     * @return string content
1391
-     */
1392
-    protected function _set_help_popup_content($help_array = array(), $display = false)
1393
-    {
1394
-        $content = '';
1395
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1396
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php';
1397
-        //loop through the array and setup content
1398
-        foreach ($help_array as $trigger => $help) {
1399
-            //make sure the array is setup properly
1400
-            if ( ! isset($help['title']) || ! isset($help['content'])) {
1401
-                throw new EE_Error(__('Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1402
-                        'event_espresso'));
1403
-            }
1404
-            //we're good so let'd setup the template vars and then assign parsed template content to our content.
1405
-            $template_args = array(
1406
-                    'help_popup_id'      => $trigger,
1407
-                    'help_popup_title'   => $help['title'],
1408
-                    'help_popup_content' => $help['content'],
1409
-            );
1410
-            $content .= EEH_Template::display_template($template_path, $template_args, true);
1411
-        }
1412
-        if ($display) {
1413
-            echo $content;
1414
-        } else {
1415
-            return $content;
1416
-        }
1417
-    }
1418
-
1419
-
1420
-
1421
-    /**
1422
-     * All this does is retrive the help content array if set by the EE_Admin_Page child
1423
-     *
1424
-     * @access private
1425
-     * @return array properly formatted array for help popup content
1426
-     */
1427
-    private function _get_help_content()
1428
-    {
1429
-        //what is the method we're looking for?
1430
-        $method_name = '_help_popup_content_' . $this->_req_action;
1431
-        //if method doesn't exist let's get out.
1432
-        if ( ! method_exists($this, $method_name)) {
1433
-            return array();
1434
-        }
1435
-        //k we're good to go let's retrieve the help array
1436
-        $help_array = call_user_func(array($this, $method_name));
1437
-        //make sure we've got an array!
1438
-        if ( ! is_array($help_array)) {
1439
-            throw new EE_Error(__('Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.', 'event_espresso'));
1440
-        }
1441
-        return $help_array;
1442
-    }
1443
-
1444
-
1445
-
1446
-    /**
1447
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1448
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1449
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1450
-     *
1451
-     * @access protected
1452
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1453
-     * @param boolean $display    if false then we return the trigger string
1454
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1455
-     * @return string
1456
-     */
1457
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1458
-    {
1459
-        if (defined('DOING_AJAX')) {
1460
-            return;
1461
-        }
1462
-        //let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1463
-        $help_array = $this->_get_help_content();
1464
-        $help_content = '';
1465
-        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1466
-            $help_array[$trigger_id] = array(
1467
-                    'title'   => __('Missing Content', 'event_espresso'),
1468
-                    'content' => __('A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1469
-                            'event_espresso'),
1470
-            );
1471
-            $help_content = $this->_set_help_popup_content($help_array, false);
1472
-        }
1473
-        //let's setup the trigger
1474
-        $content = '<a class="ee-dialog" href="?height=' . $dimensions[0] . '&width=' . $dimensions[1] . '&inlineId=' . $trigger_id . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1475
-        $content = $content . $help_content;
1476
-        if ($display) {
1477
-            echo $content;
1478
-        } else {
1479
-            return $content;
1480
-        }
1481
-    }
1482
-
1483
-
1484
-
1485
-    /**
1486
-     * _add_global_screen_options
1487
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1488
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1489
-     *
1490
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1491
-     *         see also WP_Screen object documents...
1492
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1493
-     * @abstract
1494
-     * @access private
1495
-     * @return void
1496
-     */
1497
-    private function _add_global_screen_options()
1498
-    {
1499
-    }
1500
-
1501
-
1502
-
1503
-    /**
1504
-     * _add_global_feature_pointers
1505
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1506
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1507
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1508
-     *
1509
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
1510
-     * @link   http://eamann.com/tech/wordpress-portland/
1511
-     * @abstract
1512
-     * @access protected
1513
-     * @return void
1514
-     */
1515
-    private function _add_global_feature_pointers()
1516
-    {
1517
-    }
1518
-
1519
-
1520
-
1521
-    /**
1522
-     * load_global_scripts_styles
1523
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1524
-     *
1525
-     * @return void
1526
-     */
1527
-    public function load_global_scripts_styles()
1528
-    {
1529
-        /** STYLES **/
1530
-        // add debugging styles
1531
-        if (WP_DEBUG) {
1532
-            add_action('admin_head', array($this, 'add_xdebug_style'));
1533
-        }
1534
-        //register all styles
1535
-        wp_register_style('espresso-ui-theme', EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css', array(), EVENT_ESPRESSO_VERSION);
1536
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1537
-        //helpers styles
1538
-        wp_register_style('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css', array(), EVENT_ESPRESSO_VERSION);
1539
-        //enqueue global styles
1540
-        wp_enqueue_style('ee-admin-css');
1541
-        /** SCRIPTS **/
1542
-        //register all scripts
1543
-        wp_register_script('espresso_core', EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1544
-        wp_register_script('ee-dialog', EE_ADMIN_URL . 'assets/ee-dialog-helper.js', array('jquery', 'jquery-ui-draggable'), EVENT_ESPRESSO_VERSION, true);
1545
-        wp_register_script('ee_admin_js', EE_ADMIN_URL . 'assets/ee-admin-page.js', array('espresso_core', 'ee-parse-uri', 'ee-dialog'), EVENT_ESPRESSO_VERSION, true);
1546
-        wp_register_script('jquery-ui-timepicker-addon', EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js', array('jquery-ui-datepicker', 'jquery-ui-slider'), EVENT_ESPRESSO_VERSION, true);
1547
-        // register jQuery Validate - see /includes/functions/wp_hooks.php
1548
-        add_filter('FHEE_load_jquery_validate', '__return_true');
1549
-        add_filter('FHEE_load_joyride', '__return_true');
1550
-        //script for sorting tables
1551
-        wp_register_script('espresso_ajax_table_sorting', EE_ADMIN_URL . "assets/espresso_ajax_table_sorting.js", array('ee_admin_js', 'jquery-ui-sortable'), EVENT_ESPRESSO_VERSION, true);
1552
-        //script for parsing uri's
1553
-        wp_register_script('ee-parse-uri', EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js', array(), EVENT_ESPRESSO_VERSION, true);
1554
-        //and parsing associative serialized form elements
1555
-        wp_register_script('ee-serialize-full-array', EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1556
-        //helpers scripts
1557
-        wp_register_script('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1558
-        wp_register_script('ee-moment-core', EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js', array(), EVENT_ESPRESSO_VERSION, true);
1559
-        wp_register_script('ee-moment', EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js', array('ee-moment-core'), EVENT_ESPRESSO_VERSION, true);
1560
-        wp_register_script('ee-datepicker', EE_ADMIN_URL . 'assets/ee-datepicker.js', array('jquery-ui-timepicker-addon', 'ee-moment'), EVENT_ESPRESSO_VERSION, true);
1561
-        //google charts
1562
-        wp_register_script('google-charts', 'https://www.gstatic.com/charts/loader.js', array(), EVENT_ESPRESSO_VERSION, false);
1563
-        //enqueue global scripts
1564
-        //taking care of metaboxes
1565
-        if ((isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes'])) && empty($this->_cpt_route)) {
1566
-            wp_enqueue_script('dashboard');
1567
-        }
1568
-        //enqueue thickbox for ee help popups.  default is to enqueue unless its explicitly set to false since we're assuming all EE pages will have popups
1569
-        if ( ! isset($this->_route_config['has_help_popups']) || (isset($this->_route_config['has_help_popups']) && $this->_route_config['has_help_popups'])) {
1570
-            wp_enqueue_script('ee_admin_js');
1571
-            wp_enqueue_style('ee-admin-css');
1572
-        }
1573
-        //localize script for ajax lazy loading
1574
-        $lazy_loader_container_ids = apply_filters('FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers', array('espresso_news_post_box_content'));
1575
-        wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1576
-        /**
1577
-         * help tour stuff
1578
-         */
1579
-        if ( ! empty($this->_help_tour)) {
1580
-            //register the js for kicking things off
1581
-            wp_enqueue_script('ee-help-tour', EE_ADMIN_URL . 'assets/ee-help-tour.js', array('jquery-joyride'), EVENT_ESPRESSO_VERSION, true);
1582
-            //setup tours for the js tour object
1583
-            foreach ($this->_help_tour['tours'] as $tour) {
1584
-                $tours[] = array(
1585
-                        'id'      => $tour->get_slug(),
1586
-                        'options' => $tour->get_options(),
1587
-                );
1588
-            }
1589
-            wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
1590
-            //admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1591
-        }
1592
-    }
1593
-
1594
-
1595
-
1596
-    /**
1597
-     *        admin_footer_scripts_eei18n_js_strings
1598
-     *
1599
-     * @access        public
1600
-     * @return        void
1601
-     */
1602
-    public function admin_footer_scripts_eei18n_js_strings()
1603
-    {
1604
-        EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
1605
-        EE_Registry::$i18n_js_strings['confirm_delete'] = __('Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!', 'event_espresso');
1606
-        EE_Registry::$i18n_js_strings['January'] = __('January', 'event_espresso');
1607
-        EE_Registry::$i18n_js_strings['February'] = __('February', 'event_espresso');
1608
-        EE_Registry::$i18n_js_strings['March'] = __('March', 'event_espresso');
1609
-        EE_Registry::$i18n_js_strings['April'] = __('April', 'event_espresso');
1610
-        EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1611
-        EE_Registry::$i18n_js_strings['June'] = __('June', 'event_espresso');
1612
-        EE_Registry::$i18n_js_strings['July'] = __('July', 'event_espresso');
1613
-        EE_Registry::$i18n_js_strings['August'] = __('August', 'event_espresso');
1614
-        EE_Registry::$i18n_js_strings['September'] = __('September', 'event_espresso');
1615
-        EE_Registry::$i18n_js_strings['October'] = __('October', 'event_espresso');
1616
-        EE_Registry::$i18n_js_strings['November'] = __('November', 'event_espresso');
1617
-        EE_Registry::$i18n_js_strings['December'] = __('December', 'event_espresso');
1618
-        EE_Registry::$i18n_js_strings['Jan'] = __('Jan', 'event_espresso');
1619
-        EE_Registry::$i18n_js_strings['Feb'] = __('Feb', 'event_espresso');
1620
-        EE_Registry::$i18n_js_strings['Mar'] = __('Mar', 'event_espresso');
1621
-        EE_Registry::$i18n_js_strings['Apr'] = __('Apr', 'event_espresso');
1622
-        EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1623
-        EE_Registry::$i18n_js_strings['Jun'] = __('Jun', 'event_espresso');
1624
-        EE_Registry::$i18n_js_strings['Jul'] = __('Jul', 'event_espresso');
1625
-        EE_Registry::$i18n_js_strings['Aug'] = __('Aug', 'event_espresso');
1626
-        EE_Registry::$i18n_js_strings['Sep'] = __('Sep', 'event_espresso');
1627
-        EE_Registry::$i18n_js_strings['Oct'] = __('Oct', 'event_espresso');
1628
-        EE_Registry::$i18n_js_strings['Nov'] = __('Nov', 'event_espresso');
1629
-        EE_Registry::$i18n_js_strings['Dec'] = __('Dec', 'event_espresso');
1630
-        EE_Registry::$i18n_js_strings['Sunday'] = __('Sunday', 'event_espresso');
1631
-        EE_Registry::$i18n_js_strings['Monday'] = __('Monday', 'event_espresso');
1632
-        EE_Registry::$i18n_js_strings['Tuesday'] = __('Tuesday', 'event_espresso');
1633
-        EE_Registry::$i18n_js_strings['Wednesday'] = __('Wednesday', 'event_espresso');
1634
-        EE_Registry::$i18n_js_strings['Thursday'] = __('Thursday', 'event_espresso');
1635
-        EE_Registry::$i18n_js_strings['Friday'] = __('Friday', 'event_espresso');
1636
-        EE_Registry::$i18n_js_strings['Saturday'] = __('Saturday', 'event_espresso');
1637
-        EE_Registry::$i18n_js_strings['Sun'] = __('Sun', 'event_espresso');
1638
-        EE_Registry::$i18n_js_strings['Mon'] = __('Mon', 'event_espresso');
1639
-        EE_Registry::$i18n_js_strings['Tue'] = __('Tue', 'event_espresso');
1640
-        EE_Registry::$i18n_js_strings['Wed'] = __('Wed', 'event_espresso');
1641
-        EE_Registry::$i18n_js_strings['Thu'] = __('Thu', 'event_espresso');
1642
-        EE_Registry::$i18n_js_strings['Fri'] = __('Fri', 'event_espresso');
1643
-        EE_Registry::$i18n_js_strings['Sat'] = __('Sat', 'event_espresso');
1644
-        //setting on espresso_core instead of ee_admin_js because espresso_core is enqueued by the maintenance
1645
-        //admin page when in maintenance mode and ee_admin_js is not loaded then.  This works everywhere else because
1646
-        //espresso_core is listed as a dependency of ee_admin_js.
1647
-        wp_localize_script('espresso_core', 'eei18n', EE_Registry::$i18n_js_strings);
1648
-    }
1649
-
1650
-
1651
-
1652
-    /**
1653
-     *        load enhanced xdebug styles for ppl with failing eyesight
1654
-     *
1655
-     * @access        public
1656
-     * @return        void
1657
-     */
1658
-    public function add_xdebug_style()
1659
-    {
1660
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1661
-    }
1662
-
1663
-
1664
-    /************************/
1665
-    /** LIST TABLE METHODS **/
1666
-    /************************/
1667
-    /**
1668
-     * this sets up the list table if the current view requires it.
1669
-     *
1670
-     * @access protected
1671
-     * @return void
1672
-     */
1673
-    protected function _set_list_table()
1674
-    {
1675
-        //first is this a list_table view?
1676
-        if ( ! isset($this->_route_config['list_table'])) {
1677
-            return;
1678
-        } //not a list_table view so get out.
1679
-        //list table functions are per view specific (because some admin pages might have more than one listtable!)
1680
-        if (call_user_func(array($this, '_set_list_table_views_' . $this->_req_action)) === false) {
1681
-            //user error msg
1682
-            $error_msg = __('An error occurred. The requested list table views could not be found.', 'event_espresso');
1683
-            //developer error msg
1684
-            $error_msg .= '||' . sprintf(__('List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.', 'event_espresso'),
1685
-                            $this->_req_action, '_set_list_table_views_' . $this->_req_action);
1686
-            throw new EE_Error($error_msg);
1687
-        }
1688
-        //let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
1689
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action, $this->_views);
1690
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
1691
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
1692
-        $this->_set_list_table_view();
1693
-        $this->_set_list_table_object();
1694
-    }
1695
-
1696
-
1697
-
1698
-    /**
1699
-     *        set current view for List Table
1700
-     *
1701
-     * @access public
1702
-     * @return array
1703
-     */
1704
-    protected function _set_list_table_view()
1705
-    {
1706
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1707
-        // looking at active items or dumpster diving ?
1708
-        if ( ! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
1709
-            $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
1710
-        } else {
1711
-            $this->_view = sanitize_key($this->_req_data['status']);
1712
-        }
1713
-    }
1714
-
1715
-
1716
-
1717
-    /**
1718
-     * _set_list_table_object
1719
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
1720
-     *
1721
-     * @throws \EE_Error
1722
-     */
1723
-    protected function _set_list_table_object()
1724
-    {
1725
-        if (isset($this->_route_config['list_table'])) {
1726
-            if ( ! class_exists($this->_route_config['list_table'])) {
1727
-                throw new EE_Error(
1728
-                        sprintf(
1729
-                                __(
1730
-                                        'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
1731
-                                        'event_espresso'
1732
-                                ),
1733
-                                $this->_route_config['list_table'],
1734
-                                get_class($this)
1735
-                        )
1736
-                );
1737
-            }
1738
-            $list_table = $this->_route_config['list_table'];
1739
-            $this->_list_table_object = new $list_table($this);
1740
-        }
1741
-    }
1742
-
1743
-
1744
-
1745
-    /**
1746
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
1747
-     *
1748
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
1749
-     *                                                    urls.  The array should be indexed by the view it is being
1750
-     *                                                    added to.
1751
-     * @return array
1752
-     */
1753
-    public function get_list_table_view_RLs($extra_query_args = array())
1754
-    {
1755
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1756
-        if (empty($this->_views)) {
1757
-            $this->_views = array();
1758
-        }
1759
-        // cycle thru views
1760
-        foreach ($this->_views as $key => $view) {
1761
-            $query_args = array();
1762
-            // check for current view
1763
-            $this->_views[$key]['class'] = $this->_view == $view['slug'] ? 'current' : '';
1764
-            $query_args['action'] = $this->_req_action;
1765
-            $query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
1766
-            $query_args['status'] = $view['slug'];
1767
-            //merge any other arguments sent in.
1768
-            if (isset($extra_query_args[$view['slug']])) {
1769
-                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
1770
-            }
1771
-            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1772
-        }
1773
-        return $this->_views;
1774
-    }
1775
-
1776
-
1777
-
1778
-    /**
1779
-     * _entries_per_page_dropdown
1780
-     * generates a drop down box for selecting the number of visiable rows in an admin page list table
1781
-     *
1782
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how WP does it.
1783
-     * @access protected
1784
-     * @param int $max_entries total number of rows in the table
1785
-     * @return string
1786
-     */
1787
-    protected function _entries_per_page_dropdown($max_entries = false)
1788
-    {
1789
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1790
-        $values = array(10, 25, 50, 100);
1791
-        $per_page = ( ! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
1792
-        if ($max_entries) {
1793
-            $values[] = $max_entries;
1794
-            sort($values);
1795
-        }
1796
-        $entries_per_page_dropdown = '
143
+	// yes / no array for admin form fields
144
+	protected $_yes_no_values = array();
145
+
146
+	//some default things shared by all child classes
147
+	protected $_default_espresso_metaboxes;
148
+
149
+	/**
150
+	 *    EE_Registry Object
151
+	 *
152
+	 * @var    EE_Registry
153
+	 * @access    protected
154
+	 */
155
+	protected $EE = null;
156
+
157
+
158
+
159
+	/**
160
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
161
+	 *
162
+	 * @var boolean
163
+	 */
164
+	protected $_is_caf = false;
165
+
166
+
167
+
168
+	/**
169
+	 * @Constructor
170
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
171
+	 * @access public
172
+	 */
173
+	public function __construct($routing = true)
174
+	{
175
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
176
+			$this->_is_caf = true;
177
+		}
178
+		$this->_yes_no_values = array(
179
+				array('id' => true, 'text' => __('Yes', 'event_espresso')),
180
+				array('id' => false, 'text' => __('No', 'event_espresso')),
181
+		);
182
+		//set the _req_data property.
183
+		$this->_req_data = array_merge($_GET, $_POST);
184
+		//routing enabled?
185
+		$this->_routing = $routing;
186
+		//set initial page props (child method)
187
+		$this->_init_page_props();
188
+		//set global defaults
189
+		$this->_set_defaults();
190
+		//set early because incoming requests could be ajax related and we need to register those hooks.
191
+		$this->_global_ajax_hooks();
192
+		$this->_ajax_hooks();
193
+		//other_page_hooks have to be early too.
194
+		$this->_do_other_page_hooks();
195
+		//This just allows us to have extending clases do something specific before the parent constructor runs _page_setup.
196
+		if (method_exists($this, '_before_page_setup')) {
197
+			$this->_before_page_setup();
198
+		}
199
+		//set up page dependencies
200
+		$this->_page_setup();
201
+	}
202
+
203
+
204
+
205
+	/**
206
+	 * _init_page_props
207
+	 * Child classes use to set at least the following properties:
208
+	 * $page_slug.
209
+	 * $page_label.
210
+	 *
211
+	 * @abstract
212
+	 * @access protected
213
+	 * @return void
214
+	 */
215
+	abstract protected function _init_page_props();
216
+
217
+
218
+
219
+	/**
220
+	 * _ajax_hooks
221
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
222
+	 * Note: within the ajax callback methods.
223
+	 *
224
+	 * @abstract
225
+	 * @access protected
226
+	 * @return void
227
+	 */
228
+	abstract protected function _ajax_hooks();
229
+
230
+
231
+
232
+	/**
233
+	 * _define_page_props
234
+	 * child classes define page properties in here.  Must include at least:
235
+	 * $_admin_base_url = base_url for all admin pages
236
+	 * $_admin_page_title = default admin_page_title for admin pages
237
+	 * $_labels = array of default labels for various automatically generated elements:
238
+	 *    array(
239
+	 *        'buttons' => array(
240
+	 *            'add' => __('label for add new button'),
241
+	 *            'edit' => __('label for edit button'),
242
+	 *            'delete' => __('label for delete button')
243
+	 *            )
244
+	 *        )
245
+	 *
246
+	 * @abstract
247
+	 * @access protected
248
+	 * @return void
249
+	 */
250
+	abstract protected function _define_page_props();
251
+
252
+
253
+
254
+	/**
255
+	 * _set_page_routes
256
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also have a 'default'
257
+	 * route. Here's the format
258
+	 * $this->_page_routes = array(
259
+	 *        'default' => array(
260
+	 *            'func' => '_default_method_handling_route',
261
+	 *            'args' => array('array','of','args'),
262
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e. ajax request, backend processing)
263
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a headers route after.  The string you enter here should match the defined route reference for a headers sent route.
264
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access this route.
265
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability checks).
266
+	 *        ),
267
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a handling method.
268
+	 *        )
269
+	 * )
270
+	 *
271
+	 * @abstract
272
+	 * @access protected
273
+	 * @return void
274
+	 */
275
+	abstract protected function _set_page_routes();
276
+
277
+
278
+
279
+	/**
280
+	 * _set_page_config
281
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the array corresponds to the page_route for the loaded page.
282
+	 * Format:
283
+	 * $this->_page_config = array(
284
+	 *        'default' => array(
285
+	 *            'labels' => array(
286
+	 *                'buttons' => array(
287
+	 *                    'add' => __('label for adding item'),
288
+	 *                    'edit' => __('label for editing item'),
289
+	 *                    'delete' => __('label for deleting item')
290
+	 *                ),
291
+	 *                'publishbox' => __('Localized Title for Publish metabox', 'event_espresso')
292
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the page. If this isn't present then the defaults will be used as set for the $this->_labels in _define_page_props() method
293
+	 *            'nav' => array(
294
+	 *                'label' => __('Label for Tab', 'event_espresso').
295
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
296
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
297
+	 *                'order' => 10, //required to indicate tab position.
298
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is displayed then add this parameter.
299
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
300
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load metaboxes set for eventespresso admin pages.
301
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added later.  We just use
302
+	 *            this flag to make sure the necessary js gets enqueued on page load.
303
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
304
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The array indicates the max number of columns (4) and the default number of columns on page load (2).  There is an option
305
+	 *            in the "screen_options" dropdown that is setup so users can pick what columns they want to display.
306
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
307
+	 *                'tab_id' => array(
308
+	 *                    'title' => 'tab_title',
309
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting help tab content.  The fallback if it isn't present is to try a the callback.  Filename should match a file in the admin
310
+	 *                    folder's "help_tabs" dir (ie.. events/help_tabs/name_of_file_containing_content.help_tab.php)
311
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will attempt to use the callback which should match the name of a method in the class
312
+	 *                    ),
313
+	 *                'tab2_id' => array(
314
+	 *                    'title' => 'tab2 title',
315
+	 *                    'filename' => 'file_name_2'
316
+	 *                    'callback' => 'callback_method_for_content',
317
+	 *                 ),
318
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the help tab area on an admin page. @link http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
319
+	 *            'help_tour' => array(
320
+	 *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located in a folder for this admin page named "help_tours", a file name matching the key given here
321
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
322
+	 *            ),
323
+	 *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is true if it isn't present).  To remove the requirement for a nonce check when this route is visited just set
324
+	 *            'require_nonce' to FALSE
325
+	 *            )
326
+	 * )
327
+	 *
328
+	 * @abstract
329
+	 * @access protected
330
+	 * @return void
331
+	 */
332
+	abstract protected function _set_page_config();
333
+
334
+
335
+
336
+
337
+
338
+	/** end sample help_tour methods **/
339
+	/**
340
+	 * _add_screen_options
341
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
342
+	 * Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options to a particular view.
343
+	 *
344
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
345
+	 *         see also WP_Screen object documents...
346
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
347
+	 * @abstract
348
+	 * @access protected
349
+	 * @return void
350
+	 */
351
+	abstract protected function _add_screen_options();
352
+
353
+
354
+
355
+	/**
356
+	 * _add_feature_pointers
357
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
358
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a particular view.
359
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
360
+	 * See: WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
361
+	 *
362
+	 * @link   http://eamann.com/tech/wordpress-portland/
363
+	 * @abstract
364
+	 * @access protected
365
+	 * @return void
366
+	 */
367
+	abstract protected function _add_feature_pointers();
368
+
369
+
370
+
371
+	/**
372
+	 * load_scripts_styles
373
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific scripts/styles
374
+	 * per view by putting them in a dynamic function in this format (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
375
+	 *
376
+	 * @abstract
377
+	 * @access public
378
+	 * @return void
379
+	 */
380
+	abstract public function load_scripts_styles();
381
+
382
+
383
+
384
+	/**
385
+	 * admin_init
386
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to all pages/views loaded by child class.
387
+	 *
388
+	 * @abstract
389
+	 * @access public
390
+	 * @return void
391
+	 */
392
+	abstract public function admin_init();
393
+
394
+
395
+
396
+	/**
397
+	 * admin_notices
398
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to all pages/views loaded by child class.
399
+	 *
400
+	 * @abstract
401
+	 * @access public
402
+	 * @return void
403
+	 */
404
+	abstract public function admin_notices();
405
+
406
+
407
+
408
+	/**
409
+	 * admin_footer_scripts
410
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply to all pages/views loaded by child class.
411
+	 *
412
+	 * @access public
413
+	 * @return void
414
+	 */
415
+	abstract public function admin_footer_scripts();
416
+
417
+
418
+
419
+	/**
420
+	 * admin_footer
421
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will apply to all pages/views loaded by child class.
422
+	 *
423
+	 * @access  public
424
+	 * @return void
425
+	 */
426
+	public function admin_footer()
427
+	{
428
+	}
429
+
430
+
431
+
432
+	/**
433
+	 * _global_ajax_hooks
434
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
435
+	 * Note: within the ajax callback methods.
436
+	 *
437
+	 * @abstract
438
+	 * @access protected
439
+	 * @return void
440
+	 */
441
+	protected function _global_ajax_hooks()
442
+	{
443
+		//for lazy loading of metabox content
444
+		add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
445
+	}
446
+
447
+
448
+
449
+	public function ajax_metabox_content()
450
+	{
451
+		$contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
452
+		$url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
453
+		self::cached_rss_display($contentid, $url);
454
+		wp_die();
455
+	}
456
+
457
+
458
+
459
+	/**
460
+	 * _page_setup
461
+	 * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested doesn't match the object.
462
+	 *
463
+	 * @final
464
+	 * @access protected
465
+	 * @return void
466
+	 */
467
+	final protected function _page_setup()
468
+	{
469
+		//requires?
470
+		//admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
471
+		add_action('admin_init', array($this, 'admin_init_global'), 5);
472
+		//next verify if we need to load anything...
473
+		$this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
474
+		$this->page_folder = strtolower(str_replace('_Admin_Page', '', str_replace('Extend_', '', get_class($this))));
475
+		global $ee_menu_slugs;
476
+		$ee_menu_slugs = (array)$ee_menu_slugs;
477
+		if (( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page])) && ! defined('DOING_AJAX')) {
478
+			return false;
479
+		}
480
+		// becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
481
+		if (isset($this->_req_data['action2']) && $this->_req_data['action'] == -1) {
482
+			$this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] != -1 ? $this->_req_data['action2'] : $this->_req_data['action'];
483
+		}
484
+		// then set blank or -1 action values to 'default'
485
+		$this->_req_action = isset($this->_req_data['action']) && ! empty($this->_req_data['action']) && $this->_req_data['action'] != -1 ? sanitize_key($this->_req_data['action']) : 'default';
486
+		//if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.  This covers cases where we're coming in from a list table that isn't on the default route.
487
+		$this->_req_action = $this->_req_action == 'default' && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
488
+		//however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
489
+		$this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
490
+		$this->_current_view = $this->_req_action;
491
+		$this->_req_nonce = $this->_req_action . '_nonce';
492
+		$this->_define_page_props();
493
+		$this->_current_page_view_url = add_query_arg(array('page' => $this->_current_page, 'action' => $this->_current_view), $this->_admin_base_url);
494
+		//default things
495
+		$this->_default_espresso_metaboxes = array('_espresso_news_post_box', '_espresso_links_post_box', '_espresso_ratings_request', '_espresso_sponsors_post_box');
496
+		//set page configs
497
+		$this->_set_page_routes();
498
+		$this->_set_page_config();
499
+		//let's include any referrer data in our default_query_args for this route for "stickiness".
500
+		if (isset($this->_req_data['wp_referer'])) {
501
+			$this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
502
+		}
503
+		//for caffeinated and other extended functionality.  If there is a _extend_page_config method then let's run that to modify the all the various page configuration arrays
504
+		if (method_exists($this, '_extend_page_config')) {
505
+			$this->_extend_page_config();
506
+		}
507
+		//for CPT and other extended functionality. If there is an _extend_page_config_for_cpt then let's run that to modify all the various page configuration arrays.
508
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
509
+			$this->_extend_page_config_for_cpt();
510
+		}
511
+		//filter routes and page_config so addons can add their stuff. Filtering done per class
512
+		$this->_page_routes = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_routes', $this->_page_routes, $this);
513
+		$this->_page_config = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_config', $this->_page_config, $this);
514
+		//if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
515
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
516
+			add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view), 10, 2);
517
+		}
518
+		//next route only if routing enabled
519
+		if ($this->_routing && ! defined('DOING_AJAX')) {
520
+			$this->_verify_routes();
521
+			//next let's just check user_access and kill if no access
522
+			$this->check_user_access();
523
+			if ($this->_is_UI_request) {
524
+				//admin_init stuff - global, all views for this page class, specific view
525
+				add_action('admin_init', array($this, 'admin_init'), 10);
526
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
527
+					add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
528
+				}
529
+			} else {
530
+				//hijack regular WP loading and route admin request immediately
531
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
532
+				$this->route_admin_request();
533
+			}
534
+		}
535
+	}
536
+
537
+
538
+
539
+	/**
540
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
541
+	 *
542
+	 * @access private
543
+	 * @return void
544
+	 */
545
+	private function _do_other_page_hooks()
546
+	{
547
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
548
+		foreach ($registered_pages as $page) {
549
+			//now let's setup the file name and class that should be present
550
+			$classname = str_replace('.class.php', '', $page);
551
+			//autoloaders should take care of loading file
552
+			if ( ! class_exists($classname)) {
553
+				$error_msg[] = sprintf(__('Something went wrong with loading the %s admin hooks page.', 'event_espresso'), $page);
554
+				$error_msg[] = $error_msg[0]
555
+							   . "\r\n"
556
+							   . sprintf(__('There is no class in place for the %s admin hooks page.%sMake sure you have <strong>%s</strong> defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
557
+								'event_espresso'), $page, '<br />', $classname);
558
+				throw new EE_Error(implode('||', $error_msg));
559
+			}
560
+			$a = new ReflectionClass($classname);
561
+			//notice we are passing the instance of this class to the hook object.
562
+			$hookobj[] = $a->newInstance($this);
563
+		}
564
+	}
565
+
566
+
567
+
568
+	public function load_page_dependencies()
569
+	{
570
+		try {
571
+			$this->_load_page_dependencies();
572
+		} catch (EE_Error $e) {
573
+			$e->get_error();
574
+		}
575
+	}
576
+
577
+
578
+
579
+	/**
580
+	 * load_page_dependencies
581
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
582
+	 *
583
+	 * @access public
584
+	 * @return void
585
+	 */
586
+	protected function _load_page_dependencies()
587
+	{
588
+		//let's set the current_screen and screen options to override what WP set
589
+		$this->_current_screen = get_current_screen();
590
+		//load admin_notices - global, page class, and view specific
591
+		add_action('admin_notices', array($this, 'admin_notices_global'), 5);
592
+		add_action('admin_notices', array($this, 'admin_notices'), 10);
593
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
594
+			add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
595
+		}
596
+		//load network admin_notices - global, page class, and view specific
597
+		add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
598
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
599
+			add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
600
+		}
601
+		//this will save any per_page screen options if they are present
602
+		$this->_set_per_page_screen_options();
603
+		//setup list table properties
604
+		$this->_set_list_table();
605
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.  However in some cases the metaboxes will need to be added within a route handling callback.
606
+		$this->_add_registered_meta_boxes();
607
+		$this->_add_screen_columns();
608
+		//add screen options - global, page child class, and view specific
609
+		$this->_add_global_screen_options();
610
+		$this->_add_screen_options();
611
+		if (method_exists($this, '_add_screen_options_' . $this->_current_view)) {
612
+			call_user_func(array($this, '_add_screen_options_' . $this->_current_view));
613
+		}
614
+		//add help tab(s) and tours- set via page_config and qtips.
615
+		$this->_add_help_tour();
616
+		$this->_add_help_tabs();
617
+		$this->_add_qtips();
618
+		//add feature_pointers - global, page child class, and view specific
619
+		$this->_add_feature_pointers();
620
+		$this->_add_global_feature_pointers();
621
+		if (method_exists($this, '_add_feature_pointer_' . $this->_current_view)) {
622
+			call_user_func(array($this, '_add_feature_pointer_' . $this->_current_view));
623
+		}
624
+		//enqueue scripts/styles - global, page class, and view specific
625
+		add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
626
+		add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
627
+		if (method_exists($this, 'load_scripts_styles_' . $this->_current_view)) {
628
+			add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles_' . $this->_current_view), 15);
629
+		}
630
+		add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
631
+		//admin_print_footer_scripts - global, page child class, and view specific.  NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.  In most cases that's doing_it_wrong().  But adding hidden container elements etc. is a good use case. Notice the late priority we're giving these
632
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
633
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
634
+		if (method_exists($this, 'admin_footer_scripts_' . $this->_current_view)) {
635
+			add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_' . $this->_current_view), 101);
636
+		}
637
+		//admin footer scripts
638
+		add_action('admin_footer', array($this, 'admin_footer_global'), 99);
639
+		add_action('admin_footer', array($this, 'admin_footer'), 100);
640
+		if (method_exists($this, 'admin_footer_' . $this->_current_view)) {
641
+			add_action('admin_footer', array($this, 'admin_footer_' . $this->_current_view), 101);
642
+		}
643
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
644
+		//targeted hook
645
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load__' . $this->page_slug . '__' . $this->_req_action);
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * _set_defaults
652
+	 * This sets some global defaults for class properties.
653
+	 */
654
+	private function _set_defaults()
655
+	{
656
+		$this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = $this->_event = $this->_template_path = $this->_column_template_path = null;
657
+		$this->_nav_tabs = $this_views = $this->_page_routes = $this->_page_config = $this->_default_route_query_args = array();
658
+		$this->default_nav_tab_name = 'overview';
659
+		//init template args
660
+		$this->_template_args = array(
661
+				'admin_page_header'  => '',
662
+				'admin_page_content' => '',
663
+				'post_body_content'  => '',
664
+				'before_list_table'  => '',
665
+				'after_list_table'   => '',
666
+		);
667
+	}
668
+
669
+
670
+
671
+	/**
672
+	 * route_admin_request
673
+	 *
674
+	 * @see    _route_admin_request()
675
+	 * @access public
676
+	 * @return void|exception error
677
+	 */
678
+	public function route_admin_request()
679
+	{
680
+		try {
681
+			$this->_route_admin_request();
682
+		} catch (EE_Error $e) {
683
+			$e->get_error();
684
+		}
685
+	}
686
+
687
+
688
+
689
+	public function set_wp_page_slug($wp_page_slug)
690
+	{
691
+		$this->_wp_page_slug = $wp_page_slug;
692
+		//if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
693
+		if (is_network_admin()) {
694
+			$this->_wp_page_slug .= '-network';
695
+		}
696
+	}
697
+
698
+
699
+
700
+	/**
701
+	 * _verify_routes
702
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so we know if we need to drop out.
703
+	 *
704
+	 * @access protected
705
+	 * @return void
706
+	 */
707
+	protected function _verify_routes()
708
+	{
709
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
710
+		if ( ! $this->_current_page && ! defined('DOING_AJAX')) {
711
+			return false;
712
+		}
713
+		$this->_route = false;
714
+		$func = false;
715
+		$args = array();
716
+		// check that the page_routes array is not empty
717
+		if (empty($this->_page_routes)) {
718
+			// user error msg
719
+			$error_msg = sprintf(__('No page routes have been set for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
720
+			// developer error msg
721
+			$error_msg .= '||' . $error_msg . __(' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.', 'event_espresso');
722
+			throw new EE_Error($error_msg);
723
+		}
724
+		// and that the requested page route exists
725
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
726
+			$this->_route = $this->_page_routes[$this->_req_action];
727
+			$this->_route_config = isset($this->_page_config[$this->_req_action]) ? $this->_page_config[$this->_req_action] : array();
728
+		} else {
729
+			// user error msg
730
+			$error_msg = sprintf(__('The requested page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
731
+			// developer error msg
732
+			$error_msg .= '||' . $error_msg . sprintf(__(' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.', 'event_espresso'), $this->_req_action);
733
+			throw new EE_Error($error_msg);
734
+		}
735
+		// and that a default route exists
736
+		if ( ! array_key_exists('default', $this->_page_routes)) {
737
+			// user error msg
738
+			$error_msg = sprintf(__('A default page route has not been set for the % admin page.', 'event_espresso'), $this->_admin_page_title);
739
+			// developer error msg
740
+			$error_msg .= '||' . $error_msg . __(' Create a key in the "_page_routes" array named "default" and set its value to your default page method.', 'event_espresso');
741
+			throw new EE_Error($error_msg);
742
+		}
743
+		//first lets' catch if the UI request has EVER been set.
744
+		if ($this->_is_UI_request === null) {
745
+			//lets set if this is a UI request or not.
746
+			$this->_is_UI_request = ( ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true) ? true : false;
747
+			//wait a minute... we might have a noheader in the route array
748
+			$this->_is_UI_request = is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader'] ? false : $this->_is_UI_request;
749
+		}
750
+		$this->_set_current_labels();
751
+	}
752
+
753
+
754
+
755
+	/**
756
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
757
+	 *
758
+	 * @param  string $route the route name we're verifying
759
+	 * @return mixed  (bool|Exception)      we'll throw an exception if this isn't a valid route.
760
+	 */
761
+	protected function _verify_route($route)
762
+	{
763
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
764
+			return true;
765
+		} else {
766
+			// user error msg
767
+			$error_msg = sprintf(__('The given page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
768
+			// developer error msg
769
+			$error_msg .= '||' . $error_msg . sprintf(__(' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property', 'event_espresso'), $route);
770
+			throw new EE_Error($error_msg);
771
+		}
772
+	}
773
+
774
+
775
+
776
+	/**
777
+	 * perform nonce verification
778
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces using this method (and save retyping!)
779
+	 *
780
+	 * @param  string $nonce     The nonce sent
781
+	 * @param  string $nonce_ref The nonce reference string (name0)
782
+	 * @return mixed (bool|die)
783
+	 */
784
+	protected function _verify_nonce($nonce, $nonce_ref)
785
+	{
786
+		// verify nonce against expected value
787
+		if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
788
+			// these are not the droids you are looking for !!!
789
+			$msg = sprintf(__('%sNonce Fail.%s', 'event_espresso'), '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">', '</a>');
790
+			if (WP_DEBUG) {
791
+				$msg .= "\n  " . sprintf(__('In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!', 'event_espresso'), __CLASS__);
792
+			}
793
+			if ( ! defined('DOING_AJAX')) {
794
+				wp_die($msg);
795
+			} else {
796
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
797
+				$this->_return_json();
798
+			}
799
+		}
800
+	}
801
+
802
+
803
+
804
+	/**
805
+	 * _route_admin_request()
806
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
807
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
808
+	 * in the page routes and then will try to load the corresponding method.
809
+	 *
810
+	 * @access protected
811
+	 * @return void
812
+	 * @throws \EE_Error
813
+	 */
814
+	protected function _route_admin_request()
815
+	{
816
+		if ( ! $this->_is_UI_request) {
817
+			$this->_verify_routes();
818
+		}
819
+		$nonce_check = isset($this->_route_config['require_nonce'])
820
+			? $this->_route_config['require_nonce']
821
+			: true;
822
+		if ($this->_req_action !== 'default' && $nonce_check) {
823
+			// set nonce from post data
824
+			$nonce = isset($this->_req_data[$this->_req_nonce])
825
+				? sanitize_text_field($this->_req_data[$this->_req_nonce])
826
+				: '';
827
+			$this->_verify_nonce($nonce, $this->_req_nonce);
828
+		}
829
+		//set the nav_tabs array but ONLY if this is  UI_request
830
+		if ($this->_is_UI_request) {
831
+			$this->_set_nav_tabs();
832
+		}
833
+		// grab callback function
834
+		$func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
835
+		// check if callback has args
836
+		$args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
837
+		$error_msg = '';
838
+		// action right before calling route
839
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
840
+		if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
841
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
842
+		}
843
+		// right before calling the route, let's remove _wp_http_referer from the
844
+		// $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
845
+		$_SERVER['REQUEST_URI'] = remove_query_arg('_wp_http_referer', wp_unslash($_SERVER['REQUEST_URI']));
846
+		if ( ! empty($func)) {
847
+			if (is_array($func)) {
848
+				list($class, $method) = $func;
849
+			} else if (strpos($func, '::') !== false) {
850
+				list($class, $method) = explode('::', $func);
851
+			} else {
852
+				$class = $this;
853
+				$method = $func;
854
+			}
855
+			if ( ! (is_object($class) && $class === $this)) {
856
+				// send along this admin page object for access by addons.
857
+				$args['admin_page_object'] = $this;
858
+			}
859
+
860
+			if (
861
+				//is it a method on a class that doesn't work?
862
+				(
863
+					(
864
+						method_exists($class, $method)
865
+						&& call_user_func_array(array($class, $method), $args) === false
866
+					)
867
+					&& (
868
+						//is it a standalone function that doesn't work?
869
+						function_exists($method)
870
+						&& call_user_func_array($func, array_merge(array('admin_page_object' => $this), $args)) === false
871
+					)
872
+				)
873
+				|| (
874
+					//is it neither a class method NOR a standalone function?
875
+					! method_exists($class, $method)
876
+					&& ! function_exists($method)
877
+				)
878
+			) {
879
+				// user error msg
880
+				$error_msg = __('An error occurred. The  requested page route could not be found.', 'event_espresso');
881
+				// developer error msg
882
+				$error_msg .= '||';
883
+				$error_msg .= sprintf(
884
+					__(
885
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
886
+						'event_espresso'
887
+					),
888
+					$method
889
+				);
890
+			}
891
+			if ( ! empty($error_msg)) {
892
+				throw new EE_Error($error_msg);
893
+			}
894
+		}
895
+		//if we've routed and this route has a no headers route AND a sent_headers_route, then we need to reset the routing properties to the new route.
896
+		//now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
897
+		if ($this->_is_UI_request === false
898
+			&& is_array($this->_route)
899
+			&& ! empty($this->_route['headers_sent_route'])
900
+		) {
901
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
902
+		}
903
+	}
904
+
905
+
906
+
907
+	/**
908
+	 * This method just allows the resetting of page properties in the case where a no headers
909
+	 * route redirects to a headers route in its route config.
910
+	 *
911
+	 * @since   4.3.0
912
+	 * @param  string $new_route New (non header) route to redirect to.
913
+	 * @return   void
914
+	 */
915
+	protected function _reset_routing_properties($new_route)
916
+	{
917
+		$this->_is_UI_request = true;
918
+		//now we set the current route to whatever the headers_sent_route is set at
919
+		$this->_req_data['action'] = $new_route;
920
+		//rerun page setup
921
+		$this->_page_setup();
922
+	}
923
+
924
+
925
+
926
+	/**
927
+	 * _add_query_arg
928
+	 * adds nonce to array of arguments then calls WP add_query_arg function
929
+	 *(internally just uses EEH_URL's function with the same name)
930
+	 *
931
+	 * @access public
932
+	 * @param array  $args
933
+	 * @param string $url
934
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the generated
935
+	 *                                        url in an associative array indexed by the key 'wp_referer';
936
+	 *                                        Example usage:
937
+	 *                                        If the current page is:
938
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
939
+	 *                                        &action=default&event_id=20&month_range=March%202015
940
+	 *                                        &_wpnonce=5467821
941
+	 *                                        and you call:
942
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
943
+	 *                                        array(
944
+	 *                                        'action' => 'resend_something',
945
+	 *                                        'page=>espresso_registrations'
946
+	 *                                        ),
947
+	 *                                        $some_url,
948
+	 *                                        true
949
+	 *                                        );
950
+	 *                                        It will produce a url in this structure:
951
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
952
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
953
+	 *                                        month_range]=March%202015
954
+	 * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
955
+	 * @return string
956
+	 */
957
+	public static function add_query_args_and_nonce($args = array(), $url = false, $sticky = false, $exclude_nonce = false)
958
+	{
959
+		//if there is a _wp_http_referer include the values from the request but only if sticky = true
960
+		if ($sticky) {
961
+			$request = $_REQUEST;
962
+			unset($request['_wp_http_referer']);
963
+			unset($request['wp_referer']);
964
+			foreach ($request as $key => $value) {
965
+				//do not add nonces
966
+				if (strpos($key, 'nonce') !== false) {
967
+					continue;
968
+				}
969
+				$args['wp_referer[' . $key . ']'] = $value;
970
+			}
971
+		}
972
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
973
+	}
974
+
975
+
976
+
977
+	/**
978
+	 * This returns a generated link that will load the related help tab.
979
+	 *
980
+	 * @param  string $help_tab_id the id for the connected help tab
981
+	 * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
982
+	 * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
983
+	 * @uses EEH_Template::get_help_tab_link()
984
+	 * @return string              generated link
985
+	 */
986
+	protected function _get_help_tab_link($help_tab_id, $icon_style = false, $help_text = false)
987
+	{
988
+		return EEH_Template::get_help_tab_link($help_tab_id, $this->page_slug, $this->_req_action, $icon_style, $help_text);
989
+	}
990
+
991
+
992
+
993
+	/**
994
+	 * _add_help_tabs
995
+	 * Note child classes define their help tabs within the page_config array.
996
+	 *
997
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
998
+	 * @access protected
999
+	 * @return void
1000
+	 */
1001
+	protected function _add_help_tabs()
1002
+	{
1003
+		$tour_buttons = '';
1004
+		if (isset($this->_page_config[$this->_req_action])) {
1005
+			$config = $this->_page_config[$this->_req_action];
1006
+			//is there a help tour for the current route?  if there is let's setup the tour buttons
1007
+			if (isset($this->_help_tour[$this->_req_action])) {
1008
+				$tb = array();
1009
+				$tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1010
+				foreach ($this->_help_tour['tours'] as $tour) {
1011
+					//if this is the end tour then we don't need to setup a button
1012
+					if ($tour instanceof EE_Help_Tour_final_stop) {
1013
+						continue;
1014
+					}
1015
+					$tb[] = '<button id="trigger-tour-' . $tour->get_slug() . '" class="button-primary trigger-ee-help-tour">' . $tour->get_label() . '</button>';
1016
+				}
1017
+				$tour_buttons .= implode('<br />', $tb);
1018
+				$tour_buttons .= '</div></div>';
1019
+			}
1020
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1021
+			if (is_array($config) && isset($config['help_sidebar'])) {
1022
+				//check that the callback given is valid
1023
+				if ( ! method_exists($this, $config['help_sidebar'])) {
1024
+					throw new EE_Error(sprintf(__('The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1025
+							'event_espresso'), $config['help_sidebar'], get_class($this)));
1026
+				}
1027
+				$content = apply_filters('FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar', call_user_func(array($this, $config['help_sidebar'])));
1028
+				$content .= $tour_buttons; //add help tour buttons.
1029
+				//do we have any help tours setup?  Cause if we do we want to add the buttons
1030
+				$this->_current_screen->set_help_sidebar($content);
1031
+			}
1032
+			//if we DON'T have config help sidebar and there ARE toure buttons then we'll just add the tour buttons to the sidebar.
1033
+			if ( ! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1034
+				$this->_current_screen->set_help_sidebar($tour_buttons);
1035
+			}
1036
+			//handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1037
+			if ( ! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1038
+				$_ht['id'] = $this->page_slug;
1039
+				$_ht['title'] = __('Help Tours', 'event_espresso');
1040
+				$_ht['content'] = '<p>' . __('The buttons to the right allow you to start/restart any help tours available for this page', 'event_espresso') . '</p>';
1041
+				$this->_current_screen->add_help_tab($_ht);
1042
+			}/**/
1043
+			if ( ! isset($config['help_tabs'])) {
1044
+				return;
1045
+			} //no help tabs for this route
1046
+			foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1047
+				//we're here so there ARE help tabs!
1048
+				//make sure we've got what we need
1049
+				if ( ! isset($cfg['title'])) {
1050
+					throw new EE_Error(__('The _page_config array is not set up properly for help tabs.  It is missing a title', 'event_espresso'));
1051
+				}
1052
+				if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1053
+					throw new EE_Error(__('The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1054
+							'event_espresso'));
1055
+				}
1056
+				//first priority goes to content.
1057
+				if ( ! empty($cfg['content'])) {
1058
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1059
+					//second priority goes to filename
1060
+				} else if ( ! empty($cfg['filename'])) {
1061
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1062
+					//it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1063
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tabs/' . $cfg['filename'] . '.help_tab.php' : $file_path;
1064
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1065
+					if ( ! is_readable($file_path) && ! isset($cfg['callback'])) {
1066
+						EE_Error::add_error(sprintf(__('The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1067
+								'event_espresso'), $tab_id, key($config), $file_path), __FILE__, __FUNCTION__, __LINE__);
1068
+						return;
1069
+					}
1070
+					$template_args['admin_page_obj'] = $this;
1071
+					$content = EEH_Template::display_template($file_path, $template_args, true);
1072
+				} else {
1073
+					$content = '';
1074
+				}
1075
+				//check if callback is valid
1076
+				if (empty($content) && ( ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback']))) {
1077
+					EE_Error::add_error(sprintf(__('The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1078
+							'event_espresso'), $cfg['title']), __FILE__, __FUNCTION__, __LINE__);
1079
+					return;
1080
+				}
1081
+				//setup config array for help tab method
1082
+				$id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1083
+				$_ht = array(
1084
+						'id'       => $id,
1085
+						'title'    => $cfg['title'],
1086
+						'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1087
+						'content'  => $content,
1088
+				);
1089
+				$this->_current_screen->add_help_tab($_ht);
1090
+			}
1091
+		}
1092
+	}
1093
+
1094
+
1095
+
1096
+	/**
1097
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is an array with properties for setting up usage of the joyride plugin
1098
+	 *
1099
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1100
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the _set_page_config() comments
1101
+	 * @access protected
1102
+	 * @return void
1103
+	 */
1104
+	protected function _add_help_tour()
1105
+	{
1106
+		$tours = array();
1107
+		$this->_help_tour = array();
1108
+		//exit early if help tours are turned off globally
1109
+		if ( ! EE_Registry::instance()->CFG->admin->help_tour_activation || (defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)) {
1110
+			return;
1111
+		}
1112
+		//loop through _page_config to find any help_tour defined
1113
+		foreach ($this->_page_config as $route => $config) {
1114
+			//we're only going to set things up for this route
1115
+			if ($route !== $this->_req_action) {
1116
+				continue;
1117
+			}
1118
+			if (isset($config['help_tour'])) {
1119
+				foreach ($config['help_tour'] as $tour) {
1120
+					$file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1121
+					//let's see if we can get that file... if not its possible this is a decaf route not set in caffienated so lets try and get the caffeinated equivalent
1122
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tours/' . $tour . '.class.php' : $file_path;
1123
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1124
+					if ( ! is_readable($file_path)) {
1125
+						EE_Error::add_error(sprintf(__('The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling', 'event_espresso'),
1126
+								$file_path, $tour), __FILE__, __FUNCTION__, __LINE__);
1127
+						return;
1128
+					}
1129
+					require_once $file_path;
1130
+					if ( ! class_exists($tour)) {
1131
+						$error_msg[] = sprintf(__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'), $tour);
1132
+						$error_msg[] = $error_msg[0] . "\r\n" . sprintf(__('There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1133
+										'event_espresso'), $tour, '<br />', $tour, $this->_req_action, get_class($this));
1134
+						throw new EE_Error(implode('||', $error_msg));
1135
+					}
1136
+					$a = new ReflectionClass($tour);
1137
+					$tour_obj = $a->newInstance($this->_is_caf);
1138
+					$tours[] = $tour_obj;
1139
+					$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1140
+				}
1141
+				//let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1142
+				$end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1143
+				$tours[] = $end_stop_tour;
1144
+				$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1145
+			}
1146
+		}
1147
+		if ( ! empty($tours)) {
1148
+			$this->_help_tour['tours'] = $tours;
1149
+		}
1150
+		//thats it!  Now that the $_help_tours property is set (or not) the scripts and html should be taken care of automatically.
1151
+	}
1152
+
1153
+
1154
+
1155
+	/**
1156
+	 * This simply sets up any qtips that have been defined in the page config
1157
+	 *
1158
+	 * @access protected
1159
+	 * @return void
1160
+	 */
1161
+	protected function _add_qtips()
1162
+	{
1163
+		if (isset($this->_route_config['qtips'])) {
1164
+			$qtips = (array)$this->_route_config['qtips'];
1165
+			//load qtip loader
1166
+			$path = array(
1167
+					$this->_get_dir() . '/qtips/',
1168
+					EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1169
+			);
1170
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1171
+		}
1172
+	}
1173
+
1174
+
1175
+
1176
+	/**
1177
+	 * _set_nav_tabs
1178
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you wish to add additional tabs or modify accordingly.
1179
+	 *
1180
+	 * @access protected
1181
+	 * @return void
1182
+	 */
1183
+	protected function _set_nav_tabs()
1184
+	{
1185
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1186
+		$i = 0;
1187
+		foreach ($this->_page_config as $slug => $config) {
1188
+			if ( ! is_array($config) || (is_array($config) && (isset($config['nav']) && ! $config['nav']) || ! isset($config['nav']))) {
1189
+				continue;
1190
+			} //no nav tab for this config
1191
+			//check for persistent flag
1192
+			if (isset($config['nav']['persistent']) && ! $config['nav']['persistent'] && $slug !== $this->_req_action) {
1193
+				continue;
1194
+			} //nav tab is only to appear when route requested.
1195
+			if ( ! $this->check_user_access($slug, true)) {
1196
+				continue;
1197
+			} //no nav tab becasue current user does not have access.
1198
+			$css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1199
+			$this->_nav_tabs[$slug] = array(
1200
+					'url'       => isset($config['nav']['url']) ? $config['nav']['url'] : self::add_query_args_and_nonce(array('action' => $slug), $this->_admin_base_url),
1201
+					'link_text' => isset($config['nav']['label']) ? $config['nav']['label'] : ucwords(str_replace('_', ' ', $slug)),
1202
+					'css_class' => $this->_req_action == $slug ? $css_class . 'nav-tab-active' : $css_class,
1203
+					'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1204
+			);
1205
+			$i++;
1206
+		}
1207
+		//if $this->_nav_tabs is empty then lets set the default
1208
+		if (empty($this->_nav_tabs)) {
1209
+			$this->_nav_tabs[$this->default_nav_tab_name] = array(
1210
+					'url'       => $this->admin_base_url,
1211
+					'link_text' => ucwords(str_replace('_', ' ', $this->default_nav_tab_name)),
1212
+					'css_class' => 'nav-tab-active',
1213
+					'order'     => 10,
1214
+			);
1215
+		}
1216
+		//now let's sort the tabs according to order
1217
+		usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1218
+	}
1219
+
1220
+
1221
+
1222
+	/**
1223
+	 * _set_current_labels
1224
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes property array
1225
+	 *
1226
+	 * @access private
1227
+	 * @return void
1228
+	 */
1229
+	private function _set_current_labels()
1230
+	{
1231
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1232
+			foreach ($this->_route_config['labels'] as $label => $text) {
1233
+				if (is_array($text)) {
1234
+					foreach ($text as $sublabel => $subtext) {
1235
+						$this->_labels[$label][$sublabel] = $subtext;
1236
+					}
1237
+				} else {
1238
+					$this->_labels[$label] = $text;
1239
+				}
1240
+			}
1241
+		}
1242
+	}
1243
+
1244
+
1245
+
1246
+	/**
1247
+	 *        verifies user access for this admin page
1248
+	 *
1249
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1250
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just return false if verify fail.
1251
+	 * @return        BOOL|wp_die()
1252
+	 */
1253
+	public function check_user_access($route_to_check = '', $verify_only = false)
1254
+	{
1255
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1256
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1257
+		$capability = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check]) && is_array($this->_page_routes[$route_to_check]) && ! empty($this->_page_routes[$route_to_check]['capability'])
1258
+				? $this->_page_routes[$route_to_check]['capability'] : null;
1259
+		if (empty($capability) && empty($route_to_check)) {
1260
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options' : $this->_route['capability'];
1261
+		} else {
1262
+			$capability = empty($capability) ? 'manage_options' : $capability;
1263
+		}
1264
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1265
+		if (( ! function_exists('is_admin') || ! EE_Registry::instance()->CAP->current_user_can($capability, $this->page_slug . '_' . $route_to_check, $id)) && ! defined('DOING_AJAX')) {
1266
+			if ($verify_only) {
1267
+				return false;
1268
+			} else {
1269
+				if ( is_user_logged_in() ) {
1270
+					wp_die(__('You do not have access to this route.', 'event_espresso'));
1271
+				} else {
1272
+					return false;
1273
+				}
1274
+			}
1275
+		}
1276
+		return true;
1277
+	}
1278
+
1279
+
1280
+
1281
+	/**
1282
+	 * admin_init_global
1283
+	 * This runs all the code that we want executed within the WP admin_init hook.
1284
+	 * This method executes for ALL EE Admin pages.
1285
+	 *
1286
+	 * @access public
1287
+	 * @return void
1288
+	 */
1289
+	public function admin_init_global()
1290
+	{
1291
+	}
1292
+
1293
+
1294
+
1295
+	/**
1296
+	 * wp_loaded_global
1297
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an EE_Admin page and will execute on every EE Admin Page load
1298
+	 *
1299
+	 * @access public
1300
+	 * @return void
1301
+	 */
1302
+	public function wp_loaded()
1303
+	{
1304
+	}
1305
+
1306
+
1307
+
1308
+	/**
1309
+	 * admin_notices
1310
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on ALL EE_Admin pages.
1311
+	 *
1312
+	 * @access public
1313
+	 * @return void
1314
+	 */
1315
+	public function admin_notices_global()
1316
+	{
1317
+		$this->_display_no_javascript_warning();
1318
+		$this->_display_espresso_notices();
1319
+	}
1320
+
1321
+
1322
+
1323
+	public function network_admin_notices_global()
1324
+	{
1325
+		$this->_display_no_javascript_warning();
1326
+		$this->_display_espresso_notices();
1327
+	}
1328
+
1329
+
1330
+
1331
+	/**
1332
+	 * admin_footer_scripts_global
1333
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply on ALL EE_Admin pages.
1334
+	 *
1335
+	 * @access public
1336
+	 * @return void
1337
+	 */
1338
+	public function admin_footer_scripts_global()
1339
+	{
1340
+		$this->_add_admin_page_ajax_loading_img();
1341
+		$this->_add_admin_page_overlay();
1342
+		//if metaboxes are present we need to add the nonce field
1343
+		if ((isset($this->_route_config['metaboxes']) || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes']) || isset($this->_route_config['list_table']))) {
1344
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1345
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1346
+		}
1347
+	}
1348
+
1349
+
1350
+
1351
+	/**
1352
+	 * admin_footer_global
1353
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particluar method will apply on ALL EE_Admin Pages.
1354
+	 *
1355
+	 * @access  public
1356
+	 * @return  void
1357
+	 */
1358
+	public function admin_footer_global()
1359
+	{
1360
+		//dialog container for dialog helper
1361
+		$d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1362
+		$d_cont .= '<div class="ee-notices"></div>';
1363
+		$d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1364
+		$d_cont .= '</div>';
1365
+		echo $d_cont;
1366
+		//help tour stuff?
1367
+		if (isset($this->_help_tour[$this->_req_action])) {
1368
+			echo implode('<br />', $this->_help_tour[$this->_req_action]);
1369
+		}
1370
+		//current set timezone for timezone js
1371
+		echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1372
+	}
1373
+
1374
+
1375
+
1376
+	/**
1377
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then we'll use the retrieved array to output the content using the template.
1378
+	 * For child classes:
1379
+	 * If you want to have help popups then in your templates or your content you set "triggers" for the content using the "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method for
1380
+	 * the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content for the
1381
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1382
+	 *    'help_trigger_id' => array(
1383
+	 *        'title' => __('localized title for popup', 'event_espresso'),
1384
+	 *        'content' => __('localized content for popup', 'event_espresso')
1385
+	 *    )
1386
+	 * );
1387
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1388
+	 *
1389
+	 * @access protected
1390
+	 * @return string content
1391
+	 */
1392
+	protected function _set_help_popup_content($help_array = array(), $display = false)
1393
+	{
1394
+		$content = '';
1395
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1396
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php';
1397
+		//loop through the array and setup content
1398
+		foreach ($help_array as $trigger => $help) {
1399
+			//make sure the array is setup properly
1400
+			if ( ! isset($help['title']) || ! isset($help['content'])) {
1401
+				throw new EE_Error(__('Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1402
+						'event_espresso'));
1403
+			}
1404
+			//we're good so let'd setup the template vars and then assign parsed template content to our content.
1405
+			$template_args = array(
1406
+					'help_popup_id'      => $trigger,
1407
+					'help_popup_title'   => $help['title'],
1408
+					'help_popup_content' => $help['content'],
1409
+			);
1410
+			$content .= EEH_Template::display_template($template_path, $template_args, true);
1411
+		}
1412
+		if ($display) {
1413
+			echo $content;
1414
+		} else {
1415
+			return $content;
1416
+		}
1417
+	}
1418
+
1419
+
1420
+
1421
+	/**
1422
+	 * All this does is retrive the help content array if set by the EE_Admin_Page child
1423
+	 *
1424
+	 * @access private
1425
+	 * @return array properly formatted array for help popup content
1426
+	 */
1427
+	private function _get_help_content()
1428
+	{
1429
+		//what is the method we're looking for?
1430
+		$method_name = '_help_popup_content_' . $this->_req_action;
1431
+		//if method doesn't exist let's get out.
1432
+		if ( ! method_exists($this, $method_name)) {
1433
+			return array();
1434
+		}
1435
+		//k we're good to go let's retrieve the help array
1436
+		$help_array = call_user_func(array($this, $method_name));
1437
+		//make sure we've got an array!
1438
+		if ( ! is_array($help_array)) {
1439
+			throw new EE_Error(__('Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.', 'event_espresso'));
1440
+		}
1441
+		return $help_array;
1442
+	}
1443
+
1444
+
1445
+
1446
+	/**
1447
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1448
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1449
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1450
+	 *
1451
+	 * @access protected
1452
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1453
+	 * @param boolean $display    if false then we return the trigger string
1454
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1455
+	 * @return string
1456
+	 */
1457
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1458
+	{
1459
+		if (defined('DOING_AJAX')) {
1460
+			return;
1461
+		}
1462
+		//let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1463
+		$help_array = $this->_get_help_content();
1464
+		$help_content = '';
1465
+		if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1466
+			$help_array[$trigger_id] = array(
1467
+					'title'   => __('Missing Content', 'event_espresso'),
1468
+					'content' => __('A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1469
+							'event_espresso'),
1470
+			);
1471
+			$help_content = $this->_set_help_popup_content($help_array, false);
1472
+		}
1473
+		//let's setup the trigger
1474
+		$content = '<a class="ee-dialog" href="?height=' . $dimensions[0] . '&width=' . $dimensions[1] . '&inlineId=' . $trigger_id . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1475
+		$content = $content . $help_content;
1476
+		if ($display) {
1477
+			echo $content;
1478
+		} else {
1479
+			return $content;
1480
+		}
1481
+	}
1482
+
1483
+
1484
+
1485
+	/**
1486
+	 * _add_global_screen_options
1487
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1488
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1489
+	 *
1490
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1491
+	 *         see also WP_Screen object documents...
1492
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1493
+	 * @abstract
1494
+	 * @access private
1495
+	 * @return void
1496
+	 */
1497
+	private function _add_global_screen_options()
1498
+	{
1499
+	}
1500
+
1501
+
1502
+
1503
+	/**
1504
+	 * _add_global_feature_pointers
1505
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1506
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1507
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1508
+	 *
1509
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
1510
+	 * @link   http://eamann.com/tech/wordpress-portland/
1511
+	 * @abstract
1512
+	 * @access protected
1513
+	 * @return void
1514
+	 */
1515
+	private function _add_global_feature_pointers()
1516
+	{
1517
+	}
1518
+
1519
+
1520
+
1521
+	/**
1522
+	 * load_global_scripts_styles
1523
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1524
+	 *
1525
+	 * @return void
1526
+	 */
1527
+	public function load_global_scripts_styles()
1528
+	{
1529
+		/** STYLES **/
1530
+		// add debugging styles
1531
+		if (WP_DEBUG) {
1532
+			add_action('admin_head', array($this, 'add_xdebug_style'));
1533
+		}
1534
+		//register all styles
1535
+		wp_register_style('espresso-ui-theme', EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css', array(), EVENT_ESPRESSO_VERSION);
1536
+		wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1537
+		//helpers styles
1538
+		wp_register_style('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css', array(), EVENT_ESPRESSO_VERSION);
1539
+		//enqueue global styles
1540
+		wp_enqueue_style('ee-admin-css');
1541
+		/** SCRIPTS **/
1542
+		//register all scripts
1543
+		wp_register_script('espresso_core', EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1544
+		wp_register_script('ee-dialog', EE_ADMIN_URL . 'assets/ee-dialog-helper.js', array('jquery', 'jquery-ui-draggable'), EVENT_ESPRESSO_VERSION, true);
1545
+		wp_register_script('ee_admin_js', EE_ADMIN_URL . 'assets/ee-admin-page.js', array('espresso_core', 'ee-parse-uri', 'ee-dialog'), EVENT_ESPRESSO_VERSION, true);
1546
+		wp_register_script('jquery-ui-timepicker-addon', EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js', array('jquery-ui-datepicker', 'jquery-ui-slider'), EVENT_ESPRESSO_VERSION, true);
1547
+		// register jQuery Validate - see /includes/functions/wp_hooks.php
1548
+		add_filter('FHEE_load_jquery_validate', '__return_true');
1549
+		add_filter('FHEE_load_joyride', '__return_true');
1550
+		//script for sorting tables
1551
+		wp_register_script('espresso_ajax_table_sorting', EE_ADMIN_URL . "assets/espresso_ajax_table_sorting.js", array('ee_admin_js', 'jquery-ui-sortable'), EVENT_ESPRESSO_VERSION, true);
1552
+		//script for parsing uri's
1553
+		wp_register_script('ee-parse-uri', EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js', array(), EVENT_ESPRESSO_VERSION, true);
1554
+		//and parsing associative serialized form elements
1555
+		wp_register_script('ee-serialize-full-array', EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1556
+		//helpers scripts
1557
+		wp_register_script('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1558
+		wp_register_script('ee-moment-core', EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js', array(), EVENT_ESPRESSO_VERSION, true);
1559
+		wp_register_script('ee-moment', EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js', array('ee-moment-core'), EVENT_ESPRESSO_VERSION, true);
1560
+		wp_register_script('ee-datepicker', EE_ADMIN_URL . 'assets/ee-datepicker.js', array('jquery-ui-timepicker-addon', 'ee-moment'), EVENT_ESPRESSO_VERSION, true);
1561
+		//google charts
1562
+		wp_register_script('google-charts', 'https://www.gstatic.com/charts/loader.js', array(), EVENT_ESPRESSO_VERSION, false);
1563
+		//enqueue global scripts
1564
+		//taking care of metaboxes
1565
+		if ((isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes'])) && empty($this->_cpt_route)) {
1566
+			wp_enqueue_script('dashboard');
1567
+		}
1568
+		//enqueue thickbox for ee help popups.  default is to enqueue unless its explicitly set to false since we're assuming all EE pages will have popups
1569
+		if ( ! isset($this->_route_config['has_help_popups']) || (isset($this->_route_config['has_help_popups']) && $this->_route_config['has_help_popups'])) {
1570
+			wp_enqueue_script('ee_admin_js');
1571
+			wp_enqueue_style('ee-admin-css');
1572
+		}
1573
+		//localize script for ajax lazy loading
1574
+		$lazy_loader_container_ids = apply_filters('FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers', array('espresso_news_post_box_content'));
1575
+		wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1576
+		/**
1577
+		 * help tour stuff
1578
+		 */
1579
+		if ( ! empty($this->_help_tour)) {
1580
+			//register the js for kicking things off
1581
+			wp_enqueue_script('ee-help-tour', EE_ADMIN_URL . 'assets/ee-help-tour.js', array('jquery-joyride'), EVENT_ESPRESSO_VERSION, true);
1582
+			//setup tours for the js tour object
1583
+			foreach ($this->_help_tour['tours'] as $tour) {
1584
+				$tours[] = array(
1585
+						'id'      => $tour->get_slug(),
1586
+						'options' => $tour->get_options(),
1587
+				);
1588
+			}
1589
+			wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
1590
+			//admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1591
+		}
1592
+	}
1593
+
1594
+
1595
+
1596
+	/**
1597
+	 *        admin_footer_scripts_eei18n_js_strings
1598
+	 *
1599
+	 * @access        public
1600
+	 * @return        void
1601
+	 */
1602
+	public function admin_footer_scripts_eei18n_js_strings()
1603
+	{
1604
+		EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
1605
+		EE_Registry::$i18n_js_strings['confirm_delete'] = __('Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!', 'event_espresso');
1606
+		EE_Registry::$i18n_js_strings['January'] = __('January', 'event_espresso');
1607
+		EE_Registry::$i18n_js_strings['February'] = __('February', 'event_espresso');
1608
+		EE_Registry::$i18n_js_strings['March'] = __('March', 'event_espresso');
1609
+		EE_Registry::$i18n_js_strings['April'] = __('April', 'event_espresso');
1610
+		EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1611
+		EE_Registry::$i18n_js_strings['June'] = __('June', 'event_espresso');
1612
+		EE_Registry::$i18n_js_strings['July'] = __('July', 'event_espresso');
1613
+		EE_Registry::$i18n_js_strings['August'] = __('August', 'event_espresso');
1614
+		EE_Registry::$i18n_js_strings['September'] = __('September', 'event_espresso');
1615
+		EE_Registry::$i18n_js_strings['October'] = __('October', 'event_espresso');
1616
+		EE_Registry::$i18n_js_strings['November'] = __('November', 'event_espresso');
1617
+		EE_Registry::$i18n_js_strings['December'] = __('December', 'event_espresso');
1618
+		EE_Registry::$i18n_js_strings['Jan'] = __('Jan', 'event_espresso');
1619
+		EE_Registry::$i18n_js_strings['Feb'] = __('Feb', 'event_espresso');
1620
+		EE_Registry::$i18n_js_strings['Mar'] = __('Mar', 'event_espresso');
1621
+		EE_Registry::$i18n_js_strings['Apr'] = __('Apr', 'event_espresso');
1622
+		EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1623
+		EE_Registry::$i18n_js_strings['Jun'] = __('Jun', 'event_espresso');
1624
+		EE_Registry::$i18n_js_strings['Jul'] = __('Jul', 'event_espresso');
1625
+		EE_Registry::$i18n_js_strings['Aug'] = __('Aug', 'event_espresso');
1626
+		EE_Registry::$i18n_js_strings['Sep'] = __('Sep', 'event_espresso');
1627
+		EE_Registry::$i18n_js_strings['Oct'] = __('Oct', 'event_espresso');
1628
+		EE_Registry::$i18n_js_strings['Nov'] = __('Nov', 'event_espresso');
1629
+		EE_Registry::$i18n_js_strings['Dec'] = __('Dec', 'event_espresso');
1630
+		EE_Registry::$i18n_js_strings['Sunday'] = __('Sunday', 'event_espresso');
1631
+		EE_Registry::$i18n_js_strings['Monday'] = __('Monday', 'event_espresso');
1632
+		EE_Registry::$i18n_js_strings['Tuesday'] = __('Tuesday', 'event_espresso');
1633
+		EE_Registry::$i18n_js_strings['Wednesday'] = __('Wednesday', 'event_espresso');
1634
+		EE_Registry::$i18n_js_strings['Thursday'] = __('Thursday', 'event_espresso');
1635
+		EE_Registry::$i18n_js_strings['Friday'] = __('Friday', 'event_espresso');
1636
+		EE_Registry::$i18n_js_strings['Saturday'] = __('Saturday', 'event_espresso');
1637
+		EE_Registry::$i18n_js_strings['Sun'] = __('Sun', 'event_espresso');
1638
+		EE_Registry::$i18n_js_strings['Mon'] = __('Mon', 'event_espresso');
1639
+		EE_Registry::$i18n_js_strings['Tue'] = __('Tue', 'event_espresso');
1640
+		EE_Registry::$i18n_js_strings['Wed'] = __('Wed', 'event_espresso');
1641
+		EE_Registry::$i18n_js_strings['Thu'] = __('Thu', 'event_espresso');
1642
+		EE_Registry::$i18n_js_strings['Fri'] = __('Fri', 'event_espresso');
1643
+		EE_Registry::$i18n_js_strings['Sat'] = __('Sat', 'event_espresso');
1644
+		//setting on espresso_core instead of ee_admin_js because espresso_core is enqueued by the maintenance
1645
+		//admin page when in maintenance mode and ee_admin_js is not loaded then.  This works everywhere else because
1646
+		//espresso_core is listed as a dependency of ee_admin_js.
1647
+		wp_localize_script('espresso_core', 'eei18n', EE_Registry::$i18n_js_strings);
1648
+	}
1649
+
1650
+
1651
+
1652
+	/**
1653
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1654
+	 *
1655
+	 * @access        public
1656
+	 * @return        void
1657
+	 */
1658
+	public function add_xdebug_style()
1659
+	{
1660
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1661
+	}
1662
+
1663
+
1664
+	/************************/
1665
+	/** LIST TABLE METHODS **/
1666
+	/************************/
1667
+	/**
1668
+	 * this sets up the list table if the current view requires it.
1669
+	 *
1670
+	 * @access protected
1671
+	 * @return void
1672
+	 */
1673
+	protected function _set_list_table()
1674
+	{
1675
+		//first is this a list_table view?
1676
+		if ( ! isset($this->_route_config['list_table'])) {
1677
+			return;
1678
+		} //not a list_table view so get out.
1679
+		//list table functions are per view specific (because some admin pages might have more than one listtable!)
1680
+		if (call_user_func(array($this, '_set_list_table_views_' . $this->_req_action)) === false) {
1681
+			//user error msg
1682
+			$error_msg = __('An error occurred. The requested list table views could not be found.', 'event_espresso');
1683
+			//developer error msg
1684
+			$error_msg .= '||' . sprintf(__('List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.', 'event_espresso'),
1685
+							$this->_req_action, '_set_list_table_views_' . $this->_req_action);
1686
+			throw new EE_Error($error_msg);
1687
+		}
1688
+		//let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
1689
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action, $this->_views);
1690
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
1691
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
1692
+		$this->_set_list_table_view();
1693
+		$this->_set_list_table_object();
1694
+	}
1695
+
1696
+
1697
+
1698
+	/**
1699
+	 *        set current view for List Table
1700
+	 *
1701
+	 * @access public
1702
+	 * @return array
1703
+	 */
1704
+	protected function _set_list_table_view()
1705
+	{
1706
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1707
+		// looking at active items or dumpster diving ?
1708
+		if ( ! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
1709
+			$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
1710
+		} else {
1711
+			$this->_view = sanitize_key($this->_req_data['status']);
1712
+		}
1713
+	}
1714
+
1715
+
1716
+
1717
+	/**
1718
+	 * _set_list_table_object
1719
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
1720
+	 *
1721
+	 * @throws \EE_Error
1722
+	 */
1723
+	protected function _set_list_table_object()
1724
+	{
1725
+		if (isset($this->_route_config['list_table'])) {
1726
+			if ( ! class_exists($this->_route_config['list_table'])) {
1727
+				throw new EE_Error(
1728
+						sprintf(
1729
+								__(
1730
+										'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
1731
+										'event_espresso'
1732
+								),
1733
+								$this->_route_config['list_table'],
1734
+								get_class($this)
1735
+						)
1736
+				);
1737
+			}
1738
+			$list_table = $this->_route_config['list_table'];
1739
+			$this->_list_table_object = new $list_table($this);
1740
+		}
1741
+	}
1742
+
1743
+
1744
+
1745
+	/**
1746
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
1747
+	 *
1748
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
1749
+	 *                                                    urls.  The array should be indexed by the view it is being
1750
+	 *                                                    added to.
1751
+	 * @return array
1752
+	 */
1753
+	public function get_list_table_view_RLs($extra_query_args = array())
1754
+	{
1755
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1756
+		if (empty($this->_views)) {
1757
+			$this->_views = array();
1758
+		}
1759
+		// cycle thru views
1760
+		foreach ($this->_views as $key => $view) {
1761
+			$query_args = array();
1762
+			// check for current view
1763
+			$this->_views[$key]['class'] = $this->_view == $view['slug'] ? 'current' : '';
1764
+			$query_args['action'] = $this->_req_action;
1765
+			$query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
1766
+			$query_args['status'] = $view['slug'];
1767
+			//merge any other arguments sent in.
1768
+			if (isset($extra_query_args[$view['slug']])) {
1769
+				$query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
1770
+			}
1771
+			$this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1772
+		}
1773
+		return $this->_views;
1774
+	}
1775
+
1776
+
1777
+
1778
+	/**
1779
+	 * _entries_per_page_dropdown
1780
+	 * generates a drop down box for selecting the number of visiable rows in an admin page list table
1781
+	 *
1782
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how WP does it.
1783
+	 * @access protected
1784
+	 * @param int $max_entries total number of rows in the table
1785
+	 * @return string
1786
+	 */
1787
+	protected function _entries_per_page_dropdown($max_entries = false)
1788
+	{
1789
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1790
+		$values = array(10, 25, 50, 100);
1791
+		$per_page = ( ! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
1792
+		if ($max_entries) {
1793
+			$values[] = $max_entries;
1794
+			sort($values);
1795
+		}
1796
+		$entries_per_page_dropdown = '
1797 1797
 			<div id="entries-per-page-dv" class="alignleft actions">
1798 1798
 				<label class="hide-if-no-js">
1799 1799
 					Show
1800 1800
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
1801
-        foreach ($values as $value) {
1802
-            if ($value < $max_entries) {
1803
-                $selected = $value == $per_page ? ' selected="' . $per_page . '"' : '';
1804
-                $entries_per_page_dropdown .= '
1801
+		foreach ($values as $value) {
1802
+			if ($value < $max_entries) {
1803
+				$selected = $value == $per_page ? ' selected="' . $per_page . '"' : '';
1804
+				$entries_per_page_dropdown .= '
1805 1805
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
1806
-            }
1807
-        }
1808
-        $selected = $max_entries == $per_page ? ' selected="' . $per_page . '"' : '';
1809
-        $entries_per_page_dropdown .= '
1806
+			}
1807
+		}
1808
+		$selected = $max_entries == $per_page ? ' selected="' . $per_page . '"' : '';
1809
+		$entries_per_page_dropdown .= '
1810 1810
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
1811
-        $entries_per_page_dropdown .= '
1811
+		$entries_per_page_dropdown .= '
1812 1812
 					</select>
1813 1813
 					entries
1814 1814
 				</label>
1815 1815
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
1816 1816
 			</div>
1817 1817
 		';
1818
-        return $entries_per_page_dropdown;
1819
-    }
1820
-
1821
-
1822
-
1823
-    /**
1824
-     *        _set_search_attributes
1825
-     *
1826
-     * @access        protected
1827
-     * @return        void
1828
-     */
1829
-    public function _set_search_attributes()
1830
-    {
1831
-        $this->_template_args['search']['btn_label'] = sprintf(__('Search %s', 'event_espresso'), empty($this->_search_btn_label) ? $this->page_label : $this->_search_btn_label);
1832
-        $this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
1833
-    }
1834
-
1835
-    /*** END LIST TABLE METHODS **/
1836
-    /*****************************/
1837
-    /**
1838
-     *        _add_registered_metaboxes
1839
-     *        this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
1840
-     *
1841
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
1842
-     * @access private
1843
-     * @return void
1844
-     */
1845
-    private function _add_registered_meta_boxes()
1846
-    {
1847
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1848
-        //we only add meta boxes if the page_route calls for it
1849
-        if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
1850
-            && is_array(
1851
-                    $this->_route_config['metaboxes']
1852
-            )
1853
-        ) {
1854
-            // this simply loops through the callbacks provided
1855
-            // and checks if there is a corresponding callback registered by the child
1856
-            // if there is then we go ahead and process the metabox loader.
1857
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
1858
-                // first check for Closures
1859
-                if ($metabox_callback instanceof Closure) {
1860
-                    $result = $metabox_callback();
1861
-                } else if (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
1862
-                    $result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
1863
-                } else {
1864
-                    $result = call_user_func(array($this, &$metabox_callback));
1865
-                }
1866
-                if ($result === false) {
1867
-                    // user error msg
1868
-                    $error_msg = __('An error occurred. The  requested metabox could not be found.', 'event_espresso');
1869
-                    // developer error msg
1870
-                    $error_msg .= '||' . sprintf(
1871
-                                    __(
1872
-                                            'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
1873
-                                            'event_espresso'
1874
-                                    ),
1875
-                                    $metabox_callback
1876
-                            );
1877
-                    throw new EE_Error($error_msg);
1878
-                }
1879
-            }
1880
-        }
1881
-    }
1882
-
1883
-
1884
-
1885
-    /**
1886
-     * _add_screen_columns
1887
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as the dynamic column template and we'll setup the column options for the page.
1888
-     *
1889
-     * @access private
1890
-     * @return void
1891
-     */
1892
-    private function _add_screen_columns()
1893
-    {
1894
-        if (
1895
-                is_array($this->_route_config)
1896
-                && isset($this->_route_config['columns'])
1897
-                && is_array($this->_route_config['columns'])
1898
-                && count($this->_route_config['columns']) === 2
1899
-        ) {
1900
-            add_screen_option('layout_columns', array('max' => (int)$this->_route_config['columns'][0], 'default' => (int)$this->_route_config['columns'][1]));
1901
-            $this->_template_args['num_columns'] = $this->_route_config['columns'][0];
1902
-            $screen_id = $this->_current_screen->id;
1903
-            $screen_columns = (int)get_user_option("screen_layout_$screen_id");
1904
-            $total_columns = ! empty($screen_columns) ? $screen_columns : $this->_route_config['columns'][1];
1905
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
1906
-            $this->_template_args['current_page'] = $this->_wp_page_slug;
1907
-            $this->_template_args['screen'] = $this->_current_screen;
1908
-            $this->_column_template_path = EE_ADMIN_TEMPLATE . 'admin_details_metabox_column_wrapper.template.php';
1909
-            //finally if we don't have has_metaboxes set in the route config let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
1910
-            $this->_route_config['has_metaboxes'] = true;
1911
-        }
1912
-    }
1913
-
1914
-
1915
-
1916
-    /**********************************/
1917
-    /** GLOBALLY AVAILABLE METABOXES **/
1918
-    /**
1919
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply referencing the callback in the _page_config array property.  This way you can be very specific about what pages these get
1920
-     * loaded on.
1921
-     */
1922
-    private function _espresso_news_post_box()
1923
-    {
1924
-        $news_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('New @ Event Espresso', 'event_espresso'));
1925
-        add_meta_box('espresso_news_post_box', $news_box_title, array(
1926
-                $this,
1927
-                'espresso_news_post_box',
1928
-        ), $this->_wp_page_slug, 'side');
1929
-    }
1930
-
1931
-
1932
-
1933
-    /**
1934
-     * Code for setting up espresso ratings request metabox.
1935
-     */
1936
-    protected function _espresso_ratings_request()
1937
-    {
1938
-        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
1939
-            return '';
1940
-        }
1941
-        $ratings_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('Keep Event Espresso Decaf Free', 'event_espresso'));
1942
-        add_meta_box('espresso_ratings_request', $ratings_box_title, array(
1943
-                $this,
1944
-                'espresso_ratings_request',
1945
-        ), $this->_wp_page_slug, 'side');
1946
-    }
1947
-
1948
-
1949
-
1950
-    /**
1951
-     * Code for setting up espresso ratings request metabox content.
1952
-     */
1953
-    public function espresso_ratings_request()
1954
-    {
1955
-        $template_path = EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php';
1956
-        EEH_Template::display_template($template_path, array());
1957
-    }
1958
-
1959
-
1960
-
1961
-    public static function cached_rss_display($rss_id, $url)
1962
-    {
1963
-        $loading = '<p class="widget-loading hide-if-no-js">' . __('Loading&#8230;') . '</p><p class="hide-if-js">' . __('This widget requires JavaScript.') . '</p>';
1964
-        $doing_ajax = (defined('DOING_AJAX') && DOING_AJAX);
1965
-        $pre = '<div class="espresso-rss-display">' . "\n\t";
1966
-        $pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
1967
-        $post = '</div>' . "\n";
1968
-        $cache_key = 'ee_rss_' . md5($rss_id);
1969
-        if (false != ($output = get_transient($cache_key))) {
1970
-            echo $pre . $output . $post;
1971
-            return true;
1972
-        }
1973
-        if ( ! $doing_ajax) {
1974
-            echo $pre . $loading . $post;
1975
-            return false;
1976
-        }
1977
-        ob_start();
1978
-        wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
1979
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
1980
-        return true;
1981
-    }
1982
-
1983
-
1984
-
1985
-    public function espresso_news_post_box()
1986
-    {
1987
-        ?>
1818
+		return $entries_per_page_dropdown;
1819
+	}
1820
+
1821
+
1822
+
1823
+	/**
1824
+	 *        _set_search_attributes
1825
+	 *
1826
+	 * @access        protected
1827
+	 * @return        void
1828
+	 */
1829
+	public function _set_search_attributes()
1830
+	{
1831
+		$this->_template_args['search']['btn_label'] = sprintf(__('Search %s', 'event_espresso'), empty($this->_search_btn_label) ? $this->page_label : $this->_search_btn_label);
1832
+		$this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
1833
+	}
1834
+
1835
+	/*** END LIST TABLE METHODS **/
1836
+	/*****************************/
1837
+	/**
1838
+	 *        _add_registered_metaboxes
1839
+	 *        this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
1840
+	 *
1841
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
1842
+	 * @access private
1843
+	 * @return void
1844
+	 */
1845
+	private function _add_registered_meta_boxes()
1846
+	{
1847
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1848
+		//we only add meta boxes if the page_route calls for it
1849
+		if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
1850
+			&& is_array(
1851
+					$this->_route_config['metaboxes']
1852
+			)
1853
+		) {
1854
+			// this simply loops through the callbacks provided
1855
+			// and checks if there is a corresponding callback registered by the child
1856
+			// if there is then we go ahead and process the metabox loader.
1857
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
1858
+				// first check for Closures
1859
+				if ($metabox_callback instanceof Closure) {
1860
+					$result = $metabox_callback();
1861
+				} else if (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
1862
+					$result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
1863
+				} else {
1864
+					$result = call_user_func(array($this, &$metabox_callback));
1865
+				}
1866
+				if ($result === false) {
1867
+					// user error msg
1868
+					$error_msg = __('An error occurred. The  requested metabox could not be found.', 'event_espresso');
1869
+					// developer error msg
1870
+					$error_msg .= '||' . sprintf(
1871
+									__(
1872
+											'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
1873
+											'event_espresso'
1874
+									),
1875
+									$metabox_callback
1876
+							);
1877
+					throw new EE_Error($error_msg);
1878
+				}
1879
+			}
1880
+		}
1881
+	}
1882
+
1883
+
1884
+
1885
+	/**
1886
+	 * _add_screen_columns
1887
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as the dynamic column template and we'll setup the column options for the page.
1888
+	 *
1889
+	 * @access private
1890
+	 * @return void
1891
+	 */
1892
+	private function _add_screen_columns()
1893
+	{
1894
+		if (
1895
+				is_array($this->_route_config)
1896
+				&& isset($this->_route_config['columns'])
1897
+				&& is_array($this->_route_config['columns'])
1898
+				&& count($this->_route_config['columns']) === 2
1899
+		) {
1900
+			add_screen_option('layout_columns', array('max' => (int)$this->_route_config['columns'][0], 'default' => (int)$this->_route_config['columns'][1]));
1901
+			$this->_template_args['num_columns'] = $this->_route_config['columns'][0];
1902
+			$screen_id = $this->_current_screen->id;
1903
+			$screen_columns = (int)get_user_option("screen_layout_$screen_id");
1904
+			$total_columns = ! empty($screen_columns) ? $screen_columns : $this->_route_config['columns'][1];
1905
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
1906
+			$this->_template_args['current_page'] = $this->_wp_page_slug;
1907
+			$this->_template_args['screen'] = $this->_current_screen;
1908
+			$this->_column_template_path = EE_ADMIN_TEMPLATE . 'admin_details_metabox_column_wrapper.template.php';
1909
+			//finally if we don't have has_metaboxes set in the route config let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
1910
+			$this->_route_config['has_metaboxes'] = true;
1911
+		}
1912
+	}
1913
+
1914
+
1915
+
1916
+	/**********************************/
1917
+	/** GLOBALLY AVAILABLE METABOXES **/
1918
+	/**
1919
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply referencing the callback in the _page_config array property.  This way you can be very specific about what pages these get
1920
+	 * loaded on.
1921
+	 */
1922
+	private function _espresso_news_post_box()
1923
+	{
1924
+		$news_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('New @ Event Espresso', 'event_espresso'));
1925
+		add_meta_box('espresso_news_post_box', $news_box_title, array(
1926
+				$this,
1927
+				'espresso_news_post_box',
1928
+		), $this->_wp_page_slug, 'side');
1929
+	}
1930
+
1931
+
1932
+
1933
+	/**
1934
+	 * Code for setting up espresso ratings request metabox.
1935
+	 */
1936
+	protected function _espresso_ratings_request()
1937
+	{
1938
+		if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
1939
+			return '';
1940
+		}
1941
+		$ratings_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('Keep Event Espresso Decaf Free', 'event_espresso'));
1942
+		add_meta_box('espresso_ratings_request', $ratings_box_title, array(
1943
+				$this,
1944
+				'espresso_ratings_request',
1945
+		), $this->_wp_page_slug, 'side');
1946
+	}
1947
+
1948
+
1949
+
1950
+	/**
1951
+	 * Code for setting up espresso ratings request metabox content.
1952
+	 */
1953
+	public function espresso_ratings_request()
1954
+	{
1955
+		$template_path = EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php';
1956
+		EEH_Template::display_template($template_path, array());
1957
+	}
1958
+
1959
+
1960
+
1961
+	public static function cached_rss_display($rss_id, $url)
1962
+	{
1963
+		$loading = '<p class="widget-loading hide-if-no-js">' . __('Loading&#8230;') . '</p><p class="hide-if-js">' . __('This widget requires JavaScript.') . '</p>';
1964
+		$doing_ajax = (defined('DOING_AJAX') && DOING_AJAX);
1965
+		$pre = '<div class="espresso-rss-display">' . "\n\t";
1966
+		$pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
1967
+		$post = '</div>' . "\n";
1968
+		$cache_key = 'ee_rss_' . md5($rss_id);
1969
+		if (false != ($output = get_transient($cache_key))) {
1970
+			echo $pre . $output . $post;
1971
+			return true;
1972
+		}
1973
+		if ( ! $doing_ajax) {
1974
+			echo $pre . $loading . $post;
1975
+			return false;
1976
+		}
1977
+		ob_start();
1978
+		wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
1979
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
1980
+		return true;
1981
+	}
1982
+
1983
+
1984
+
1985
+	public function espresso_news_post_box()
1986
+	{
1987
+		?>
1988 1988
         <div class="padding">
1989 1989
             <div id="espresso_news_post_box_content" class="infolinks">
1990 1990
                 <?php
1991
-                // Get RSS Feed(s)
1992
-                $feed_url = apply_filters('FHEE__EE_Admin_Page__espresso_news_post_box__feed_url', 'http://eventespresso.com/feed/');
1993
-                $url = urlencode($feed_url);
1994
-                self::cached_rss_display('espresso_news_post_box_content', $url);
1995
-                ?>
1991
+				// Get RSS Feed(s)
1992
+				$feed_url = apply_filters('FHEE__EE_Admin_Page__espresso_news_post_box__feed_url', 'http://eventespresso.com/feed/');
1993
+				$url = urlencode($feed_url);
1994
+				self::cached_rss_display('espresso_news_post_box_content', $url);
1995
+				?>
1996 1996
             </div>
1997 1997
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
1998 1998
         </div>
1999 1999
         <?php
2000
-    }
2001
-
2002
-
2003
-
2004
-    private function _espresso_links_post_box()
2005
-    {
2006
-        //Hiding until we actually have content to put in here...
2007
-        //add_meta_box('espresso_links_post_box', __('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2008
-    }
2009
-
2010
-
2011
-
2012
-    public function espresso_links_post_box()
2013
-    {
2014
-        //Hiding until we actually have content to put in here...
2015
-        //$templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php';
2016
-        //EEH_Template::display_template( $templatepath );
2017
-    }
2018
-
2019
-
2020
-
2021
-    protected function _espresso_sponsors_post_box()
2022
-    {
2023
-        $show_sponsors = apply_filters('FHEE_show_sponsors_meta_box', true);
2024
-        if ($show_sponsors) {
2025
-            add_meta_box('espresso_sponsors_post_box', __('Event Espresso Highlights', 'event_espresso'), array($this, 'espresso_sponsors_post_box'), $this->_wp_page_slug, 'side');
2026
-        }
2027
-    }
2028
-
2029
-
2030
-
2031
-    public function espresso_sponsors_post_box()
2032
-    {
2033
-        $templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php';
2034
-        EEH_Template::display_template($templatepath);
2035
-    }
2036
-
2037
-
2038
-
2039
-    private function _publish_post_box()
2040
-    {
2041
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2042
-        //if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array then we'll use that for the metabox label.  Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2043
-        if ( ! empty($this->_labels['publishbox'])) {
2044
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action] : $this->_labels['publishbox'];
2045
-        } else {
2046
-            $box_label = __('Publish', 'event_espresso');
2047
-        }
2048
-        $box_label = apply_filters('FHEE__EE_Admin_Page___publish_post_box__box_label', $box_label, $this->_req_action, $this);
2049
-        add_meta_box($meta_box_ref, $box_label, array($this, 'editor_overview'), $this->_current_screen->id, 'side', 'high');
2050
-    }
2051
-
2052
-
2053
-
2054
-    public function editor_overview()
2055
-    {
2056
-        //if we have extra content set let's add it in if not make sure its empty
2057
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2058
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php';
2059
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2060
-    }
2061
-
2062
-
2063
-    /** end of globally available metaboxes section **/
2064
-    /*************************************************/
2065
-    /**
2066
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2067
-     * protected method.
2068
-     *
2069
-     * @see   $this->_set_publish_post_box_vars for param details
2070
-     * @since 4.6.0
2071
-     */
2072
-    public function set_publish_post_box_vars($name = null, $id = false, $delete = false, $save_close_redirect_URL = null, $both_btns = true)
2073
-    {
2074
-        $this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2075
-    }
2076
-
2077
-
2078
-
2079
-    /**
2080
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2081
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2082
-     * save, and save and close buttons to work properly, then you will want to include a
2083
-     * values for the name and id arguments.
2084
-     *
2085
-     * @todo  Add in validation for name/id arguments.
2086
-     * @param    string  $name                    key used for the action ID (i.e. event_id)
2087
-     * @param    int     $id                      id attached to the item published
2088
-     * @param    string  $delete                  page route callback for the delete action
2089
-     * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2090
-     * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just the Save button
2091
-     * @throws \EE_Error
2092
-     */
2093
-    protected function _set_publish_post_box_vars(
2094
-            $name = '',
2095
-            $id = 0,
2096
-            $delete = '',
2097
-            $save_close_redirect_URL = '',
2098
-            $both_btns = true
2099
-    ) {
2100
-        // if Save & Close, use a custom redirect URL or default to the main page?
2101
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL) ? $save_close_redirect_URL : $this->_admin_base_url;
2102
-        // create the Save & Close and Save buttons
2103
-        $this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2104
-        //if we have extra content set let's add it in if not make sure its empty
2105
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2106
-        if ($delete && ! empty($id)) {
2107
-            //make sure we have a default if just true is sent.
2108
-            $delete = ! empty($delete) ? $delete : 'delete';
2109
-            $delete_link_args = array($name => $id);
2110
-            $delete = $this->get_action_link_or_button(
2111
-                    $delete,
2112
-                    $delete,
2113
-                    $delete_link_args,
2114
-                    'submitdelete deletion',
2115
-                    '',
2116
-                    false
2117
-            );
2118
-        }
2119
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2120
-        if ( ! empty($name) && ! empty($id)) {
2121
-            $hidden_field_arr[$name] = array(
2122
-                    'type'  => 'hidden',
2123
-                    'value' => $id,
2124
-            );
2125
-            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2126
-        } else {
2127
-            $hf = '';
2128
-        }
2129
-        // add hidden field
2130
-        $this->_template_args['publish_hidden_fields'] = ! empty($hf) ? $hf[$name]['field'] : $hf;
2131
-    }
2132
-
2133
-
2134
-
2135
-    /**
2136
-     *        displays an error message to ppl who have javascript disabled
2137
-     *
2138
-     * @access        private
2139
-     * @return        string
2140
-     */
2141
-    private function _display_no_javascript_warning()
2142
-    {
2143
-        ?>
2000
+	}
2001
+
2002
+
2003
+
2004
+	private function _espresso_links_post_box()
2005
+	{
2006
+		//Hiding until we actually have content to put in here...
2007
+		//add_meta_box('espresso_links_post_box', __('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2008
+	}
2009
+
2010
+
2011
+
2012
+	public function espresso_links_post_box()
2013
+	{
2014
+		//Hiding until we actually have content to put in here...
2015
+		//$templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php';
2016
+		//EEH_Template::display_template( $templatepath );
2017
+	}
2018
+
2019
+
2020
+
2021
+	protected function _espresso_sponsors_post_box()
2022
+	{
2023
+		$show_sponsors = apply_filters('FHEE_show_sponsors_meta_box', true);
2024
+		if ($show_sponsors) {
2025
+			add_meta_box('espresso_sponsors_post_box', __('Event Espresso Highlights', 'event_espresso'), array($this, 'espresso_sponsors_post_box'), $this->_wp_page_slug, 'side');
2026
+		}
2027
+	}
2028
+
2029
+
2030
+
2031
+	public function espresso_sponsors_post_box()
2032
+	{
2033
+		$templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php';
2034
+		EEH_Template::display_template($templatepath);
2035
+	}
2036
+
2037
+
2038
+
2039
+	private function _publish_post_box()
2040
+	{
2041
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2042
+		//if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array then we'll use that for the metabox label.  Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2043
+		if ( ! empty($this->_labels['publishbox'])) {
2044
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action] : $this->_labels['publishbox'];
2045
+		} else {
2046
+			$box_label = __('Publish', 'event_espresso');
2047
+		}
2048
+		$box_label = apply_filters('FHEE__EE_Admin_Page___publish_post_box__box_label', $box_label, $this->_req_action, $this);
2049
+		add_meta_box($meta_box_ref, $box_label, array($this, 'editor_overview'), $this->_current_screen->id, 'side', 'high');
2050
+	}
2051
+
2052
+
2053
+
2054
+	public function editor_overview()
2055
+	{
2056
+		//if we have extra content set let's add it in if not make sure its empty
2057
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2058
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php';
2059
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2060
+	}
2061
+
2062
+
2063
+	/** end of globally available metaboxes section **/
2064
+	/*************************************************/
2065
+	/**
2066
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2067
+	 * protected method.
2068
+	 *
2069
+	 * @see   $this->_set_publish_post_box_vars for param details
2070
+	 * @since 4.6.0
2071
+	 */
2072
+	public function set_publish_post_box_vars($name = null, $id = false, $delete = false, $save_close_redirect_URL = null, $both_btns = true)
2073
+	{
2074
+		$this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2075
+	}
2076
+
2077
+
2078
+
2079
+	/**
2080
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2081
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2082
+	 * save, and save and close buttons to work properly, then you will want to include a
2083
+	 * values for the name and id arguments.
2084
+	 *
2085
+	 * @todo  Add in validation for name/id arguments.
2086
+	 * @param    string  $name                    key used for the action ID (i.e. event_id)
2087
+	 * @param    int     $id                      id attached to the item published
2088
+	 * @param    string  $delete                  page route callback for the delete action
2089
+	 * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2090
+	 * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just the Save button
2091
+	 * @throws \EE_Error
2092
+	 */
2093
+	protected function _set_publish_post_box_vars(
2094
+			$name = '',
2095
+			$id = 0,
2096
+			$delete = '',
2097
+			$save_close_redirect_URL = '',
2098
+			$both_btns = true
2099
+	) {
2100
+		// if Save & Close, use a custom redirect URL or default to the main page?
2101
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL) ? $save_close_redirect_URL : $this->_admin_base_url;
2102
+		// create the Save & Close and Save buttons
2103
+		$this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2104
+		//if we have extra content set let's add it in if not make sure its empty
2105
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2106
+		if ($delete && ! empty($id)) {
2107
+			//make sure we have a default if just true is sent.
2108
+			$delete = ! empty($delete) ? $delete : 'delete';
2109
+			$delete_link_args = array($name => $id);
2110
+			$delete = $this->get_action_link_or_button(
2111
+					$delete,
2112
+					$delete,
2113
+					$delete_link_args,
2114
+					'submitdelete deletion',
2115
+					'',
2116
+					false
2117
+			);
2118
+		}
2119
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2120
+		if ( ! empty($name) && ! empty($id)) {
2121
+			$hidden_field_arr[$name] = array(
2122
+					'type'  => 'hidden',
2123
+					'value' => $id,
2124
+			);
2125
+			$hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2126
+		} else {
2127
+			$hf = '';
2128
+		}
2129
+		// add hidden field
2130
+		$this->_template_args['publish_hidden_fields'] = ! empty($hf) ? $hf[$name]['field'] : $hf;
2131
+	}
2132
+
2133
+
2134
+
2135
+	/**
2136
+	 *        displays an error message to ppl who have javascript disabled
2137
+	 *
2138
+	 * @access        private
2139
+	 * @return        string
2140
+	 */
2141
+	private function _display_no_javascript_warning()
2142
+	{
2143
+		?>
2144 2144
         <noscript>
2145 2145
             <div id="no-js-message" class="error">
2146 2146
                 <p style="font-size:1.3em;">
@@ -2150,1231 +2150,1231 @@  discard block
 block discarded – undo
2150 2150
             </div>
2151 2151
         </noscript>
2152 2152
         <?php
2153
-    }
2153
+	}
2154 2154
 
2155 2155
 
2156 2156
 
2157
-    /**
2158
-     *        displays espresso success and/or error notices
2159
-     *
2160
-     * @access        private
2161
-     * @return        string
2162
-     */
2163
-    private function _display_espresso_notices()
2164
-    {
2165
-        $notices = $this->_get_transient(true);
2166
-        echo stripslashes($notices);
2167
-    }
2157
+	/**
2158
+	 *        displays espresso success and/or error notices
2159
+	 *
2160
+	 * @access        private
2161
+	 * @return        string
2162
+	 */
2163
+	private function _display_espresso_notices()
2164
+	{
2165
+		$notices = $this->_get_transient(true);
2166
+		echo stripslashes($notices);
2167
+	}
2168 2168
 
2169 2169
 
2170 2170
 
2171
-    /**
2172
-     *        spinny things pacify the masses
2173
-     *
2174
-     * @access private
2175
-     * @return string
2176
-     */
2177
-    protected function _add_admin_page_ajax_loading_img()
2178
-    {
2179
-        ?>
2171
+	/**
2172
+	 *        spinny things pacify the masses
2173
+	 *
2174
+	 * @access private
2175
+	 * @return string
2176
+	 */
2177
+	protected function _add_admin_page_ajax_loading_img()
2178
+	{
2179
+		?>
2180 2180
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2181 2181
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php _e('loading...', 'event_espresso'); ?></span>
2182 2182
         </div>
2183 2183
         <?php
2184
-    }
2184
+	}
2185 2185
 
2186 2186
 
2187 2187
 
2188
-    /**
2189
-     *        add admin page overlay for modal boxes
2190
-     *
2191
-     * @access private
2192
-     * @return string
2193
-     */
2194
-    protected function _add_admin_page_overlay()
2195
-    {
2196
-        ?>
2188
+	/**
2189
+	 *        add admin page overlay for modal boxes
2190
+	 *
2191
+	 * @access private
2192
+	 * @return string
2193
+	 */
2194
+	protected function _add_admin_page_overlay()
2195
+	{
2196
+		?>
2197 2197
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2198 2198
         <?php
2199
-    }
2200
-
2201
-
2202
-
2203
-    /**
2204
-     * facade for add_meta_box
2205
-     *
2206
-     * @param string  $action        where the metabox get's displayed
2207
-     * @param string  $title         Title of Metabox (output in metabox header)
2208
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback instead of the one created in here.
2209
-     * @param array   $callback_args an array of args supplied for the metabox
2210
-     * @param string  $column        what metabox column
2211
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2212
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function created but just set our own callback for wp's add_meta_box.
2213
-     */
2214
-    public function _add_admin_page_meta_box($action, $title, $callback, $callback_args, $column = 'normal', $priority = 'high', $create_func = true)
2215
-    {
2216
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2217
-        //if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2218
-        if (empty($callback_args) && $create_func) {
2219
-            $callback_args = array(
2220
-                    'template_path' => $this->_template_path,
2221
-                    'template_args' => $this->_template_args,
2222
-            );
2223
-        }
2224
-        //if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2225
-        $call_back_func = $create_func ? create_function('$post, $metabox',
2226
-                'do_action( "AHEE_log", __FILE__, __FUNCTION__, ""); echo EEH_Template::display_template( $metabox["args"]["template_path"], $metabox["args"]["template_args"], TRUE );') : $callback;
2227
-        add_meta_box(str_replace('_', '-', $action) . '-mbox', $title, $call_back_func, $this->_wp_page_slug, $column, $priority, $callback_args);
2228
-    }
2229
-
2230
-
2231
-
2232
-    /**
2233
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2234
-     *
2235
-     * @return [type] [description]
2236
-     */
2237
-    public function display_admin_page_with_metabox_columns()
2238
-    {
2239
-        $this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2240
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_column_template_path, $this->_template_args, true);
2241
-        //the final wrapper
2242
-        $this->admin_page_wrapper();
2243
-    }
2244
-
2245
-
2246
-
2247
-    /**
2248
-     *        generates  HTML wrapper for an admin details page
2249
-     *
2250
-     * @access public
2251
-     * @return void
2252
-     */
2253
-    public function display_admin_page_with_sidebar()
2254
-    {
2255
-        $this->_display_admin_page(true);
2256
-    }
2257
-
2258
-
2259
-
2260
-    /**
2261
-     *        generates  HTML wrapper for an admin details page (except no sidebar)
2262
-     *
2263
-     * @access public
2264
-     * @return void
2265
-     */
2266
-    public function display_admin_page_with_no_sidebar()
2267
-    {
2268
-        $this->_display_admin_page();
2269
-    }
2270
-
2271
-
2272
-
2273
-    /**
2274
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2275
-     *
2276
-     * @access public
2277
-     * @return void
2278
-     */
2279
-    public function display_about_admin_page()
2280
-    {
2281
-        $this->_display_admin_page(false, true);
2282
-    }
2283
-
2284
-
2285
-
2286
-    /**
2287
-     * display_admin_page
2288
-     * contains the code for actually displaying an admin page
2289
-     *
2290
-     * @access private
2291
-     * @param  boolean $sidebar true with sidebar, false without
2292
-     * @param  boolean $about   use the about admin wrapper instead of the default.
2293
-     * @return void
2294
-     */
2295
-    private function _display_admin_page($sidebar = false, $about = false)
2296
-    {
2297
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2298
-        //custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2299
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2300
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2301
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2302
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2303
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2304
-                ? 'poststuff'
2305
-                : 'espresso-default-admin';
2306
-        $template_path = $sidebar
2307
-                ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2308
-                : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2309
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2310
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2311
-        }
2312
-        $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2313
-        $this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '';
2314
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '';
2315
-        $this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '';
2316
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2317
-        // the final template wrapper
2318
-        $this->admin_page_wrapper($about);
2319
-    }
2320
-
2321
-
2322
-
2323
-    /**
2324
-     * This is used to display caf preview pages.
2325
-     *
2326
-     * @since 4.3.2
2327
-     * @param string $utm_campaign_source what is the key used for google analytics link
2328
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2329
-     * @return void
2330
-     * @throws \EE_Error
2331
-     */
2332
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2333
-    {
2334
-        //let's generate a default preview action button if there isn't one already present.
2335
-        $this->_labels['buttons']['buy_now'] = __('Upgrade to Event Espresso 4 Right Now', 'event_espresso');
2336
-        $buy_now_url = add_query_arg(
2337
-                array(
2338
-                        'ee_ver'       => 'ee4',
2339
-                        'utm_source'   => 'ee4_plugin_admin',
2340
-                        'utm_medium'   => 'link',
2341
-                        'utm_campaign' => $utm_campaign_source,
2342
-                        'utm_content'  => 'buy_now_button',
2343
-                ),
2344
-                'https://eventespresso.com/pricing/'
2345
-        );
2346
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2347
-                ? $this->get_action_link_or_button(
2348
-                        '',
2349
-                        'buy_now',
2350
-                        array(),
2351
-                        'button-primary button-large',
2352
-                        $buy_now_url,
2353
-                        true
2354
-                )
2355
-                : $this->_template_args['preview_action_button'];
2356
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php';
2357
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2358
-                $template_path,
2359
-                $this->_template_args,
2360
-                true
2361
-        );
2362
-        $this->_display_admin_page($display_sidebar);
2363
-    }
2364
-
2365
-
2366
-
2367
-    /**
2368
-     * display_admin_list_table_page_with_sidebar
2369
-     * generates HTML wrapper for an admin_page with list_table
2370
-     *
2371
-     * @access public
2372
-     * @return void
2373
-     */
2374
-    public function display_admin_list_table_page_with_sidebar()
2375
-    {
2376
-        $this->_display_admin_list_table_page(true);
2377
-    }
2378
-
2379
-
2380
-
2381
-    /**
2382
-     * display_admin_list_table_page_with_no_sidebar
2383
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2384
-     *
2385
-     * @access public
2386
-     * @return void
2387
-     */
2388
-    public function display_admin_list_table_page_with_no_sidebar()
2389
-    {
2390
-        $this->_display_admin_list_table_page();
2391
-    }
2392
-
2393
-
2394
-
2395
-    /**
2396
-     * generates html wrapper for an admin_list_table page
2397
-     *
2398
-     * @access private
2399
-     * @param boolean $sidebar whether to display with sidebar or not.
2400
-     * @return void
2401
-     */
2402
-    private function _display_admin_list_table_page($sidebar = false)
2403
-    {
2404
-        //setup search attributes
2405
-        $this->_set_search_attributes();
2406
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2407
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2408
-        $this->_template_args['table_url'] = defined('DOING_AJAX')
2409
-                ? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2410
-                : add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2411
-        $this->_template_args['list_table'] = $this->_list_table_object;
2412
-        $this->_template_args['current_route'] = $this->_req_action;
2413
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2414
-        $ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2415
-        if ( ! empty($ajax_sorting_callback)) {
2416
-            $sortable_list_table_form_fields = wp_nonce_field(
2417
-                    $ajax_sorting_callback . '_nonce',
2418
-                    $ajax_sorting_callback . '_nonce',
2419
-                    false,
2420
-                    false
2421
-            );
2422
-            //			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
2423
-            //			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
2424
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="' . $this->page_slug . '" />';
2425
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="' . $ajax_sorting_callback . '" />';
2426
-        } else {
2427
-            $sortable_list_table_form_fields = '';
2428
-        }
2429
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2430
-        $hidden_form_fields = isset($this->_template_args['list_table_hidden_fields']) ? $this->_template_args['list_table_hidden_fields'] : '';
2431
-        $nonce_ref = $this->_req_action . '_nonce';
2432
-        $hidden_form_fields .= '<input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2433
-        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2434
-        //display message about search results?
2435
-        $this->_template_args['before_list_table'] .= apply_filters(
2436
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2437
-                ! empty($this->_req_data['s'])
2438
-                        ? '<p class="ee-search-results">' . sprintf(
2439
-                                __('Displaying search results for the search string: <strong><em>%s</em></strong>', 'event_espresso'),
2440
-                                trim($this->_req_data['s'], '%')
2441
-                        ) . '</p>'
2442
-                        : '',
2443
-                $this->page_slug,
2444
-                $this->_req_data,
2445
-                $this->_req_action
2446
-        );
2447
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2448
-                $template_path,
2449
-                $this->_template_args,
2450
-                true
2451
-        );
2452
-        // the final template wrapper
2453
-        if ($sidebar) {
2454
-            $this->display_admin_page_with_sidebar();
2455
-        } else {
2456
-            $this->display_admin_page_with_no_sidebar();
2457
-        }
2458
-    }
2459
-
2460
-
2461
-
2462
-    /**
2463
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the html string for the legend.
2464
-     * $items are expected in an array in the following format:
2465
-     * $legend_items = array(
2466
-     *        'item_id' => array(
2467
-     *            'icon' => 'http://url_to_icon_being_described.png',
2468
-     *            'desc' => __('localized description of item');
2469
-     *        )
2470
-     * );
2471
-     *
2472
-     * @param  array $items see above for format of array
2473
-     * @return string        html string of legend
2474
-     */
2475
-    protected function _display_legend($items)
2476
-    {
2477
-        $this->_template_args['items'] = apply_filters('FHEE__EE_Admin_Page___display_legend__items', (array)$items, $this);
2478
-        $legend_template = EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php';
2479
-        return EEH_Template::display_template($legend_template, $this->_template_args, true);
2480
-    }
2481
-
2482
-
2483
-
2484
-    /**
2485
-     * this is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
2486
-     *
2487
-     * @param bool $sticky_notices Used to indicate whether you want to ensure notices are added to a transient instead of displayed.
2488
-     *                             The returned json object is created from an array in the following format:
2489
-     *                             array(
2490
-     *                             'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
2491
-     *                             'success' => FALSE, //(default FALSE) - contains any special success message.
2492
-     *                             'notices' => '', // - contains any EE_Error formatted notices
2493
-     *                             'content' => 'string can be html', //this is a string of formatted content (can be html)
2494
-     *                             'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js. We're also going to include the template args with every package (so js can pick out any
2495
-     *                             specific template args that might be included in here)
2496
-     *                             )
2497
-     *                             The json object is populated by whatever is set in the $_template_args property.
2498
-     * @return void
2499
-     */
2500
-    protected function _return_json($sticky_notices = false)
2501
-    {
2502
-        //make sure any EE_Error notices have been handled.
2503
-        $this->_process_notices(array(), true, $sticky_notices);
2504
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
2505
-        unset($this->_template_args['data']);
2506
-        $json = array(
2507
-                'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
2508
-                'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
2509
-                'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
2510
-                'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
2511
-                'notices'   => EE_Error::get_notices(),
2512
-                'content'   => isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '',
2513
-                'data'      => array_merge($data, array('template_args' => $this->_template_args)),
2514
-                'isEEajax'  => true //special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
2515
-        );
2516
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
2517
-        if (null === error_get_last() || ! headers_sent()) {
2518
-            header('Content-Type: application/json; charset=UTF-8');
2519
-        }
2520
-        echo wp_json_encode($json);
2521
-
2522
-        exit();
2523
-    }
2524
-
2525
-
2526
-
2527
-    /**
2528
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
2529
-     *
2530
-     * @return void
2531
-     * @throws EE_Error
2532
-     */
2533
-    public function return_json()
2534
-    {
2535
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2536
-            $this->_return_json();
2537
-        } else {
2538
-            throw new EE_Error(sprintf(__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'), __FUNCTION__));
2539
-        }
2540
-    }
2541
-
2542
-
2543
-
2544
-    /**
2545
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
2546
-     *
2547
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
2548
-     * @access   public
2549
-     */
2550
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
2551
-    {
2552
-        $this->_hook_obj = $hook_obj;
2553
-    }
2554
-
2555
-
2556
-
2557
-    /**
2558
-     *        generates  HTML wrapper with Tabbed nav for an admin page
2559
-     *
2560
-     * @access public
2561
-     * @param  boolean $about whether to use the special about page wrapper or default.
2562
-     * @return void
2563
-     */
2564
-    public function admin_page_wrapper($about = false)
2565
-    {
2566
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2567
-        $this->_nav_tabs = $this->_get_main_nav_tabs();
2568
-        $this->_template_args['nav_tabs'] = $this->_nav_tabs;
2569
-        $this->_template_args['admin_page_title'] = $this->_admin_page_title;
2570
-        $this->_template_args['before_admin_page_content'] = apply_filters('FHEE_before_admin_page_content' . $this->_current_page . $this->_current_view,
2571
-                isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '');
2572
-        $this->_template_args['after_admin_page_content'] = apply_filters('FHEE_after_admin_page_content' . $this->_current_page . $this->_current_view,
2573
-                isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '');
2574
-        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
2575
-        // load settings page wrapper template
2576
-        $template_path = ! defined('DOING_AJAX') ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php' : EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php';
2577
-        //about page?
2578
-        $template_path = $about ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php' : $template_path;
2579
-        if (defined('DOING_AJAX')) {
2580
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2581
-            $this->_return_json();
2582
-        } else {
2583
-            EEH_Template::display_template($template_path, $this->_template_args);
2584
-        }
2585
-    }
2586
-
2587
-
2588
-
2589
-    /**
2590
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
2591
-     *
2592
-     * @return string html
2593
-     */
2594
-    protected function _get_main_nav_tabs()
2595
-    {
2596
-        //let's generate the html using the EEH_Tabbed_Content helper.  We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute (rather than setting in the page_routes array)
2597
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
2598
-    }
2599
-
2600
-
2601
-
2602
-    /**
2603
-     *        sort nav tabs
2604
-     *
2605
-     * @access public
2606
-     * @param $a
2607
-     * @param $b
2608
-     * @return int
2609
-     */
2610
-    private function _sort_nav_tabs($a, $b)
2611
-    {
2612
-        if ($a['order'] == $b['order']) {
2613
-            return 0;
2614
-        }
2615
-        return ($a['order'] < $b['order']) ? -1 : 1;
2616
-    }
2617
-
2618
-
2619
-
2620
-    /**
2621
-     *    generates HTML for the forms used on admin pages
2622
-     *
2623
-     * @access protected
2624
-     * @param    array $input_vars - array of input field details
2625
-     * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to use)
2626
-     * @return string
2627
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
2628
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
2629
-     */
2630
-    protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
2631
-    {
2632
-        $content = $generator == 'string' ? EEH_Form_Fields::get_form_fields($input_vars, $id) : EEH_Form_Fields::get_form_fields_array($input_vars);
2633
-        return $content;
2634
-    }
2635
-
2636
-
2637
-
2638
-    /**
2639
-     * generates the "Save" and "Save & Close" buttons for edit forms
2640
-     *
2641
-     * @access protected
2642
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save & Close" button.
2643
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] => 'Save', [1] => 'save & close')
2644
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e. via the "name" value in the button).  We can also use this to just dump default actions by submitting some other value.
2645
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it will use the $referrer string. IF null, then we don't do ANYTHING on save and close (normal form handling).
2646
-     */
2647
-    protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
2648
-    {
2649
-        //make sure $text and $actions are in an array
2650
-        $text = (array)$text;
2651
-        $actions = (array)$actions;
2652
-        $referrer_url = empty($referrer) ? '' : $referrer;
2653
-        $referrer_url = ! $referrer ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $_SERVER['REQUEST_URI'] . '" />'
2654
-                : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $referrer . '" />';
2655
-        $button_text = ! empty($text) ? $text : array(__('Save', 'event_espresso'), __('Save and Close', 'event_espresso'));
2656
-        $default_names = array('save', 'save_and_close');
2657
-        //add in a hidden index for the current page (so save and close redirects properly)
2658
-        $this->_template_args['save_buttons'] = $referrer_url;
2659
-        foreach ($button_text as $key => $button) {
2660
-            $ref = $default_names[$key];
2661
-            $id = $this->_current_view . '_' . $ref;
2662
-            $name = ! empty($actions) ? $actions[$key] : $ref;
2663
-            $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary ' . $ref . '" value="' . $button . '" name="' . $name . '" id="' . $id . '" />';
2664
-            if ( ! $both) {
2665
-                break;
2666
-            }
2667
-        }
2668
-    }
2669
-
2670
-
2671
-
2672
-    /**
2673
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
2674
-     *
2675
-     * @see   $this->_set_add_edit_form_tags() for details on params
2676
-     * @since 4.6.0
2677
-     * @param string $route
2678
-     * @param array  $additional_hidden_fields
2679
-     */
2680
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2681
-    {
2682
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
2683
-    }
2684
-
2685
-
2686
-
2687
-    /**
2688
-     * set form open and close tags on add/edit pages.
2689
-     *
2690
-     * @access protected
2691
-     * @param string $route                    the route you want the form to direct to
2692
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
2693
-     * @return void
2694
-     */
2695
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2696
-    {
2697
-        if (empty($route)) {
2698
-            $user_msg = __('An error occurred. No action was set for this page\'s form.', 'event_espresso');
2699
-            $dev_msg = $user_msg . "\n" . sprintf(__('The $route argument is required for the %s->%s method.', 'event_espresso'), __FUNCTION__, __CLASS__);
2700
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
2701
-        }
2702
-        // open form
2703
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="' . $this->_admin_base_url . '" id="' . $route . '_event_form" >';
2704
-        // add nonce
2705
-        $nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
2706
-        //		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
2707
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
2708
-        // add REQUIRED form action
2709
-        $hidden_fields = array(
2710
-                'action' => array('type' => 'hidden', 'value' => $route),
2711
-        );
2712
-        // merge arrays
2713
-        $hidden_fields = is_array($additional_hidden_fields) ? array_merge($hidden_fields, $additional_hidden_fields) : $hidden_fields;
2714
-        // generate form fields
2715
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
2716
-        // add fields to form
2717
-        foreach ((array)$form_fields as $field_name => $form_field) {
2718
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
2719
-        }
2720
-        // close form
2721
-        $this->_template_args['after_admin_page_content'] = '</form>';
2722
-    }
2723
-
2724
-
2725
-
2726
-    /**
2727
-     * Public Wrapper for _redirect_after_action() method since its
2728
-     * discovered it would be useful for external code to have access.
2729
-     *
2730
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
2731
-     * @since 4.5.0
2732
-     */
2733
-    public function redirect_after_action($success = false, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2734
-    {
2735
-        $this->_redirect_after_action($success, $what, $action_desc, $query_args, $override_overwrite);
2736
-    }
2737
-
2738
-
2739
-
2740
-    /**
2741
-     *    _redirect_after_action
2742
-     *
2743
-     * @param int    $success            - whether success was for two or more records, or just one, or none
2744
-     * @param string $what               - what the action was performed on
2745
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
2746
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin action is completed
2747
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to override this so that they show.
2748
-     * @access protected
2749
-     * @return void
2750
-     */
2751
-    protected function _redirect_after_action($success = 0, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2752
-    {
2753
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2754
-        //class name for actions/filters.
2755
-        $classname = get_class($this);
2756
-        //set redirect url. Note if there is a "page" index in the $query_args then we go with vanilla admin.php route, otherwise we go with whatever is set as the _admin_base_url
2757
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
2758
-        $notices = EE_Error::get_notices(false);
2759
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
2760
-        if ( ! $override_overwrite || ! empty($notices['errors'])) {
2761
-            EE_Error::overwrite_success();
2762
-        }
2763
-        if ( ! empty($what) && ! empty($action_desc)) {
2764
-            // how many records affected ? more than one record ? or just one ?
2765
-            if ($success > 1 && empty($notices['errors'])) {
2766
-                // set plural msg
2767
-                EE_Error::add_success(
2768
-                        sprintf(
2769
-                                __('The "%s" have been successfully %s.', 'event_espresso'),
2770
-                                $what,
2771
-                                $action_desc
2772
-                        ),
2773
-                        __FILE__, __FUNCTION__, __LINE__
2774
-                );
2775
-            } else if ($success == 1 && empty($notices['errors'])) {
2776
-                // set singular msg
2777
-                EE_Error::add_success(
2778
-                        sprintf(
2779
-                                __('The "%s" has been successfully %s.', 'event_espresso'),
2780
-                                $what,
2781
-                                $action_desc
2782
-                        ),
2783
-                        __FILE__, __FUNCTION__, __LINE__
2784
-                );
2785
-            }
2786
-        }
2787
-        // check that $query_args isn't something crazy
2788
-        if ( ! is_array($query_args)) {
2789
-            $query_args = array();
2790
-        }
2791
-        /**
2792
-         * Allow injecting actions before the query_args are modified for possible different
2793
-         * redirections on save and close actions
2794
-         *
2795
-         * @since 4.2.0
2796
-         * @param array $query_args       The original query_args array coming into the
2797
-         *                                method.
2798
-         */
2799
-        do_action('AHEE__' . $classname . '___redirect_after_action__before_redirect_modification_' . $this->_req_action, $query_args);
2800
-        //calculate where we're going (if we have a "save and close" button pushed)
2801
-        if (isset($this->_req_data['save_and_close']) && isset($this->_req_data['save_and_close_referrer'])) {
2802
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
2803
-            $parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
2804
-            // regenerate query args array from referrer URL
2805
-            parse_str($parsed_url['query'], $query_args);
2806
-            // correct page and action will be in the query args now
2807
-            $redirect_url = admin_url('admin.php');
2808
-        }
2809
-        //merge any default query_args set in _default_route_query_args property
2810
-        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
2811
-            $args_to_merge = array();
2812
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
2813
-                //is there a wp_referer array in our _default_route_query_args property?
2814
-                if ($query_param == 'wp_referer') {
2815
-                    $query_value = (array)$query_value;
2816
-                    foreach ($query_value as $reference => $value) {
2817
-                        if (strpos($reference, 'nonce') !== false) {
2818
-                            continue;
2819
-                        }
2820
-                        //finally we will override any arguments in the referer with
2821
-                        //what might be set on the _default_route_query_args array.
2822
-                        if (isset($this->_default_route_query_args[$reference])) {
2823
-                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
2824
-                        } else {
2825
-                            $args_to_merge[$reference] = urlencode($value);
2826
-                        }
2827
-                    }
2828
-                    continue;
2829
-                }
2830
-                $args_to_merge[$query_param] = $query_value;
2831
-            }
2832
-            //now let's merge these arguments but override with what was specifically sent in to the
2833
-            //redirect.
2834
-            $query_args = array_merge($args_to_merge, $query_args);
2835
-        }
2836
-        $this->_process_notices($query_args);
2837
-        // generate redirect url
2838
-        // if redirecting to anything other than the main page, add a nonce
2839
-        if (isset($query_args['action'])) {
2840
-            // manually generate wp_nonce and merge that with the query vars becuz the wp_nonce_url function wrecks havoc on some vars
2841
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2842
-        }
2843
-        //we're adding some hooks and filters in here for processing any things just before redirects (example: an admin page has done an insert or update and we want to run something after that).
2844
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
2845
-        $redirect_url = apply_filters('FHEE_redirect_' . $classname . $this->_req_action, self::add_query_args_and_nonce($query_args, $redirect_url), $query_args);
2846
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
2847
-        if (defined('DOING_AJAX')) {
2848
-            $default_data = array(
2849
-                    'close'        => true,
2850
-                    'redirect_url' => $redirect_url,
2851
-                    'where'        => 'main',
2852
-                    'what'         => 'append',
2853
-            );
2854
-            $this->_template_args['success'] = $success;
2855
-            $this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge($default_data, $this->_template_args['data']) : $default_data;
2856
-            $this->_return_json();
2857
-        }
2858
-        wp_safe_redirect($redirect_url);
2859
-        exit();
2860
-    }
2861
-
2862
-
2863
-
2864
-    /**
2865
-     * process any notices before redirecting (or returning ajax request)
2866
-     * This method sets the $this->_template_args['notices'] attribute;
2867
-     *
2868
-     * @param  array $query_args        any query args that need to be used for notice transient ('action')
2869
-     * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and page_routes haven't been defined yet.
2870
-     * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we still save a transient for the notice.
2871
-     * @return void
2872
-     */
2873
-    protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
2874
-    {
2875
-        //first let's set individual error properties if doing_ajax and the properties aren't already set.
2876
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2877
-            $notices = EE_Error::get_notices(false);
2878
-            if (empty($this->_template_args['success'])) {
2879
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
2880
-            }
2881
-            if (empty($this->_template_args['errors'])) {
2882
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
2883
-            }
2884
-            if (empty($this->_template_args['attention'])) {
2885
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
2886
-            }
2887
-        }
2888
-        $this->_template_args['notices'] = EE_Error::get_notices();
2889
-        //IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
2890
-        if ( ! defined('DOING_AJAX') || $sticky_notices) {
2891
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
2892
-            $this->_add_transient($route, $this->_template_args['notices'], true, $skip_route_verify);
2893
-        }
2894
-    }
2895
-
2896
-
2897
-
2898
-    /**
2899
-     * get_action_link_or_button
2900
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
2901
-     *
2902
-     * @param string $action        use this to indicate which action the url is generated with.
2903
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key) property.
2904
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
2905
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
2906
-     * @param string $base_url      If this is not provided
2907
-     *                              the _admin_base_url will be used as the default for the button base_url.
2908
-     *                              Otherwise this value will be used.
2909
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
2910
-     * @return string
2911
-     * @throws \EE_Error
2912
-     */
2913
-    public function get_action_link_or_button(
2914
-            $action,
2915
-            $type = 'add',
2916
-            $extra_request = array(),
2917
-            $class = 'button-primary',
2918
-            $base_url = '',
2919
-            $exclude_nonce = false
2920
-    ) {
2921
-        //first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
2922
-        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
2923
-            throw new EE_Error(
2924
-                    sprintf(
2925
-                            __(
2926
-                                    'There is no page route for given action for the button.  This action was given: %s',
2927
-                                    'event_espresso'
2928
-                            ),
2929
-                            $action
2930
-                    )
2931
-            );
2932
-        }
2933
-        if ( ! isset($this->_labels['buttons'][$type])) {
2934
-            throw new EE_Error(
2935
-                    sprintf(
2936
-                            __(
2937
-                                    'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
2938
-                                    'event_espresso'
2939
-                            ),
2940
-                            $type
2941
-                    )
2942
-            );
2943
-        }
2944
-        //finally check user access for this button.
2945
-        $has_access = $this->check_user_access($action, true);
2946
-        if ( ! $has_access) {
2947
-            return '';
2948
-        }
2949
-        $_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
2950
-        $query_args = array(
2951
-                'action' => $action,
2952
-        );
2953
-        //merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
2954
-        if ( ! empty($extra_request)) {
2955
-            $query_args = array_merge($extra_request, $query_args);
2956
-        }
2957
-        $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
2958
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
2959
-    }
2960
-
2961
-
2962
-
2963
-    /**
2964
-     * _per_page_screen_option
2965
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
2966
-     *
2967
-     * @return void
2968
-     */
2969
-    protected function _per_page_screen_option()
2970
-    {
2971
-        $option = 'per_page';
2972
-        $args = array(
2973
-                'label'   => $this->_admin_page_title,
2974
-                'default' => 10,
2975
-                'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
2976
-        );
2977
-        //ONLY add the screen option if the user has access to it.
2978
-        if ($this->check_user_access($this->_current_view, true)) {
2979
-            add_screen_option($option, $args);
2980
-        }
2981
-    }
2982
-
2983
-
2984
-
2985
-    /**
2986
-     * set_per_page_screen_option
2987
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
2988
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than admin_menu.
2989
-     *
2990
-     * @access private
2991
-     * @return void
2992
-     */
2993
-    private function _set_per_page_screen_options()
2994
-    {
2995
-        if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
2996
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
2997
-            if ( ! $user = wp_get_current_user()) {
2998
-                return;
2999
-            }
3000
-            $option = $_POST['wp_screen_options']['option'];
3001
-            $value = $_POST['wp_screen_options']['value'];
3002
-            if ($option != sanitize_key($option)) {
3003
-                return;
3004
-            }
3005
-            $map_option = $option;
3006
-            $option = str_replace('-', '_', $option);
3007
-            switch ($map_option) {
3008
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3009
-                    $value = (int)$value;
3010
-                    if ($value < 1 || $value > 999) {
3011
-                        return;
3012
-                    }
3013
-                    break;
3014
-                default:
3015
-                    $value = apply_filters('FHEE__EE_Admin_Page___set_per_page_screen_options__value', false, $option, $value);
3016
-                    if (false === $value) {
3017
-                        return;
3018
-                    }
3019
-                    break;
3020
-            }
3021
-            update_user_meta($user->ID, $option, $value);
3022
-            wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3023
-            exit;
3024
-        }
3025
-    }
3026
-
3027
-
3028
-
3029
-    /**
3030
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3031
-     *
3032
-     * @param array $data array that will be assigned to template args.
3033
-     */
3034
-    public function set_template_args($data)
3035
-    {
3036
-        $this->_template_args = array_merge($this->_template_args, (array)$data);
3037
-    }
3038
-
3039
-
3040
-
3041
-    /**
3042
-     * This makes available the WP transient system for temporarily moving data between routes
3043
-     *
3044
-     * @access protected
3045
-     * @param string $route             the route that should receive the transient
3046
-     * @param array  $data              the data that gets sent
3047
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a normal route transient.
3048
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used when we are adding a transient before page_routes have been defined.
3049
-     * @return void
3050
-     */
3051
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3052
-    {
3053
-        $user_id = get_current_user_id();
3054
-        if ( ! $skip_route_verify) {
3055
-            $this->_verify_route($route);
3056
-        }
3057
-        //now let's set the string for what kind of transient we're setting
3058
-        $transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3059
-        $data = $notices ? array('notices' => $data) : $data;
3060
-        //is there already a transient for this route?  If there is then let's ADD to that transient
3061
-        $existing = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3062
-        if ($existing) {
3063
-            $data = array_merge((array)$data, (array)$existing);
3064
-        }
3065
-        if (is_multisite() && is_network_admin()) {
3066
-            set_site_transient($transient, $data, 8);
3067
-        } else {
3068
-            set_transient($transient, $data, 8);
3069
-        }
3070
-    }
3071
-
3072
-
3073
-
3074
-    /**
3075
-     * this retrieves the temporary transient that has been set for moving data between routes.
3076
-     *
3077
-     * @param bool $notices true we get notices transient. False we just return normal route transient
3078
-     * @return mixed data
3079
-     */
3080
-    protected function _get_transient($notices = false, $route = false)
3081
-    {
3082
-        $user_id = get_current_user_id();
3083
-        $route = ! $route ? $this->_req_action : $route;
3084
-        $transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3085
-        $data = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3086
-        //delete transient after retrieval (just in case it hasn't expired);
3087
-        if (is_multisite() && is_network_admin()) {
3088
-            delete_site_transient($transient);
3089
-        } else {
3090
-            delete_transient($transient);
3091
-        }
3092
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3093
-    }
3094
-
3095
-
3096
-
3097
-    /**
3098
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but would not be called later.
3099
-     * This will be assigned to run on a specific EE Admin page. (place the method in the default route callback on the EE_Admin page you want it run.)
3100
-     *
3101
-     * @return void
3102
-     */
3103
-    protected function _transient_garbage_collection()
3104
-    {
3105
-        global $wpdb;
3106
-        //retrieve all existing transients
3107
-        $query = "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3108
-        if ($results = $wpdb->get_results($query)) {
3109
-            foreach ($results as $result) {
3110
-                $transient = str_replace('_transient_', '', $result->option_name);
3111
-                get_transient($transient);
3112
-                if (is_multisite() && is_network_admin()) {
3113
-                    get_site_transient($transient);
3114
-                }
3115
-            }
3116
-        }
3117
-    }
3118
-
3119
-
3120
-
3121
-    /**
3122
-     * get_view
3123
-     *
3124
-     * @access public
3125
-     * @return string content of _view property
3126
-     */
3127
-    public function get_view()
3128
-    {
3129
-        return $this->_view;
3130
-    }
3131
-
3132
-
3133
-
3134
-    /**
3135
-     * getter for the protected $_views property
3136
-     *
3137
-     * @return array
3138
-     */
3139
-    public function get_views()
3140
-    {
3141
-        return $this->_views;
3142
-    }
3143
-
3144
-
3145
-
3146
-    /**
3147
-     * get_current_page
3148
-     *
3149
-     * @access public
3150
-     * @return string _current_page property value
3151
-     */
3152
-    public function get_current_page()
3153
-    {
3154
-        return $this->_current_page;
3155
-    }
3156
-
3157
-
3158
-
3159
-    /**
3160
-     * get_current_view
3161
-     *
3162
-     * @access public
3163
-     * @return string _current_view property value
3164
-     */
3165
-    public function get_current_view()
3166
-    {
3167
-        return $this->_current_view;
3168
-    }
3169
-
3170
-
3171
-
3172
-    /**
3173
-     * get_current_screen
3174
-     *
3175
-     * @access public
3176
-     * @return object The current WP_Screen object
3177
-     */
3178
-    public function get_current_screen()
3179
-    {
3180
-        return $this->_current_screen;
3181
-    }
3182
-
3183
-
3184
-
3185
-    /**
3186
-     * get_current_page_view_url
3187
-     *
3188
-     * @access public
3189
-     * @return string This returns the url for the current_page_view.
3190
-     */
3191
-    public function get_current_page_view_url()
3192
-    {
3193
-        return $this->_current_page_view_url;
3194
-    }
3195
-
3196
-
3197
-
3198
-    /**
3199
-     * just returns the _req_data property
3200
-     *
3201
-     * @return array
3202
-     */
3203
-    public function get_request_data()
3204
-    {
3205
-        return $this->_req_data;
3206
-    }
3207
-
3208
-
3209
-
3210
-    /**
3211
-     * returns the _req_data protected property
3212
-     *
3213
-     * @return string
3214
-     */
3215
-    public function get_req_action()
3216
-    {
3217
-        return $this->_req_action;
3218
-    }
3219
-
3220
-
3221
-
3222
-    /**
3223
-     * @return bool  value of $_is_caf property
3224
-     */
3225
-    public function is_caf()
3226
-    {
3227
-        return $this->_is_caf;
3228
-    }
3229
-
3230
-
3231
-
3232
-    /**
3233
-     * @return mixed
3234
-     */
3235
-    public function default_espresso_metaboxes()
3236
-    {
3237
-        return $this->_default_espresso_metaboxes;
3238
-    }
3239
-
3240
-
3241
-
3242
-    /**
3243
-     * @return mixed
3244
-     */
3245
-    public function admin_base_url()
3246
-    {
3247
-        return $this->_admin_base_url;
3248
-    }
3249
-
3250
-
3251
-
3252
-    /**
3253
-     * @return mixed
3254
-     */
3255
-    public function wp_page_slug()
3256
-    {
3257
-        return $this->_wp_page_slug;
3258
-    }
3259
-
3260
-
3261
-
3262
-    /**
3263
-     * updates  espresso configuration settings
3264
-     *
3265
-     * @access    protected
3266
-     * @param string                   $tab
3267
-     * @param EE_Config_Base|EE_Config $config
3268
-     * @param string                   $file file where error occurred
3269
-     * @param string                   $func function  where error occurred
3270
-     * @param string                   $line line no where error occurred
3271
-     * @return boolean
3272
-     */
3273
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3274
-    {
3275
-        //remove any options that are NOT going to be saved with the config settings.
3276
-        if (isset($config->core->ee_ueip_optin)) {
3277
-            $config->core->ee_ueip_has_notified = true;
3278
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
3279
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3280
-            update_option('ee_ueip_has_notified', true);
3281
-        }
3282
-        // and save it (note we're also doing the network save here)
3283
-        $net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
3284
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
3285
-        if ($config_saved && $net_saved) {
3286
-            EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3287
-            return true;
3288
-        } else {
3289
-            EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3290
-            return false;
3291
-        }
3292
-    }
3293
-
3294
-
3295
-
3296
-    /**
3297
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
3298
-     *
3299
-     * @return array
3300
-     */
3301
-    public function get_yes_no_values()
3302
-    {
3303
-        return $this->_yes_no_values;
3304
-    }
3305
-
3306
-
3307
-
3308
-    protected function _get_dir()
3309
-    {
3310
-        $reflector = new ReflectionClass(get_class($this));
3311
-        return dirname($reflector->getFileName());
3312
-    }
3313
-
3314
-
3315
-
3316
-    /**
3317
-     * A helper for getting a "next link".
3318
-     *
3319
-     * @param string $url   The url to link to
3320
-     * @param string $class The class to use.
3321
-     * @return string
3322
-     */
3323
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
3324
-    {
3325
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3326
-    }
3327
-
3328
-
3329
-
3330
-    /**
3331
-     * A helper for getting a "previous link".
3332
-     *
3333
-     * @param string $url   The url to link to
3334
-     * @param string $class The class to use.
3335
-     * @return string
3336
-     */
3337
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
3338
-    {
3339
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3340
-    }
3341
-
3342
-
3343
-
3344
-
3345
-
3346
-
3347
-
3348
-    //below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
3349
-    /**
3350
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the _req_data
3351
-     * array.
3352
-     *
3353
-     * @return bool success/fail
3354
-     */
3355
-    protected function _process_resend_registration()
3356
-    {
3357
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
3358
-        do_action('AHEE__EE_Admin_Page___process_resend_registration', $this->_template_args['success'], $this->_req_data);
3359
-        return $this->_template_args['success'];
3360
-    }
3361
-
3362
-
3363
-
3364
-    /**
3365
-     * This automatically processes any payment message notifications when manual payment has been applied.
3366
-     *
3367
-     * @access protected
3368
-     * @param \EE_Payment $payment
3369
-     * @return bool success/fail
3370
-     */
3371
-    protected function _process_payment_notification(EE_Payment $payment)
3372
-    {
3373
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
3374
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
3375
-        $this->_template_args['success'] = apply_filters('FHEE__EE_Admin_Page___process_admin_payment_notification__success', false, $payment);
3376
-        return $this->_template_args['success'];
3377
-    }
2199
+	}
2200
+
2201
+
2202
+
2203
+	/**
2204
+	 * facade for add_meta_box
2205
+	 *
2206
+	 * @param string  $action        where the metabox get's displayed
2207
+	 * @param string  $title         Title of Metabox (output in metabox header)
2208
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback instead of the one created in here.
2209
+	 * @param array   $callback_args an array of args supplied for the metabox
2210
+	 * @param string  $column        what metabox column
2211
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2212
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function created but just set our own callback for wp's add_meta_box.
2213
+	 */
2214
+	public function _add_admin_page_meta_box($action, $title, $callback, $callback_args, $column = 'normal', $priority = 'high', $create_func = true)
2215
+	{
2216
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2217
+		//if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2218
+		if (empty($callback_args) && $create_func) {
2219
+			$callback_args = array(
2220
+					'template_path' => $this->_template_path,
2221
+					'template_args' => $this->_template_args,
2222
+			);
2223
+		}
2224
+		//if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2225
+		$call_back_func = $create_func ? create_function('$post, $metabox',
2226
+				'do_action( "AHEE_log", __FILE__, __FUNCTION__, ""); echo EEH_Template::display_template( $metabox["args"]["template_path"], $metabox["args"]["template_args"], TRUE );') : $callback;
2227
+		add_meta_box(str_replace('_', '-', $action) . '-mbox', $title, $call_back_func, $this->_wp_page_slug, $column, $priority, $callback_args);
2228
+	}
2229
+
2230
+
2231
+
2232
+	/**
2233
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2234
+	 *
2235
+	 * @return [type] [description]
2236
+	 */
2237
+	public function display_admin_page_with_metabox_columns()
2238
+	{
2239
+		$this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2240
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_column_template_path, $this->_template_args, true);
2241
+		//the final wrapper
2242
+		$this->admin_page_wrapper();
2243
+	}
2244
+
2245
+
2246
+
2247
+	/**
2248
+	 *        generates  HTML wrapper for an admin details page
2249
+	 *
2250
+	 * @access public
2251
+	 * @return void
2252
+	 */
2253
+	public function display_admin_page_with_sidebar()
2254
+	{
2255
+		$this->_display_admin_page(true);
2256
+	}
2257
+
2258
+
2259
+
2260
+	/**
2261
+	 *        generates  HTML wrapper for an admin details page (except no sidebar)
2262
+	 *
2263
+	 * @access public
2264
+	 * @return void
2265
+	 */
2266
+	public function display_admin_page_with_no_sidebar()
2267
+	{
2268
+		$this->_display_admin_page();
2269
+	}
2270
+
2271
+
2272
+
2273
+	/**
2274
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2275
+	 *
2276
+	 * @access public
2277
+	 * @return void
2278
+	 */
2279
+	public function display_about_admin_page()
2280
+	{
2281
+		$this->_display_admin_page(false, true);
2282
+	}
2283
+
2284
+
2285
+
2286
+	/**
2287
+	 * display_admin_page
2288
+	 * contains the code for actually displaying an admin page
2289
+	 *
2290
+	 * @access private
2291
+	 * @param  boolean $sidebar true with sidebar, false without
2292
+	 * @param  boolean $about   use the about admin wrapper instead of the default.
2293
+	 * @return void
2294
+	 */
2295
+	private function _display_admin_page($sidebar = false, $about = false)
2296
+	{
2297
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2298
+		//custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2299
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2300
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2301
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2302
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2303
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2304
+				? 'poststuff'
2305
+				: 'espresso-default-admin';
2306
+		$template_path = $sidebar
2307
+				? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2308
+				: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2309
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2310
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2311
+		}
2312
+		$template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2313
+		$this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '';
2314
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '';
2315
+		$this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '';
2316
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2317
+		// the final template wrapper
2318
+		$this->admin_page_wrapper($about);
2319
+	}
2320
+
2321
+
2322
+
2323
+	/**
2324
+	 * This is used to display caf preview pages.
2325
+	 *
2326
+	 * @since 4.3.2
2327
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2328
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2329
+	 * @return void
2330
+	 * @throws \EE_Error
2331
+	 */
2332
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2333
+	{
2334
+		//let's generate a default preview action button if there isn't one already present.
2335
+		$this->_labels['buttons']['buy_now'] = __('Upgrade to Event Espresso 4 Right Now', 'event_espresso');
2336
+		$buy_now_url = add_query_arg(
2337
+				array(
2338
+						'ee_ver'       => 'ee4',
2339
+						'utm_source'   => 'ee4_plugin_admin',
2340
+						'utm_medium'   => 'link',
2341
+						'utm_campaign' => $utm_campaign_source,
2342
+						'utm_content'  => 'buy_now_button',
2343
+				),
2344
+				'https://eventespresso.com/pricing/'
2345
+		);
2346
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2347
+				? $this->get_action_link_or_button(
2348
+						'',
2349
+						'buy_now',
2350
+						array(),
2351
+						'button-primary button-large',
2352
+						$buy_now_url,
2353
+						true
2354
+				)
2355
+				: $this->_template_args['preview_action_button'];
2356
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php';
2357
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2358
+				$template_path,
2359
+				$this->_template_args,
2360
+				true
2361
+		);
2362
+		$this->_display_admin_page($display_sidebar);
2363
+	}
2364
+
2365
+
2366
+
2367
+	/**
2368
+	 * display_admin_list_table_page_with_sidebar
2369
+	 * generates HTML wrapper for an admin_page with list_table
2370
+	 *
2371
+	 * @access public
2372
+	 * @return void
2373
+	 */
2374
+	public function display_admin_list_table_page_with_sidebar()
2375
+	{
2376
+		$this->_display_admin_list_table_page(true);
2377
+	}
2378
+
2379
+
2380
+
2381
+	/**
2382
+	 * display_admin_list_table_page_with_no_sidebar
2383
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2384
+	 *
2385
+	 * @access public
2386
+	 * @return void
2387
+	 */
2388
+	public function display_admin_list_table_page_with_no_sidebar()
2389
+	{
2390
+		$this->_display_admin_list_table_page();
2391
+	}
2392
+
2393
+
2394
+
2395
+	/**
2396
+	 * generates html wrapper for an admin_list_table page
2397
+	 *
2398
+	 * @access private
2399
+	 * @param boolean $sidebar whether to display with sidebar or not.
2400
+	 * @return void
2401
+	 */
2402
+	private function _display_admin_list_table_page($sidebar = false)
2403
+	{
2404
+		//setup search attributes
2405
+		$this->_set_search_attributes();
2406
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2407
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2408
+		$this->_template_args['table_url'] = defined('DOING_AJAX')
2409
+				? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2410
+				: add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2411
+		$this->_template_args['list_table'] = $this->_list_table_object;
2412
+		$this->_template_args['current_route'] = $this->_req_action;
2413
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2414
+		$ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2415
+		if ( ! empty($ajax_sorting_callback)) {
2416
+			$sortable_list_table_form_fields = wp_nonce_field(
2417
+					$ajax_sorting_callback . '_nonce',
2418
+					$ajax_sorting_callback . '_nonce',
2419
+					false,
2420
+					false
2421
+			);
2422
+			//			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
2423
+			//			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
2424
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="' . $this->page_slug . '" />';
2425
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="' . $ajax_sorting_callback . '" />';
2426
+		} else {
2427
+			$sortable_list_table_form_fields = '';
2428
+		}
2429
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2430
+		$hidden_form_fields = isset($this->_template_args['list_table_hidden_fields']) ? $this->_template_args['list_table_hidden_fields'] : '';
2431
+		$nonce_ref = $this->_req_action . '_nonce';
2432
+		$hidden_form_fields .= '<input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2433
+		$this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2434
+		//display message about search results?
2435
+		$this->_template_args['before_list_table'] .= apply_filters(
2436
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2437
+				! empty($this->_req_data['s'])
2438
+						? '<p class="ee-search-results">' . sprintf(
2439
+								__('Displaying search results for the search string: <strong><em>%s</em></strong>', 'event_espresso'),
2440
+								trim($this->_req_data['s'], '%')
2441
+						) . '</p>'
2442
+						: '',
2443
+				$this->page_slug,
2444
+				$this->_req_data,
2445
+				$this->_req_action
2446
+		);
2447
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2448
+				$template_path,
2449
+				$this->_template_args,
2450
+				true
2451
+		);
2452
+		// the final template wrapper
2453
+		if ($sidebar) {
2454
+			$this->display_admin_page_with_sidebar();
2455
+		} else {
2456
+			$this->display_admin_page_with_no_sidebar();
2457
+		}
2458
+	}
2459
+
2460
+
2461
+
2462
+	/**
2463
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the html string for the legend.
2464
+	 * $items are expected in an array in the following format:
2465
+	 * $legend_items = array(
2466
+	 *        'item_id' => array(
2467
+	 *            'icon' => 'http://url_to_icon_being_described.png',
2468
+	 *            'desc' => __('localized description of item');
2469
+	 *        )
2470
+	 * );
2471
+	 *
2472
+	 * @param  array $items see above for format of array
2473
+	 * @return string        html string of legend
2474
+	 */
2475
+	protected function _display_legend($items)
2476
+	{
2477
+		$this->_template_args['items'] = apply_filters('FHEE__EE_Admin_Page___display_legend__items', (array)$items, $this);
2478
+		$legend_template = EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php';
2479
+		return EEH_Template::display_template($legend_template, $this->_template_args, true);
2480
+	}
2481
+
2482
+
2483
+
2484
+	/**
2485
+	 * this is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
2486
+	 *
2487
+	 * @param bool $sticky_notices Used to indicate whether you want to ensure notices are added to a transient instead of displayed.
2488
+	 *                             The returned json object is created from an array in the following format:
2489
+	 *                             array(
2490
+	 *                             'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
2491
+	 *                             'success' => FALSE, //(default FALSE) - contains any special success message.
2492
+	 *                             'notices' => '', // - contains any EE_Error formatted notices
2493
+	 *                             'content' => 'string can be html', //this is a string of formatted content (can be html)
2494
+	 *                             'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js. We're also going to include the template args with every package (so js can pick out any
2495
+	 *                             specific template args that might be included in here)
2496
+	 *                             )
2497
+	 *                             The json object is populated by whatever is set in the $_template_args property.
2498
+	 * @return void
2499
+	 */
2500
+	protected function _return_json($sticky_notices = false)
2501
+	{
2502
+		//make sure any EE_Error notices have been handled.
2503
+		$this->_process_notices(array(), true, $sticky_notices);
2504
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
2505
+		unset($this->_template_args['data']);
2506
+		$json = array(
2507
+				'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
2508
+				'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
2509
+				'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
2510
+				'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
2511
+				'notices'   => EE_Error::get_notices(),
2512
+				'content'   => isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '',
2513
+				'data'      => array_merge($data, array('template_args' => $this->_template_args)),
2514
+				'isEEajax'  => true //special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
2515
+		);
2516
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
2517
+		if (null === error_get_last() || ! headers_sent()) {
2518
+			header('Content-Type: application/json; charset=UTF-8');
2519
+		}
2520
+		echo wp_json_encode($json);
2521
+
2522
+		exit();
2523
+	}
2524
+
2525
+
2526
+
2527
+	/**
2528
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
2529
+	 *
2530
+	 * @return void
2531
+	 * @throws EE_Error
2532
+	 */
2533
+	public function return_json()
2534
+	{
2535
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2536
+			$this->_return_json();
2537
+		} else {
2538
+			throw new EE_Error(sprintf(__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'), __FUNCTION__));
2539
+		}
2540
+	}
2541
+
2542
+
2543
+
2544
+	/**
2545
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
2546
+	 *
2547
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
2548
+	 * @access   public
2549
+	 */
2550
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
2551
+	{
2552
+		$this->_hook_obj = $hook_obj;
2553
+	}
2554
+
2555
+
2556
+
2557
+	/**
2558
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
2559
+	 *
2560
+	 * @access public
2561
+	 * @param  boolean $about whether to use the special about page wrapper or default.
2562
+	 * @return void
2563
+	 */
2564
+	public function admin_page_wrapper($about = false)
2565
+	{
2566
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2567
+		$this->_nav_tabs = $this->_get_main_nav_tabs();
2568
+		$this->_template_args['nav_tabs'] = $this->_nav_tabs;
2569
+		$this->_template_args['admin_page_title'] = $this->_admin_page_title;
2570
+		$this->_template_args['before_admin_page_content'] = apply_filters('FHEE_before_admin_page_content' . $this->_current_page . $this->_current_view,
2571
+				isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '');
2572
+		$this->_template_args['after_admin_page_content'] = apply_filters('FHEE_after_admin_page_content' . $this->_current_page . $this->_current_view,
2573
+				isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '');
2574
+		$this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
2575
+		// load settings page wrapper template
2576
+		$template_path = ! defined('DOING_AJAX') ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php' : EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php';
2577
+		//about page?
2578
+		$template_path = $about ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php' : $template_path;
2579
+		if (defined('DOING_AJAX')) {
2580
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2581
+			$this->_return_json();
2582
+		} else {
2583
+			EEH_Template::display_template($template_path, $this->_template_args);
2584
+		}
2585
+	}
2586
+
2587
+
2588
+
2589
+	/**
2590
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
2591
+	 *
2592
+	 * @return string html
2593
+	 */
2594
+	protected function _get_main_nav_tabs()
2595
+	{
2596
+		//let's generate the html using the EEH_Tabbed_Content helper.  We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute (rather than setting in the page_routes array)
2597
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
2598
+	}
2599
+
2600
+
2601
+
2602
+	/**
2603
+	 *        sort nav tabs
2604
+	 *
2605
+	 * @access public
2606
+	 * @param $a
2607
+	 * @param $b
2608
+	 * @return int
2609
+	 */
2610
+	private function _sort_nav_tabs($a, $b)
2611
+	{
2612
+		if ($a['order'] == $b['order']) {
2613
+			return 0;
2614
+		}
2615
+		return ($a['order'] < $b['order']) ? -1 : 1;
2616
+	}
2617
+
2618
+
2619
+
2620
+	/**
2621
+	 *    generates HTML for the forms used on admin pages
2622
+	 *
2623
+	 * @access protected
2624
+	 * @param    array $input_vars - array of input field details
2625
+	 * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to use)
2626
+	 * @return string
2627
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
2628
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
2629
+	 */
2630
+	protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
2631
+	{
2632
+		$content = $generator == 'string' ? EEH_Form_Fields::get_form_fields($input_vars, $id) : EEH_Form_Fields::get_form_fields_array($input_vars);
2633
+		return $content;
2634
+	}
2635
+
2636
+
2637
+
2638
+	/**
2639
+	 * generates the "Save" and "Save & Close" buttons for edit forms
2640
+	 *
2641
+	 * @access protected
2642
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save & Close" button.
2643
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] => 'Save', [1] => 'save & close')
2644
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e. via the "name" value in the button).  We can also use this to just dump default actions by submitting some other value.
2645
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it will use the $referrer string. IF null, then we don't do ANYTHING on save and close (normal form handling).
2646
+	 */
2647
+	protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
2648
+	{
2649
+		//make sure $text and $actions are in an array
2650
+		$text = (array)$text;
2651
+		$actions = (array)$actions;
2652
+		$referrer_url = empty($referrer) ? '' : $referrer;
2653
+		$referrer_url = ! $referrer ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $_SERVER['REQUEST_URI'] . '" />'
2654
+				: '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $referrer . '" />';
2655
+		$button_text = ! empty($text) ? $text : array(__('Save', 'event_espresso'), __('Save and Close', 'event_espresso'));
2656
+		$default_names = array('save', 'save_and_close');
2657
+		//add in a hidden index for the current page (so save and close redirects properly)
2658
+		$this->_template_args['save_buttons'] = $referrer_url;
2659
+		foreach ($button_text as $key => $button) {
2660
+			$ref = $default_names[$key];
2661
+			$id = $this->_current_view . '_' . $ref;
2662
+			$name = ! empty($actions) ? $actions[$key] : $ref;
2663
+			$this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary ' . $ref . '" value="' . $button . '" name="' . $name . '" id="' . $id . '" />';
2664
+			if ( ! $both) {
2665
+				break;
2666
+			}
2667
+		}
2668
+	}
2669
+
2670
+
2671
+
2672
+	/**
2673
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
2674
+	 *
2675
+	 * @see   $this->_set_add_edit_form_tags() for details on params
2676
+	 * @since 4.6.0
2677
+	 * @param string $route
2678
+	 * @param array  $additional_hidden_fields
2679
+	 */
2680
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2681
+	{
2682
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
2683
+	}
2684
+
2685
+
2686
+
2687
+	/**
2688
+	 * set form open and close tags on add/edit pages.
2689
+	 *
2690
+	 * @access protected
2691
+	 * @param string $route                    the route you want the form to direct to
2692
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
2693
+	 * @return void
2694
+	 */
2695
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2696
+	{
2697
+		if (empty($route)) {
2698
+			$user_msg = __('An error occurred. No action was set for this page\'s form.', 'event_espresso');
2699
+			$dev_msg = $user_msg . "\n" . sprintf(__('The $route argument is required for the %s->%s method.', 'event_espresso'), __FUNCTION__, __CLASS__);
2700
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
2701
+		}
2702
+		// open form
2703
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="' . $this->_admin_base_url . '" id="' . $route . '_event_form" >';
2704
+		// add nonce
2705
+		$nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
2706
+		//		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
2707
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
2708
+		// add REQUIRED form action
2709
+		$hidden_fields = array(
2710
+				'action' => array('type' => 'hidden', 'value' => $route),
2711
+		);
2712
+		// merge arrays
2713
+		$hidden_fields = is_array($additional_hidden_fields) ? array_merge($hidden_fields, $additional_hidden_fields) : $hidden_fields;
2714
+		// generate form fields
2715
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
2716
+		// add fields to form
2717
+		foreach ((array)$form_fields as $field_name => $form_field) {
2718
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
2719
+		}
2720
+		// close form
2721
+		$this->_template_args['after_admin_page_content'] = '</form>';
2722
+	}
2723
+
2724
+
2725
+
2726
+	/**
2727
+	 * Public Wrapper for _redirect_after_action() method since its
2728
+	 * discovered it would be useful for external code to have access.
2729
+	 *
2730
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
2731
+	 * @since 4.5.0
2732
+	 */
2733
+	public function redirect_after_action($success = false, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2734
+	{
2735
+		$this->_redirect_after_action($success, $what, $action_desc, $query_args, $override_overwrite);
2736
+	}
2737
+
2738
+
2739
+
2740
+	/**
2741
+	 *    _redirect_after_action
2742
+	 *
2743
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
2744
+	 * @param string $what               - what the action was performed on
2745
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
2746
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin action is completed
2747
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to override this so that they show.
2748
+	 * @access protected
2749
+	 * @return void
2750
+	 */
2751
+	protected function _redirect_after_action($success = 0, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2752
+	{
2753
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2754
+		//class name for actions/filters.
2755
+		$classname = get_class($this);
2756
+		//set redirect url. Note if there is a "page" index in the $query_args then we go with vanilla admin.php route, otherwise we go with whatever is set as the _admin_base_url
2757
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
2758
+		$notices = EE_Error::get_notices(false);
2759
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
2760
+		if ( ! $override_overwrite || ! empty($notices['errors'])) {
2761
+			EE_Error::overwrite_success();
2762
+		}
2763
+		if ( ! empty($what) && ! empty($action_desc)) {
2764
+			// how many records affected ? more than one record ? or just one ?
2765
+			if ($success > 1 && empty($notices['errors'])) {
2766
+				// set plural msg
2767
+				EE_Error::add_success(
2768
+						sprintf(
2769
+								__('The "%s" have been successfully %s.', 'event_espresso'),
2770
+								$what,
2771
+								$action_desc
2772
+						),
2773
+						__FILE__, __FUNCTION__, __LINE__
2774
+				);
2775
+			} else if ($success == 1 && empty($notices['errors'])) {
2776
+				// set singular msg
2777
+				EE_Error::add_success(
2778
+						sprintf(
2779
+								__('The "%s" has been successfully %s.', 'event_espresso'),
2780
+								$what,
2781
+								$action_desc
2782
+						),
2783
+						__FILE__, __FUNCTION__, __LINE__
2784
+				);
2785
+			}
2786
+		}
2787
+		// check that $query_args isn't something crazy
2788
+		if ( ! is_array($query_args)) {
2789
+			$query_args = array();
2790
+		}
2791
+		/**
2792
+		 * Allow injecting actions before the query_args are modified for possible different
2793
+		 * redirections on save and close actions
2794
+		 *
2795
+		 * @since 4.2.0
2796
+		 * @param array $query_args       The original query_args array coming into the
2797
+		 *                                method.
2798
+		 */
2799
+		do_action('AHEE__' . $classname . '___redirect_after_action__before_redirect_modification_' . $this->_req_action, $query_args);
2800
+		//calculate where we're going (if we have a "save and close" button pushed)
2801
+		if (isset($this->_req_data['save_and_close']) && isset($this->_req_data['save_and_close_referrer'])) {
2802
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
2803
+			$parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
2804
+			// regenerate query args array from referrer URL
2805
+			parse_str($parsed_url['query'], $query_args);
2806
+			// correct page and action will be in the query args now
2807
+			$redirect_url = admin_url('admin.php');
2808
+		}
2809
+		//merge any default query_args set in _default_route_query_args property
2810
+		if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
2811
+			$args_to_merge = array();
2812
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
2813
+				//is there a wp_referer array in our _default_route_query_args property?
2814
+				if ($query_param == 'wp_referer') {
2815
+					$query_value = (array)$query_value;
2816
+					foreach ($query_value as $reference => $value) {
2817
+						if (strpos($reference, 'nonce') !== false) {
2818
+							continue;
2819
+						}
2820
+						//finally we will override any arguments in the referer with
2821
+						//what might be set on the _default_route_query_args array.
2822
+						if (isset($this->_default_route_query_args[$reference])) {
2823
+							$args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
2824
+						} else {
2825
+							$args_to_merge[$reference] = urlencode($value);
2826
+						}
2827
+					}
2828
+					continue;
2829
+				}
2830
+				$args_to_merge[$query_param] = $query_value;
2831
+			}
2832
+			//now let's merge these arguments but override with what was specifically sent in to the
2833
+			//redirect.
2834
+			$query_args = array_merge($args_to_merge, $query_args);
2835
+		}
2836
+		$this->_process_notices($query_args);
2837
+		// generate redirect url
2838
+		// if redirecting to anything other than the main page, add a nonce
2839
+		if (isset($query_args['action'])) {
2840
+			// manually generate wp_nonce and merge that with the query vars becuz the wp_nonce_url function wrecks havoc on some vars
2841
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2842
+		}
2843
+		//we're adding some hooks and filters in here for processing any things just before redirects (example: an admin page has done an insert or update and we want to run something after that).
2844
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
2845
+		$redirect_url = apply_filters('FHEE_redirect_' . $classname . $this->_req_action, self::add_query_args_and_nonce($query_args, $redirect_url), $query_args);
2846
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
2847
+		if (defined('DOING_AJAX')) {
2848
+			$default_data = array(
2849
+					'close'        => true,
2850
+					'redirect_url' => $redirect_url,
2851
+					'where'        => 'main',
2852
+					'what'         => 'append',
2853
+			);
2854
+			$this->_template_args['success'] = $success;
2855
+			$this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge($default_data, $this->_template_args['data']) : $default_data;
2856
+			$this->_return_json();
2857
+		}
2858
+		wp_safe_redirect($redirect_url);
2859
+		exit();
2860
+	}
2861
+
2862
+
2863
+
2864
+	/**
2865
+	 * process any notices before redirecting (or returning ajax request)
2866
+	 * This method sets the $this->_template_args['notices'] attribute;
2867
+	 *
2868
+	 * @param  array $query_args        any query args that need to be used for notice transient ('action')
2869
+	 * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and page_routes haven't been defined yet.
2870
+	 * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we still save a transient for the notice.
2871
+	 * @return void
2872
+	 */
2873
+	protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
2874
+	{
2875
+		//first let's set individual error properties if doing_ajax and the properties aren't already set.
2876
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2877
+			$notices = EE_Error::get_notices(false);
2878
+			if (empty($this->_template_args['success'])) {
2879
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
2880
+			}
2881
+			if (empty($this->_template_args['errors'])) {
2882
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
2883
+			}
2884
+			if (empty($this->_template_args['attention'])) {
2885
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
2886
+			}
2887
+		}
2888
+		$this->_template_args['notices'] = EE_Error::get_notices();
2889
+		//IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
2890
+		if ( ! defined('DOING_AJAX') || $sticky_notices) {
2891
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
2892
+			$this->_add_transient($route, $this->_template_args['notices'], true, $skip_route_verify);
2893
+		}
2894
+	}
2895
+
2896
+
2897
+
2898
+	/**
2899
+	 * get_action_link_or_button
2900
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
2901
+	 *
2902
+	 * @param string $action        use this to indicate which action the url is generated with.
2903
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key) property.
2904
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
2905
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
2906
+	 * @param string $base_url      If this is not provided
2907
+	 *                              the _admin_base_url will be used as the default for the button base_url.
2908
+	 *                              Otherwise this value will be used.
2909
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
2910
+	 * @return string
2911
+	 * @throws \EE_Error
2912
+	 */
2913
+	public function get_action_link_or_button(
2914
+			$action,
2915
+			$type = 'add',
2916
+			$extra_request = array(),
2917
+			$class = 'button-primary',
2918
+			$base_url = '',
2919
+			$exclude_nonce = false
2920
+	) {
2921
+		//first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
2922
+		if (empty($base_url) && ! isset($this->_page_routes[$action])) {
2923
+			throw new EE_Error(
2924
+					sprintf(
2925
+							__(
2926
+									'There is no page route for given action for the button.  This action was given: %s',
2927
+									'event_espresso'
2928
+							),
2929
+							$action
2930
+					)
2931
+			);
2932
+		}
2933
+		if ( ! isset($this->_labels['buttons'][$type])) {
2934
+			throw new EE_Error(
2935
+					sprintf(
2936
+							__(
2937
+									'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
2938
+									'event_espresso'
2939
+							),
2940
+							$type
2941
+					)
2942
+			);
2943
+		}
2944
+		//finally check user access for this button.
2945
+		$has_access = $this->check_user_access($action, true);
2946
+		if ( ! $has_access) {
2947
+			return '';
2948
+		}
2949
+		$_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
2950
+		$query_args = array(
2951
+				'action' => $action,
2952
+		);
2953
+		//merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
2954
+		if ( ! empty($extra_request)) {
2955
+			$query_args = array_merge($extra_request, $query_args);
2956
+		}
2957
+		$url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
2958
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
2959
+	}
2960
+
2961
+
2962
+
2963
+	/**
2964
+	 * _per_page_screen_option
2965
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
2966
+	 *
2967
+	 * @return void
2968
+	 */
2969
+	protected function _per_page_screen_option()
2970
+	{
2971
+		$option = 'per_page';
2972
+		$args = array(
2973
+				'label'   => $this->_admin_page_title,
2974
+				'default' => 10,
2975
+				'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
2976
+		);
2977
+		//ONLY add the screen option if the user has access to it.
2978
+		if ($this->check_user_access($this->_current_view, true)) {
2979
+			add_screen_option($option, $args);
2980
+		}
2981
+	}
2982
+
2983
+
2984
+
2985
+	/**
2986
+	 * set_per_page_screen_option
2987
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
2988
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than admin_menu.
2989
+	 *
2990
+	 * @access private
2991
+	 * @return void
2992
+	 */
2993
+	private function _set_per_page_screen_options()
2994
+	{
2995
+		if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
2996
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
2997
+			if ( ! $user = wp_get_current_user()) {
2998
+				return;
2999
+			}
3000
+			$option = $_POST['wp_screen_options']['option'];
3001
+			$value = $_POST['wp_screen_options']['value'];
3002
+			if ($option != sanitize_key($option)) {
3003
+				return;
3004
+			}
3005
+			$map_option = $option;
3006
+			$option = str_replace('-', '_', $option);
3007
+			switch ($map_option) {
3008
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3009
+					$value = (int)$value;
3010
+					if ($value < 1 || $value > 999) {
3011
+						return;
3012
+					}
3013
+					break;
3014
+				default:
3015
+					$value = apply_filters('FHEE__EE_Admin_Page___set_per_page_screen_options__value', false, $option, $value);
3016
+					if (false === $value) {
3017
+						return;
3018
+					}
3019
+					break;
3020
+			}
3021
+			update_user_meta($user->ID, $option, $value);
3022
+			wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3023
+			exit;
3024
+		}
3025
+	}
3026
+
3027
+
3028
+
3029
+	/**
3030
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3031
+	 *
3032
+	 * @param array $data array that will be assigned to template args.
3033
+	 */
3034
+	public function set_template_args($data)
3035
+	{
3036
+		$this->_template_args = array_merge($this->_template_args, (array)$data);
3037
+	}
3038
+
3039
+
3040
+
3041
+	/**
3042
+	 * This makes available the WP transient system for temporarily moving data between routes
3043
+	 *
3044
+	 * @access protected
3045
+	 * @param string $route             the route that should receive the transient
3046
+	 * @param array  $data              the data that gets sent
3047
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a normal route transient.
3048
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used when we are adding a transient before page_routes have been defined.
3049
+	 * @return void
3050
+	 */
3051
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3052
+	{
3053
+		$user_id = get_current_user_id();
3054
+		if ( ! $skip_route_verify) {
3055
+			$this->_verify_route($route);
3056
+		}
3057
+		//now let's set the string for what kind of transient we're setting
3058
+		$transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3059
+		$data = $notices ? array('notices' => $data) : $data;
3060
+		//is there already a transient for this route?  If there is then let's ADD to that transient
3061
+		$existing = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3062
+		if ($existing) {
3063
+			$data = array_merge((array)$data, (array)$existing);
3064
+		}
3065
+		if (is_multisite() && is_network_admin()) {
3066
+			set_site_transient($transient, $data, 8);
3067
+		} else {
3068
+			set_transient($transient, $data, 8);
3069
+		}
3070
+	}
3071
+
3072
+
3073
+
3074
+	/**
3075
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3076
+	 *
3077
+	 * @param bool $notices true we get notices transient. False we just return normal route transient
3078
+	 * @return mixed data
3079
+	 */
3080
+	protected function _get_transient($notices = false, $route = false)
3081
+	{
3082
+		$user_id = get_current_user_id();
3083
+		$route = ! $route ? $this->_req_action : $route;
3084
+		$transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3085
+		$data = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3086
+		//delete transient after retrieval (just in case it hasn't expired);
3087
+		if (is_multisite() && is_network_admin()) {
3088
+			delete_site_transient($transient);
3089
+		} else {
3090
+			delete_transient($transient);
3091
+		}
3092
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3093
+	}
3094
+
3095
+
3096
+
3097
+	/**
3098
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but would not be called later.
3099
+	 * This will be assigned to run on a specific EE Admin page. (place the method in the default route callback on the EE_Admin page you want it run.)
3100
+	 *
3101
+	 * @return void
3102
+	 */
3103
+	protected function _transient_garbage_collection()
3104
+	{
3105
+		global $wpdb;
3106
+		//retrieve all existing transients
3107
+		$query = "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3108
+		if ($results = $wpdb->get_results($query)) {
3109
+			foreach ($results as $result) {
3110
+				$transient = str_replace('_transient_', '', $result->option_name);
3111
+				get_transient($transient);
3112
+				if (is_multisite() && is_network_admin()) {
3113
+					get_site_transient($transient);
3114
+				}
3115
+			}
3116
+		}
3117
+	}
3118
+
3119
+
3120
+
3121
+	/**
3122
+	 * get_view
3123
+	 *
3124
+	 * @access public
3125
+	 * @return string content of _view property
3126
+	 */
3127
+	public function get_view()
3128
+	{
3129
+		return $this->_view;
3130
+	}
3131
+
3132
+
3133
+
3134
+	/**
3135
+	 * getter for the protected $_views property
3136
+	 *
3137
+	 * @return array
3138
+	 */
3139
+	public function get_views()
3140
+	{
3141
+		return $this->_views;
3142
+	}
3143
+
3144
+
3145
+
3146
+	/**
3147
+	 * get_current_page
3148
+	 *
3149
+	 * @access public
3150
+	 * @return string _current_page property value
3151
+	 */
3152
+	public function get_current_page()
3153
+	{
3154
+		return $this->_current_page;
3155
+	}
3156
+
3157
+
3158
+
3159
+	/**
3160
+	 * get_current_view
3161
+	 *
3162
+	 * @access public
3163
+	 * @return string _current_view property value
3164
+	 */
3165
+	public function get_current_view()
3166
+	{
3167
+		return $this->_current_view;
3168
+	}
3169
+
3170
+
3171
+
3172
+	/**
3173
+	 * get_current_screen
3174
+	 *
3175
+	 * @access public
3176
+	 * @return object The current WP_Screen object
3177
+	 */
3178
+	public function get_current_screen()
3179
+	{
3180
+		return $this->_current_screen;
3181
+	}
3182
+
3183
+
3184
+
3185
+	/**
3186
+	 * get_current_page_view_url
3187
+	 *
3188
+	 * @access public
3189
+	 * @return string This returns the url for the current_page_view.
3190
+	 */
3191
+	public function get_current_page_view_url()
3192
+	{
3193
+		return $this->_current_page_view_url;
3194
+	}
3195
+
3196
+
3197
+
3198
+	/**
3199
+	 * just returns the _req_data property
3200
+	 *
3201
+	 * @return array
3202
+	 */
3203
+	public function get_request_data()
3204
+	{
3205
+		return $this->_req_data;
3206
+	}
3207
+
3208
+
3209
+
3210
+	/**
3211
+	 * returns the _req_data protected property
3212
+	 *
3213
+	 * @return string
3214
+	 */
3215
+	public function get_req_action()
3216
+	{
3217
+		return $this->_req_action;
3218
+	}
3219
+
3220
+
3221
+
3222
+	/**
3223
+	 * @return bool  value of $_is_caf property
3224
+	 */
3225
+	public function is_caf()
3226
+	{
3227
+		return $this->_is_caf;
3228
+	}
3229
+
3230
+
3231
+
3232
+	/**
3233
+	 * @return mixed
3234
+	 */
3235
+	public function default_espresso_metaboxes()
3236
+	{
3237
+		return $this->_default_espresso_metaboxes;
3238
+	}
3239
+
3240
+
3241
+
3242
+	/**
3243
+	 * @return mixed
3244
+	 */
3245
+	public function admin_base_url()
3246
+	{
3247
+		return $this->_admin_base_url;
3248
+	}
3249
+
3250
+
3251
+
3252
+	/**
3253
+	 * @return mixed
3254
+	 */
3255
+	public function wp_page_slug()
3256
+	{
3257
+		return $this->_wp_page_slug;
3258
+	}
3259
+
3260
+
3261
+
3262
+	/**
3263
+	 * updates  espresso configuration settings
3264
+	 *
3265
+	 * @access    protected
3266
+	 * @param string                   $tab
3267
+	 * @param EE_Config_Base|EE_Config $config
3268
+	 * @param string                   $file file where error occurred
3269
+	 * @param string                   $func function  where error occurred
3270
+	 * @param string                   $line line no where error occurred
3271
+	 * @return boolean
3272
+	 */
3273
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3274
+	{
3275
+		//remove any options that are NOT going to be saved with the config settings.
3276
+		if (isset($config->core->ee_ueip_optin)) {
3277
+			$config->core->ee_ueip_has_notified = true;
3278
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
3279
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3280
+			update_option('ee_ueip_has_notified', true);
3281
+		}
3282
+		// and save it (note we're also doing the network save here)
3283
+		$net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
3284
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
3285
+		if ($config_saved && $net_saved) {
3286
+			EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3287
+			return true;
3288
+		} else {
3289
+			EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3290
+			return false;
3291
+		}
3292
+	}
3293
+
3294
+
3295
+
3296
+	/**
3297
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
3298
+	 *
3299
+	 * @return array
3300
+	 */
3301
+	public function get_yes_no_values()
3302
+	{
3303
+		return $this->_yes_no_values;
3304
+	}
3305
+
3306
+
3307
+
3308
+	protected function _get_dir()
3309
+	{
3310
+		$reflector = new ReflectionClass(get_class($this));
3311
+		return dirname($reflector->getFileName());
3312
+	}
3313
+
3314
+
3315
+
3316
+	/**
3317
+	 * A helper for getting a "next link".
3318
+	 *
3319
+	 * @param string $url   The url to link to
3320
+	 * @param string $class The class to use.
3321
+	 * @return string
3322
+	 */
3323
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
3324
+	{
3325
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
3326
+	}
3327
+
3328
+
3329
+
3330
+	/**
3331
+	 * A helper for getting a "previous link".
3332
+	 *
3333
+	 * @param string $url   The url to link to
3334
+	 * @param string $class The class to use.
3335
+	 * @return string
3336
+	 */
3337
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
3338
+	{
3339
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
3340
+	}
3341
+
3342
+
3343
+
3344
+
3345
+
3346
+
3347
+
3348
+	//below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
3349
+	/**
3350
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the _req_data
3351
+	 * array.
3352
+	 *
3353
+	 * @return bool success/fail
3354
+	 */
3355
+	protected function _process_resend_registration()
3356
+	{
3357
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
3358
+		do_action('AHEE__EE_Admin_Page___process_resend_registration', $this->_template_args['success'], $this->_req_data);
3359
+		return $this->_template_args['success'];
3360
+	}
3361
+
3362
+
3363
+
3364
+	/**
3365
+	 * This automatically processes any payment message notifications when manual payment has been applied.
3366
+	 *
3367
+	 * @access protected
3368
+	 * @param \EE_Payment $payment
3369
+	 * @return bool success/fail
3370
+	 */
3371
+	protected function _process_payment_notification(EE_Payment $payment)
3372
+	{
3373
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
3374
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
3375
+		$this->_template_args['success'] = apply_filters('FHEE__EE_Admin_Page___process_admin_payment_notification__success', false, $payment);
3376
+		return $this->_template_args['success'];
3377
+	}
3378 3378
 
3379 3379
 
3380 3380
 }
Please login to merge, or discard this patch.