Completed
Branch FET/11183/improvements-to-pue-... (232f50)
by
unknown
43:46 queued 26:36
created
core/libraries/plugin_api/EE_Register_Data_Migration_Scripts.lib.php 2 patches
Indentation   +87 added lines, -87 removed lines patch added patch discarded remove patch
@@ -18,99 +18,99 @@
 block discarded – undo
18 18
 class EE_Register_Data_Migration_Scripts implements EEI_Plugin_API
19 19
 {
20 20
 
21
-    /**
22
-     * Holds values for registered DMSs
23
-     *
24
-     * @var array[][]
25
-     */
26
-    protected static $_settings = array();
21
+	/**
22
+	 * Holds values for registered DMSs
23
+	 *
24
+	 * @var array[][]
25
+	 */
26
+	protected static $_settings = array();
27 27
 
28 28
 
29
-    /**
30
-     * Method for registering new Data Migration Scripts
31
-     *
32
-     * @since 4.3.0
33
-     * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
34
-     *                           If EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
35
-     * @param array $setup_args {
36
-     *      @type string  $dms_paths an array of full server paths to folders that contain data migration scripts
37
-     *  }
38
-     * @throws EE_Error
39
-     * @return void
40
-     */
41
-    public static function register($addon_name = '', $setup_args = array())
42
-    {
43
-        //required fields MUST be present, so let's make sure they are.
44
-        if (empty($addon_name) || ! is_array($setup_args) || empty($setup_args['dms_paths'])) {
45
-            throw new EE_Error(
46
-                esc_html__(
47
-                    'In order to register Data Migration Scripts with EE_Register_Data_Migration_Scripts::register(), you must include the EE_Addon class name (used as a unique identifier for this set of data migration scripts), and an array containing the following keys: "dms_paths" (an array of full server paths to folders that contain data migration scripts)',
48
-                    'event_espresso'
49
-                )
50
-            );
51
-        }
52
-        //make sure we don't register twice
53
-        if (isset(self::$_settings[ $addon_name ])) {
54
-            return;
55
-        }
56
-        //make sure this was called in the right place!
57
-        if (! did_action('AHEE__EE_System__load_espresso_addons')
58
-            || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
59
-        ) {
60
-            EE_Error::doing_it_wrong(
61
-                __METHOD__,
62
-                esc_html__(
63
-                    'An attempt to register Data Migration Scripts has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register Data Migration Scripts.',
64
-                    'event_espresso'
65
-                ),
66
-                '4.3.0'
67
-            );
68
-        }
69
-        //setup $_settings array from incoming values.
70
-        self::$_settings[ $addon_name ] = array(
71
-            'dms_paths' => (array) $setup_args['dms_paths']
72
-        );
73
-        // setup DMS
74
-        add_filter(
75
-            'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
76
-            array('EE_Register_Data_Migration_Scripts', 'add_data_migration_script_folders')
77
-        );
78
-    }
29
+	/**
30
+	 * Method for registering new Data Migration Scripts
31
+	 *
32
+	 * @since 4.3.0
33
+	 * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
34
+	 *                           If EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
35
+	 * @param array $setup_args {
36
+	 *      @type string  $dms_paths an array of full server paths to folders that contain data migration scripts
37
+	 *  }
38
+	 * @throws EE_Error
39
+	 * @return void
40
+	 */
41
+	public static function register($addon_name = '', $setup_args = array())
42
+	{
43
+		//required fields MUST be present, so let's make sure they are.
44
+		if (empty($addon_name) || ! is_array($setup_args) || empty($setup_args['dms_paths'])) {
45
+			throw new EE_Error(
46
+				esc_html__(
47
+					'In order to register Data Migration Scripts with EE_Register_Data_Migration_Scripts::register(), you must include the EE_Addon class name (used as a unique identifier for this set of data migration scripts), and an array containing the following keys: "dms_paths" (an array of full server paths to folders that contain data migration scripts)',
48
+					'event_espresso'
49
+				)
50
+			);
51
+		}
52
+		//make sure we don't register twice
53
+		if (isset(self::$_settings[ $addon_name ])) {
54
+			return;
55
+		}
56
+		//make sure this was called in the right place!
57
+		if (! did_action('AHEE__EE_System__load_espresso_addons')
58
+			|| did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
59
+		) {
60
+			EE_Error::doing_it_wrong(
61
+				__METHOD__,
62
+				esc_html__(
63
+					'An attempt to register Data Migration Scripts has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register Data Migration Scripts.',
64
+					'event_espresso'
65
+				),
66
+				'4.3.0'
67
+			);
68
+		}
69
+		//setup $_settings array from incoming values.
70
+		self::$_settings[ $addon_name ] = array(
71
+			'dms_paths' => (array) $setup_args['dms_paths']
72
+		);
73
+		// setup DMS
74
+		add_filter(
75
+			'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
76
+			array('EE_Register_Data_Migration_Scripts', 'add_data_migration_script_folders')
77
+		);
78
+	}
79 79
 
80 80
 
81
-    /**
82
-     * @param array $dms_paths
83
-     * @return array
84
-     */
85
-    public static function add_data_migration_script_folders($dms_paths = array())
86
-    {
87
-        foreach (self::$_settings as $addon_name => $settings) {
88
-            $wildcards = 0;
89
-            foreach ($settings['dms_paths'] as $dms_path) {
90
-                // since we are using the addon name for the array key
91
-                // we need to ensure that the key is unique,
92
-                // so if for some reason an addon has multiple dms paths,
93
-                // we append one or more * to the classname
94
-                // which will get stripped out later on
95
-                $dms_paths[ $addon_name . str_repeat('*', $wildcards) ] = $dms_path;
96
-                $wildcards++;
97
-            }
98
-        }
99
-        return $dms_paths;
100
-    }
81
+	/**
82
+	 * @param array $dms_paths
83
+	 * @return array
84
+	 */
85
+	public static function add_data_migration_script_folders($dms_paths = array())
86
+	{
87
+		foreach (self::$_settings as $addon_name => $settings) {
88
+			$wildcards = 0;
89
+			foreach ($settings['dms_paths'] as $dms_path) {
90
+				// since we are using the addon name for the array key
91
+				// we need to ensure that the key is unique,
92
+				// so if for some reason an addon has multiple dms paths,
93
+				// we append one or more * to the classname
94
+				// which will get stripped out later on
95
+				$dms_paths[ $addon_name . str_repeat('*', $wildcards) ] = $dms_path;
96
+				$wildcards++;
97
+			}
98
+		}
99
+		return $dms_paths;
100
+	}
101 101
 
102 102
 
103
-    /**
104
-     * This deregisters a set of Data Migration Scripts that were previously registered with a specific dms_id
105
-     *
106
-     * @since 4.3.0
107
-     * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
108
-     * @return void
109
-     */
110
-    public static function deregister($addon_name = '')
111
-    {
112
-        unset(self::$_settings[ $addon_name ]);
113
-    }
103
+	/**
104
+	 * This deregisters a set of Data Migration Scripts that were previously registered with a specific dms_id
105
+	 *
106
+	 * @since 4.3.0
107
+	 * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
108
+	 * @return void
109
+	 */
110
+	public static function deregister($addon_name = '')
111
+	{
112
+		unset(self::$_settings[ $addon_name ]);
113
+	}
114 114
 }
115 115
 // End of file EE_Register_Data_Migration_Scripts.lib.php
116 116
 // Location: /core/libraries/plugin_api/EE_Register_Data_Migration_Scripts.lib.php
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -50,11 +50,11 @@  discard block
 block discarded – undo
50 50
             );
51 51
         }
52 52
         //make sure we don't register twice
53
-        if (isset(self::$_settings[ $addon_name ])) {
53
+        if (isset(self::$_settings[$addon_name])) {
54 54
             return;
55 55
         }
56 56
         //make sure this was called in the right place!
57
-        if (! did_action('AHEE__EE_System__load_espresso_addons')
57
+        if ( ! did_action('AHEE__EE_System__load_espresso_addons')
58 58
             || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
59 59
         ) {
60 60
             EE_Error::doing_it_wrong(
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
             );
68 68
         }
69 69
         //setup $_settings array from incoming values.
70
-        self::$_settings[ $addon_name ] = array(
70
+        self::$_settings[$addon_name] = array(
71 71
             'dms_paths' => (array) $setup_args['dms_paths']
72 72
         );
73 73
         // setup DMS
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
                 // so if for some reason an addon has multiple dms paths,
93 93
                 // we append one or more * to the classname
94 94
                 // which will get stripped out later on
95
-                $dms_paths[ $addon_name . str_repeat('*', $wildcards) ] = $dms_path;
95
+                $dms_paths[$addon_name.str_repeat('*', $wildcards)] = $dms_path;
96 96
                 $wildcards++;
97 97
             }
98 98
         }
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
      */
110 110
     public static function deregister($addon_name = '')
111 111
     {
112
-        unset(self::$_settings[ $addon_name ]);
112
+        unset(self::$_settings[$addon_name]);
113 113
     }
114 114
 }
115 115
 // End of file EE_Register_Data_Migration_Scripts.lib.php
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1587 added lines, -1587 removed lines patch added patch discarded remove patch
@@ -23,1593 +23,1593 @@
 block discarded – undo
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Registry $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var EE_Dependency_Map $_dependency_map
33
-     */
34
-    protected $_dependency_map;
35
-
36
-    /**
37
-     * @var array $_class_abbreviations
38
-     */
39
-    protected $_class_abbreviations = array();
40
-
41
-    /**
42
-     * @var CommandBusInterface $BUS
43
-     */
44
-    public $BUS;
45
-
46
-    /**
47
-     * @var EE_Cart $CART
48
-     */
49
-    public $CART;
50
-
51
-    /**
52
-     * @var EE_Config $CFG
53
-     */
54
-    public $CFG;
55
-
56
-    /**
57
-     * @var EE_Network_Config $NET_CFG
58
-     */
59
-    public $NET_CFG;
60
-
61
-    /**
62
-     * StdClass object for storing library classes in
63
-     *
64
-     * @var StdClass $LIB
65
-     */
66
-    public $LIB;
67
-
68
-    /**
69
-     * @var EE_Request_Handler $REQ
70
-     */
71
-    public $REQ;
72
-
73
-    /**
74
-     * @var EE_Session $SSN
75
-     */
76
-    public $SSN;
77
-
78
-    /**
79
-     * @since 4.5.0
80
-     * @var EE_Capabilities $CAP
81
-     */
82
-    public $CAP;
83
-
84
-    /**
85
-     * @since 4.9.0
86
-     * @var EE_Message_Resource_Manager $MRM
87
-     */
88
-    public $MRM;
89
-
90
-
91
-    /**
92
-     * @var Registry $AssetsRegistry
93
-     */
94
-    public $AssetsRegistry;
95
-
96
-    /**
97
-     * StdClass object for holding addons which have registered themselves to work with EE core
98
-     *
99
-     * @var EE_Addon[] $addons
100
-     */
101
-    public $addons;
102
-
103
-    /**
104
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
105
-     *
106
-     * @var EEM_Base[] $models
107
-     */
108
-    public $models = array();
109
-
110
-    /**
111
-     * @var EED_Module[] $modules
112
-     */
113
-    public $modules;
114
-
115
-    /**
116
-     * @var EES_Shortcode[] $shortcodes
117
-     */
118
-    public $shortcodes;
119
-
120
-    /**
121
-     * @var WP_Widget[] $widgets
122
-     */
123
-    public $widgets;
124
-
125
-    /**
126
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
127
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
128
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
129
-     * classnames (eg "EEM_Event")
130
-     *
131
-     * @var array $non_abstract_db_models
132
-     */
133
-    public $non_abstract_db_models = array();
134
-
135
-
136
-    /**
137
-     * internationalization for JS strings
138
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
139
-     *    in js file:  var translatedString = eei18n.string_key;
140
-     *
141
-     * @var array $i18n_js_strings
142
-     */
143
-    public static $i18n_js_strings = array();
144
-
145
-
146
-    /**
147
-     * $main_file - path to espresso.php
148
-     *
149
-     * @var array $main_file
150
-     */
151
-    public $main_file;
152
-
153
-    /**
154
-     * array of ReflectionClass objects where the key is the class name
155
-     *
156
-     * @var ReflectionClass[] $_reflectors
157
-     */
158
-    public $_reflectors;
159
-
160
-    /**
161
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
162
-     *
163
-     * @var boolean $_cache_on
164
-     */
165
-    protected $_cache_on = true;
166
-
167
-
168
-
169
-    /**
170
-     * @singleton method used to instantiate class object
171
-     * @param  EE_Dependency_Map $dependency_map
172
-     * @return EE_Registry instance
173
-     * @throws InvalidArgumentException
174
-     * @throws InvalidInterfaceException
175
-     * @throws InvalidDataTypeException
176
-     */
177
-    public static function instance(EE_Dependency_Map $dependency_map = null)
178
-    {
179
-        // check if class object is instantiated
180
-        if (! self::$_instance instanceof EE_Registry) {
181
-            self::$_instance = new self($dependency_map);
182
-        }
183
-        return self::$_instance;
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * protected constructor to prevent direct creation
190
-     *
191
-     * @Constructor
192
-     * @param  EE_Dependency_Map $dependency_map
193
-     * @throws InvalidDataTypeException
194
-     * @throws InvalidInterfaceException
195
-     * @throws InvalidArgumentException
196
-     */
197
-    protected function __construct(EE_Dependency_Map $dependency_map)
198
-    {
199
-        $this->_dependency_map = $dependency_map;
200
-        // $registry_container = new RegistryContainer();
201
-        $this->LIB = new RegistryContainer();
202
-        $this->addons = new RegistryContainer();
203
-        $this->modules = new RegistryContainer();
204
-        $this->shortcodes = new RegistryContainer();
205
-        $this->widgets = new RegistryContainer();
206
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
207
-    }
208
-
209
-
210
-
211
-    /**
212
-     * initialize
213
-     *
214
-     * @throws EE_Error
215
-     * @throws ReflectionException
216
-     */
217
-    public function initialize()
218
-    {
219
-        $this->_class_abbreviations = apply_filters(
220
-            'FHEE__EE_Registry____construct___class_abbreviations',
221
-            array(
222
-                'EE_Config'                                       => 'CFG',
223
-                'EE_Session'                                      => 'SSN',
224
-                'EE_Capabilities'                                 => 'CAP',
225
-                'EE_Cart'                                         => 'CART',
226
-                'EE_Network_Config'                               => 'NET_CFG',
227
-                'EE_Request_Handler'                              => 'REQ',
228
-                'EE_Message_Resource_Manager'                     => 'MRM',
229
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
230
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
231
-            )
232
-        );
233
-        $this->load_core('Base', array(), true);
234
-        // add our request and response objects to the cache
235
-        $request_loader = $this->_dependency_map->class_loader(
236
-            'EventEspresso\core\services\request\Request'
237
-        );
238
-        $this->_set_cached_class(
239
-            $request_loader(),
240
-            'EventEspresso\core\services\request\Request'
241
-        );
242
-        $response_loader = $this->_dependency_map->class_loader(
243
-            'EventEspresso\core\services\request\Response'
244
-        );
245
-        $this->_set_cached_class(
246
-            $response_loader(),
247
-            'EventEspresso\core\services\request\Response'
248
-        );
249
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
250
-    }
251
-
252
-
253
-
254
-    /**
255
-     * @return void
256
-     */
257
-    public function init()
258
-    {
259
-        // Get current page protocol
260
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
261
-        // Output admin-ajax.php URL with same protocol as current page
262
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
263
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
264
-    }
265
-
266
-
267
-
268
-    /**
269
-     * localize_i18n_js_strings
270
-     *
271
-     * @return string
272
-     */
273
-    public static function localize_i18n_js_strings()
274
-    {
275
-        $i18n_js_strings = (array)self::$i18n_js_strings;
276
-        foreach ($i18n_js_strings as $key => $value) {
277
-            if (is_scalar($value)) {
278
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
279
-            }
280
-        }
281
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @param mixed string | EED_Module $module
288
-     * @throws EE_Error
289
-     * @throws ReflectionException
290
-     */
291
-    public function add_module($module)
292
-    {
293
-        if ($module instanceof EED_Module) {
294
-            $module_class = get_class($module);
295
-            $this->modules->{$module_class} = $module;
296
-        } else {
297
-            if ( ! class_exists('EE_Module_Request_Router', false)) {
298
-                $this->load_core('Module_Request_Router');
299
-            }
300
-            EE_Module_Request_Router::module_factory($module);
301
-        }
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @param string $module_name
308
-     * @return mixed EED_Module | NULL
309
-     */
310
-    public function get_module($module_name = '')
311
-    {
312
-        return isset($this->modules->{$module_name})
313
-            ? $this->modules->{$module_name}
314
-            : null;
315
-    }
316
-
317
-
318
-
319
-    /**
320
-     * loads core classes - must be singletons
321
-     *
322
-     * @param string $class_name - simple class name ie: session
323
-     * @param mixed  $arguments
324
-     * @param bool   $load_only
325
-     * @return mixed
326
-     * @throws EE_Error
327
-     * @throws ReflectionException
328
-     */
329
-    public function load_core($class_name, $arguments = array(), $load_only = false)
330
-    {
331
-        $core_paths = apply_filters(
332
-            'FHEE__EE_Registry__load_core__core_paths',
333
-            array(
334
-                EE_CORE,
335
-                EE_ADMIN,
336
-                EE_CPTS,
337
-                EE_CORE . 'data_migration_scripts' . DS,
338
-                EE_CORE . 'capabilities' . DS,
339
-                EE_CORE . 'request_stack' . DS,
340
-                EE_CORE . 'middleware' . DS,
341
-            )
342
-        );
343
-        // retrieve instantiated class
344
-        return $this->_load(
345
-            $core_paths,
346
-            'EE_',
347
-            $class_name,
348
-            'core',
349
-            $arguments,
350
-            false,
351
-            true,
352
-            $load_only
353
-        );
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * loads service classes
360
-     *
361
-     * @param string $class_name - simple class name ie: session
362
-     * @param mixed  $arguments
363
-     * @param bool   $load_only
364
-     * @return mixed
365
-     * @throws EE_Error
366
-     * @throws ReflectionException
367
-     */
368
-    public function load_service($class_name, $arguments = array(), $load_only = false)
369
-    {
370
-        $service_paths = apply_filters(
371
-            'FHEE__EE_Registry__load_service__service_paths',
372
-            array(
373
-                EE_CORE . 'services' . DS,
374
-            )
375
-        );
376
-        // retrieve instantiated class
377
-        return $this->_load(
378
-            $service_paths,
379
-            'EE_',
380
-            $class_name,
381
-            'class',
382
-            $arguments,
383
-            false,
384
-            true,
385
-            $load_only
386
-        );
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     * loads data_migration_scripts
393
-     *
394
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
395
-     * @param mixed  $arguments
396
-     * @return EE_Data_Migration_Script_Base|mixed
397
-     * @throws EE_Error
398
-     * @throws ReflectionException
399
-     */
400
-    public function load_dms($class_name, $arguments = array())
401
-    {
402
-        // retrieve instantiated class
403
-        return $this->_load(
404
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
405
-            'EE_DMS_',
406
-            $class_name,
407
-            'dms',
408
-            $arguments,
409
-            false,
410
-            false
411
-        );
412
-    }
413
-
414
-
415
-
416
-    /**
417
-     * loads object creating classes - must be singletons
418
-     *
419
-     * @param string $class_name - simple class name ie: attendee
420
-     * @param mixed  $arguments  - an array of arguments to pass to the class
421
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
422
-     *                           instantiate
423
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
424
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
425
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
426
-     *                           (default)
427
-     * @return EE_Base_Class | bool
428
-     * @throws EE_Error
429
-     * @throws ReflectionException
430
-     */
431
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
432
-    {
433
-        $paths = apply_filters(
434
-            'FHEE__EE_Registry__load_class__paths', array(
435
-            EE_CORE,
436
-            EE_CLASSES,
437
-            EE_BUSINESS,
438
-        )
439
-        );
440
-        // retrieve instantiated class
441
-        return $this->_load(
442
-            $paths,
443
-            'EE_',
444
-            $class_name,
445
-            'class',
446
-            $arguments,
447
-            $from_db,
448
-            $cache,
449
-            $load_only
450
-        );
451
-    }
452
-
453
-
454
-
455
-    /**
456
-     * loads helper classes - must be singletons
457
-     *
458
-     * @param string $class_name - simple class name ie: price
459
-     * @param mixed  $arguments
460
-     * @param bool   $load_only
461
-     * @return EEH_Base | bool
462
-     * @throws EE_Error
463
-     * @throws ReflectionException
464
-     */
465
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
466
-    {
467
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
468
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
469
-        // retrieve instantiated class
470
-        return $this->_load(
471
-            $helper_paths,
472
-            'EEH_',
473
-            $class_name,
474
-            'helper',
475
-            $arguments,
476
-            false,
477
-            true,
478
-            $load_only
479
-        );
480
-    }
481
-
482
-
483
-
484
-    /**
485
-     * loads core classes - must be singletons
486
-     *
487
-     * @param string $class_name - simple class name ie: session
488
-     * @param mixed  $arguments
489
-     * @param bool   $load_only
490
-     * @param bool   $cache      whether to cache the object or not.
491
-     * @return mixed
492
-     * @throws EE_Error
493
-     * @throws ReflectionException
494
-     */
495
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
496
-    {
497
-        $paths = array(
498
-            EE_LIBRARIES,
499
-            EE_LIBRARIES . 'messages' . DS,
500
-            EE_LIBRARIES . 'shortcodes' . DS,
501
-            EE_LIBRARIES . 'qtips' . DS,
502
-            EE_LIBRARIES . 'payment_methods' . DS,
503
-        );
504
-        // retrieve instantiated class
505
-        return $this->_load(
506
-            $paths,
507
-            'EE_',
508
-            $class_name,
509
-            'lib',
510
-            $arguments,
511
-            false,
512
-            $cache,
513
-            $load_only
514
-        );
515
-    }
516
-
517
-
518
-
519
-    /**
520
-     * loads model classes - must be singletons
521
-     *
522
-     * @param string $class_name - simple class name ie: price
523
-     * @param mixed  $arguments
524
-     * @param bool   $load_only
525
-     * @return EEM_Base | bool
526
-     * @throws EE_Error
527
-     * @throws ReflectionException
528
-     */
529
-    public function load_model($class_name, $arguments = array(), $load_only = false)
530
-    {
531
-        $paths = apply_filters(
532
-            'FHEE__EE_Registry__load_model__paths', array(
533
-            EE_MODELS,
534
-            EE_CORE,
535
-        )
536
-        );
537
-        // retrieve instantiated class
538
-        return $this->_load(
539
-            $paths,
540
-            'EEM_',
541
-            $class_name,
542
-            'model',
543
-            $arguments,
544
-            false,
545
-            true,
546
-            $load_only
547
-        );
548
-    }
549
-
550
-
551
-
552
-    /**
553
-     * loads model classes - must be singletons
554
-     *
555
-     * @param string $class_name - simple class name ie: price
556
-     * @param mixed  $arguments
557
-     * @param bool   $load_only
558
-     * @return mixed | bool
559
-     * @throws EE_Error
560
-     * @throws ReflectionException
561
-     */
562
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
563
-    {
564
-        $paths = array(
565
-            EE_MODELS . 'fields' . DS,
566
-            EE_MODELS . 'helpers' . DS,
567
-            EE_MODELS . 'relations' . DS,
568
-            EE_MODELS . 'strategies' . DS,
569
-        );
570
-        // retrieve instantiated class
571
-        return $this->_load(
572
-            $paths,
573
-            'EE_',
574
-            $class_name,
575
-            '',
576
-            $arguments,
577
-            false,
578
-            true,
579
-            $load_only
580
-        );
581
-    }
582
-
583
-
584
-
585
-    /**
586
-     * Determines if $model_name is the name of an actual EE model.
587
-     *
588
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
589
-     * @return boolean
590
-     */
591
-    public function is_model_name($model_name)
592
-    {
593
-        return isset($this->models[$model_name]);
594
-    }
595
-
596
-
597
-
598
-    /**
599
-     * generic class loader
600
-     *
601
-     * @param string $path_to_file - directory path to file location, not including filename
602
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
603
-     * @param string $type         - file type - core? class? helper? model?
604
-     * @param mixed  $arguments
605
-     * @param bool   $load_only
606
-     * @return mixed
607
-     * @throws EE_Error
608
-     * @throws ReflectionException
609
-     */
610
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
611
-    {
612
-        // retrieve instantiated class
613
-        return $this->_load(
614
-            $path_to_file,
615
-            '',
616
-            $file_name,
617
-            $type,
618
-            $arguments,
619
-            false,
620
-            true,
621
-            $load_only
622
-        );
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * @param string $path_to_file - directory path to file location, not including filename
629
-     * @param string $class_name   - full class name  ie:  My_Class
630
-     * @param string $type         - file type - core? class? helper? model?
631
-     * @param mixed  $arguments
632
-     * @param bool   $load_only
633
-     * @return bool|EE_Addon|object
634
-     * @throws EE_Error
635
-     * @throws ReflectionException
636
-     */
637
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
638
-    {
639
-        // retrieve instantiated class
640
-        return $this->_load(
641
-            $path_to_file,
642
-            'addon',
643
-            $class_name,
644
-            $type,
645
-            $arguments,
646
-            false,
647
-            true,
648
-            $load_only
649
-        );
650
-    }
651
-
652
-
653
-
654
-    /**
655
-     * instantiates, caches, and automatically resolves dependencies
656
-     * for classes that use a Fully Qualified Class Name.
657
-     * if the class is not capable of being loaded using PSR-4 autoloading,
658
-     * then you need to use one of the existing load_*() methods
659
-     * which can resolve the classname and filepath from the passed arguments
660
-     *
661
-     * @param bool|string $class_name   Fully Qualified Class Name
662
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
663
-     * @param bool        $cache        whether to cache the instantiated object for reuse
664
-     * @param bool        $from_db      some classes are instantiated from the db
665
-     *                                  and thus call a different method to instantiate
666
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
667
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
668
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
669
-     *                                  object = class loaded and instantiated successfully.
670
-     *                                  bool = fail or success when $load_only is true
671
-     * @throws EE_Error
672
-     * @throws ReflectionException
673
-     */
674
-    public function create(
675
-        $class_name = false,
676
-        $arguments = array(),
677
-        $cache = false,
678
-        $from_db = false,
679
-        $load_only = false,
680
-        $addon = false
681
-    ) {
682
-        $class_name = ltrim($class_name, '\\');
683
-        $class_name = $this->_dependency_map->get_alias($class_name);
684
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
685
-        // if a non-FQCN was passed, then verifyClassExists() might return an object
686
-        // or it could return null if the class just could not be found anywhere
687
-        if ($class_exists instanceof $class_name || $class_exists === null){
688
-            // either way, return the results
689
-            return $class_exists;
690
-        }
691
-        $class_name = $class_exists;
692
-        // if we're only loading the class and it already exists, then let's just return true immediately
693
-        if ($load_only) {
694
-            return true;
695
-        }
696
-        $addon = $addon
697
-            ? 'addon'
698
-            : '';
699
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
700
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
701
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
702
-        if ($this->_cache_on && $cache && ! $load_only) {
703
-            // return object if it's already cached
704
-            $cached_class = $this->_get_cached_class($class_name, $addon);
705
-            if ($cached_class !== null) {
706
-                return $cached_class;
707
-            }
708
-        }
709
-        // obtain the loader method from the dependency map
710
-        $loader = $this->_dependency_map->class_loader($class_name);
711
-        // instantiate the requested object
712
-        if ($loader instanceof Closure) {
713
-            $class_obj = $loader($arguments);
714
-        } else if ($loader && method_exists($this, $loader)) {
715
-            $class_obj = $this->{$loader}($class_name, $arguments);
716
-        } else {
717
-            $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
718
-        }
719
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
720
-            // save it for later... kinda like gum  { : $
721
-            $this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
722
-        }
723
-        $this->_cache_on = true;
724
-        return $class_obj;
725
-    }
726
-
727
-
728
-
729
-    /**
730
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
731
-     *
732
-     * @param string $class_name
733
-     * @param array  $arguments
734
-     * @param int    $attempt
735
-     * @return mixed
736
-     */
737
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1) {
738
-        if (is_object($class_name) || class_exists($class_name)) {
739
-            return $class_name;
740
-        }
741
-        switch ($attempt) {
742
-            case 1:
743
-                // if it's a FQCN then maybe the class is registered with a preceding \
744
-                $class_name = strpos($class_name, '\\') !== false
745
-                    ? '\\' . ltrim($class_name, '\\')
746
-                    : $class_name;
747
-                break;
748
-            case 2:
749
-                //
750
-                $loader = $this->_dependency_map->class_loader($class_name);
751
-                if ($loader && method_exists($this, $loader)) {
752
-                    return $this->{$loader}($class_name, $arguments);
753
-                }
754
-                break;
755
-            case 3:
756
-            default;
757
-                return null;
758
-        }
759
-        $attempt++;
760
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
761
-    }
762
-
763
-
764
-
765
-    /**
766
-     * instantiates, caches, and injects dependencies for classes
767
-     *
768
-     * @param array       $file_paths   an array of paths to folders to look in
769
-     * @param string      $class_prefix EE  or EEM or... ???
770
-     * @param bool|string $class_name   $class name
771
-     * @param string      $type         file type - core? class? helper? model?
772
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
773
-     * @param bool        $from_db      some classes are instantiated from the db
774
-     *                                  and thus call a different method to instantiate
775
-     * @param bool        $cache        whether to cache the instantiated object for reuse
776
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
777
-     * @return bool|null|object null = failure to load or instantiate class object.
778
-     *                                  object = class loaded and instantiated successfully.
779
-     *                                  bool = fail or success when $load_only is true
780
-     * @throws EE_Error
781
-     * @throws ReflectionException
782
-     */
783
-    protected function _load(
784
-        $file_paths = array(),
785
-        $class_prefix = 'EE_',
786
-        $class_name = false,
787
-        $type = 'class',
788
-        $arguments = array(),
789
-        $from_db = false,
790
-        $cache = true,
791
-        $load_only = false
792
-    ) {
793
-        $class_name = ltrim($class_name, '\\');
794
-        // strip php file extension
795
-        $class_name = str_replace('.php', '', trim($class_name));
796
-        // does the class have a prefix ?
797
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
798
-            // make sure $class_prefix is uppercase
799
-            $class_prefix = strtoupper(trim($class_prefix));
800
-            // add class prefix ONCE!!!
801
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
802
-        }
803
-        $class_name = $this->_dependency_map->get_alias($class_name);
804
-        $class_exists = class_exists($class_name, false);
805
-        // if we're only loading the class and it already exists, then let's just return true immediately
806
-        if ($load_only && $class_exists) {
807
-            return true;
808
-        }
809
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
810
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
811
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
812
-        if ($this->_cache_on && $cache && ! $load_only) {
813
-            // return object if it's already cached
814
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix);
815
-            if ($cached_class !== null) {
816
-                return $cached_class;
817
-            }
818
-        }
819
-        // if the class doesn't already exist.. then we need to try and find the file and load it
820
-        if (! $class_exists) {
821
-            // get full path to file
822
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
823
-            // load the file
824
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
825
-            // if loading failed, or we are only loading a file but NOT instantiating an object
826
-            if (! $loaded || $load_only) {
827
-                // return boolean if only loading, or null if an object was expected
828
-                return $load_only
829
-                    ? $loaded
830
-                    : null;
831
-            }
832
-        }
833
-        // instantiate the requested object
834
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
835
-        if ($this->_cache_on && $cache) {
836
-            // save it for later... kinda like gum  { : $
837
-            $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
838
-        }
839
-        $this->_cache_on = true;
840
-        return $class_obj;
841
-    }
842
-
843
-
844
-
845
-    /**
846
-     * @param string $class_name
847
-     * @param string $default have to specify something, but not anything that will conflict
848
-     * @return mixed|string
849
-     */
850
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
851
-    {
852
-        return isset($this->_class_abbreviations[$class_name])
853
-            ? $this->_class_abbreviations[$class_name]
854
-            : $default;
855
-    }
856
-
857
-    /**
858
-     * attempts to find a cached version of the requested class
859
-     * by looking in the following places:
860
-     *        $this->{$class_abbreviation}            ie:    $this->CART
861
-     *        $this->{$class_name}                        ie:    $this->Some_Class
862
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
863
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
864
-     *
865
-     * @param string $class_name
866
-     * @param string $class_prefix
867
-     * @return mixed
868
-     * @throws OutOfBoundsException
869
-     */
870
-    protected function _get_cached_class($class_name, $class_prefix = '')
871
-    {
872
-        if ($class_name === 'EE_Registry') {
873
-            return $this;
874
-        }
875
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
876
-        $class_name = str_replace('\\', '_', $class_name);
877
-        // check if class has already been loaded, and return it if it has been
878
-        if (isset($this->{$class_abbreviation})) {
879
-            return $this->{$class_abbreviation};
880
-        }
881
-        if (isset ($this->{$class_name})) {
882
-            return $this->{$class_name};
883
-        }
884
-        if (isset ($this->LIB->{$class_name})) {
885
-            return $this->LIB->{$class_name};
886
-        }
887
-        if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
888
-            return $this->addons->{$class_name};
889
-        }
890
-        return null;
891
-    }
892
-
893
-
894
-
895
-    /**
896
-     * removes a cached version of the requested class
897
-     *
898
-     * @param string  $class_name
899
-     * @param boolean $addon
900
-     * @return boolean
901
-     * @throws OutOfBoundsException
902
-     */
903
-    public function clear_cached_class($class_name, $addon = false)
904
-    {
905
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
906
-        $class_name = str_replace('\\', '_', $class_name);
907
-        // check if class has already been loaded, and return it if it has been
908
-        if (isset($this->{$class_abbreviation})) {
909
-            $this->{$class_abbreviation} = null;
910
-            return true;
911
-        }
912
-        if (isset($this->{$class_name})) {
913
-            $this->{$class_name} = null;
914
-            return true;
915
-        }
916
-        if (isset($this->LIB->{$class_name})) {
917
-            unset($this->LIB->{$class_name});
918
-            return true;
919
-        }
920
-        if ($addon && isset($this->addons->{$class_name})) {
921
-            unset($this->addons->{$class_name});
922
-            return true;
923
-        }
924
-        return false;
925
-    }
926
-
927
-
928
-
929
-    /**
930
-     * attempts to find a full valid filepath for the requested class.
931
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
932
-     * then returns that path if the target file has been found and is readable
933
-     *
934
-     * @param string $class_name
935
-     * @param string $type
936
-     * @param array  $file_paths
937
-     * @return string | bool
938
-     */
939
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
940
-    {
941
-        // make sure $file_paths is an array
942
-        $file_paths = is_array($file_paths)
943
-            ? $file_paths
944
-            : array($file_paths);
945
-        // cycle thru paths
946
-        foreach ($file_paths as $key => $file_path) {
947
-            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
948
-            $file_path = $file_path
949
-                ? str_replace(array('/', '\\'), DS, $file_path)
950
-                : EE_CLASSES;
951
-            // prep file type
952
-            $type = ! empty($type)
953
-                ? trim($type, '.') . '.'
954
-                : '';
955
-            // build full file path
956
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
957
-            //does the file exist and can be read ?
958
-            if (is_readable($file_paths[$key])) {
959
-                return $file_paths[$key];
960
-            }
961
-        }
962
-        return false;
963
-    }
964
-
965
-
966
-
967
-    /**
968
-     * basically just performs a require_once()
969
-     * but with some error handling
970
-     *
971
-     * @param  string $path
972
-     * @param  string $class_name
973
-     * @param  string $type
974
-     * @param  array  $file_paths
975
-     * @return bool
976
-     * @throws EE_Error
977
-     * @throws ReflectionException
978
-     */
979
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
980
-    {
981
-        $this->resolve_legacy_class_parent($class_name);
982
-        // don't give up! you gotta...
983
-        try {
984
-            //does the file exist and can it be read ?
985
-            if (! $path) {
986
-                // just in case the file has already been autoloaded,
987
-                // but discrepancies in the naming schema are preventing it from
988
-                // being loaded via one of the EE_Registry::load_*() methods,
989
-                // then let's try one last hail mary before throwing an exception
990
-                // and call class_exists() again, but with autoloading turned ON
991
-                if(class_exists($class_name)) {
992
-                    return true;
993
-                }
994
-                // so sorry, can't find the file
995
-                throw new EE_Error (
996
-                    sprintf(
997
-                        esc_html__(
998
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
999
-                            'event_espresso'
1000
-                        ),
1001
-                        trim($type, '.'),
1002
-                        $class_name,
1003
-                        '<br />' . implode(',<br />', $file_paths)
1004
-                    )
1005
-                );
1006
-            }
1007
-            // get the file
1008
-            require_once($path);
1009
-            // if the class isn't already declared somewhere
1010
-            if (class_exists($class_name, false) === false) {
1011
-                // so sorry, not a class
1012
-                throw new EE_Error(
1013
-                    sprintf(
1014
-                        esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
1015
-                        $type,
1016
-                        $path,
1017
-                        $class_name
1018
-                    )
1019
-                );
1020
-            }
1021
-        } catch (EE_Error $e) {
1022
-            $e->get_error();
1023
-            return false;
1024
-        }
1025
-        return true;
1026
-    }
1027
-
1028
-
1029
-
1030
-    /**
1031
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1032
-     * before their class declaration in order to ensure that the parent class was loaded.
1033
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1034
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1035
-     *
1036
-     * @param string $class_name
1037
-     */
1038
-    protected function resolve_legacy_class_parent($class_name = '')
1039
-    {
1040
-        try {
1041
-            $legacy_parent_class_map = array(
1042
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
1043
-            );
1044
-            if(isset($legacy_parent_class_map[$class_name])) {
1045
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
1046
-            }
1047
-        } catch (Exception $exception) {
1048
-        }
1049
-    }
1050
-
1051
-
1052
-
1053
-    /**
1054
-     * _create_object
1055
-     * Attempts to instantiate the requested class via any of the
1056
-     * commonly used instantiation methods employed throughout EE.
1057
-     * The priority for instantiation is as follows:
1058
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1059
-     *        - model objects via their 'new_instance_from_db' method
1060
-     *        - model objects via their 'new_instance' method
1061
-     *        - "singleton" classes" via their 'instance' method
1062
-     *    - standard instantiable classes via their __constructor
1063
-     * Prior to instantiation, if the classname exists in the dependency_map,
1064
-     * then the constructor for the requested class will be examined to determine
1065
-     * if any dependencies exist, and if they can be injected.
1066
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1067
-     *
1068
-     * @param string $class_name
1069
-     * @param array  $arguments
1070
-     * @param string $type
1071
-     * @param bool   $from_db
1072
-     * @return null|object
1073
-     * @throws EE_Error
1074
-     * @throws ReflectionException
1075
-     */
1076
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1077
-    {
1078
-        // create reflection
1079
-        $reflector = $this->get_ReflectionClass($class_name);
1080
-        // make sure arguments are an array
1081
-        $arguments = is_array($arguments)
1082
-            ? $arguments
1083
-            : array($arguments);
1084
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1085
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1086
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1087
-            ? $arguments
1088
-            : array($arguments);
1089
-        // attempt to inject dependencies ?
1090
-        if ($this->_dependency_map->has($class_name)) {
1091
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1092
-        }
1093
-        // instantiate the class if possible
1094
-        if ($reflector->isAbstract()) {
1095
-            // nothing to instantiate, loading file was enough
1096
-            // does not throw an exception so $instantiation_mode is unused
1097
-            // $instantiation_mode = "1) no constructor abstract class";
1098
-            return true;
1099
-        }
1100
-        if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1101
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1102
-            // $instantiation_mode = "2) no constructor but instantiable";
1103
-            return $reflector->newInstance();
1104
-        }
1105
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1106
-            // $instantiation_mode = "3) new_instance_from_db()";
1107
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1108
-        }
1109
-        if (method_exists($class_name, 'new_instance')) {
1110
-            // $instantiation_mode = "4) new_instance()";
1111
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1112
-        }
1113
-        if (method_exists($class_name, 'instance')) {
1114
-            // $instantiation_mode = "5) instance()";
1115
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1116
-        }
1117
-        if ($reflector->isInstantiable()) {
1118
-            // $instantiation_mode = "6) constructor";
1119
-            return $reflector->newInstanceArgs($arguments);
1120
-        }
1121
-        // heh ? something's not right !
1122
-        throw new EE_Error(
1123
-            sprintf(
1124
-                __('The %s file %s could not be instantiated.', 'event_espresso'),
1125
-                $type,
1126
-                $class_name
1127
-            )
1128
-        );
1129
-    }
1130
-
1131
-
1132
-
1133
-    /**
1134
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1135
-     * @param array $array
1136
-     * @return bool
1137
-     */
1138
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1139
-    {
1140
-        return ! empty($array)
1141
-            ? array_keys($array) === range(0, count($array) - 1)
1142
-            : true;
1143
-    }
1144
-
1145
-
1146
-
1147
-    /**
1148
-     * getReflectionClass
1149
-     * checks if a ReflectionClass object has already been generated for a class
1150
-     * and returns that instead of creating a new one
1151
-     *
1152
-     * @param string $class_name
1153
-     * @return ReflectionClass
1154
-     * @throws ReflectionException
1155
-     */
1156
-    public function get_ReflectionClass($class_name)
1157
-    {
1158
-        if (
1159
-            ! isset($this->_reflectors[$class_name])
1160
-            || ! $this->_reflectors[$class_name] instanceof ReflectionClass
1161
-        ) {
1162
-            $this->_reflectors[$class_name] = new ReflectionClass($class_name);
1163
-        }
1164
-        return $this->_reflectors[$class_name];
1165
-    }
1166
-
1167
-
1168
-
1169
-    /**
1170
-     * _resolve_dependencies
1171
-     * examines the constructor for the requested class to determine
1172
-     * if any dependencies exist, and if they can be injected.
1173
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1174
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1175
-     * For example:
1176
-     *        if attempting to load a class "Foo" with the following constructor:
1177
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1178
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1179
-     *        but only IF they are NOT already present in the incoming arguments array,
1180
-     *        and the correct classes can be loaded
1181
-     *
1182
-     * @param ReflectionClass $reflector
1183
-     * @param string          $class_name
1184
-     * @param array           $arguments
1185
-     * @return array
1186
-     * @throws EE_Error
1187
-     * @throws ReflectionException
1188
-     */
1189
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1190
-    {
1191
-        // let's examine the constructor
1192
-        $constructor = $reflector->getConstructor();
1193
-        // whu? huh? nothing?
1194
-        if (! $constructor) {
1195
-            return $arguments;
1196
-        }
1197
-        // get constructor parameters
1198
-        $params = $constructor->getParameters();
1199
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1200
-        $argument_keys = array_keys($arguments);
1201
-        // now loop thru all of the constructors expected parameters
1202
-        foreach ($params as $index => $param) {
1203
-            // is this a dependency for a specific class ?
1204
-            $param_class = $param->getClass()
1205
-                ? $param->getClass()->name
1206
-                : null;
1207
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1208
-            $param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1209
-                ? $this->_dependency_map->get_alias($param_class, $class_name)
1210
-                : $param_class;
1211
-            if (
1212
-                // param is not even a class
1213
-                $param_class === null
1214
-                // and something already exists in the incoming arguments for this param
1215
-                && array_key_exists($index, $argument_keys)
1216
-                && array_key_exists($argument_keys[$index], $arguments)
1217
-            ) {
1218
-                // so let's skip this argument and move on to the next
1219
-                continue;
1220
-            }
1221
-            if (
1222
-                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1223
-                $param_class !== null
1224
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1225
-                && $arguments[$argument_keys[$index]] instanceof $param_class
1226
-            ) {
1227
-                // skip this argument and move on to the next
1228
-                continue;
1229
-            }
1230
-            if (
1231
-                // parameter is type hinted as a class, and should be injected
1232
-                $param_class !== null
1233
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1234
-            ) {
1235
-                $arguments = $this->_resolve_dependency(
1236
-                    $class_name,
1237
-                    $param_class,
1238
-                    $arguments,
1239
-                    $index,
1240
-                    $argument_keys
1241
-                );
1242
-            } else {
1243
-                try {
1244
-                    $arguments[$index] = $param->isDefaultValueAvailable()
1245
-                        ? $param->getDefaultValue()
1246
-                        : null;
1247
-                } catch (ReflectionException $e) {
1248
-                    throw new ReflectionException(
1249
-                        sprintf(
1250
-                            esc_html__('%1$s for parameter "$%2$s on classname "%3$s"', 'event_espresso'),
1251
-                            $e->getMessage(),
1252
-                            $param->getName(),
1253
-                            $class_name
1254
-                        )
1255
-                    );
1256
-                }
1257
-            }
1258
-        }
1259
-        return $arguments;
1260
-    }
1261
-
1262
-
1263
-
1264
-    /**
1265
-     * @param string $class_name
1266
-     * @param string $param_class
1267
-     * @param array  $arguments
1268
-     * @param mixed  $index
1269
-     * @param array  $argument_keys
1270
-     * @return array
1271
-     * @throws EE_Error
1272
-     * @throws ReflectionException
1273
-     * @throws InvalidArgumentException
1274
-     * @throws InvalidInterfaceException
1275
-     * @throws InvalidDataTypeException
1276
-     */
1277
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1278
-    {
1279
-        $dependency = null;
1280
-        // should dependency be loaded from cache ?
1281
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1282
-            $class_name,
1283
-            $param_class
1284
-        );
1285
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1286
-        // we might have a dependency...
1287
-        // let's MAYBE try and find it in our cache if that's what's been requested
1288
-        $cached_class = $cache_on
1289
-            ? $this->_get_cached_class($param_class)
1290
-            : null;
1291
-        // and grab it if it exists
1292
-        if ($cached_class instanceof $param_class) {
1293
-            $dependency = $cached_class;
1294
-        } else if ($param_class !== $class_name) {
1295
-            // obtain the loader method from the dependency map
1296
-            $loader = $this->_dependency_map->class_loader($param_class);
1297
-            // is loader a custom closure ?
1298
-            if ($loader instanceof Closure) {
1299
-                $dependency = $loader($arguments);
1300
-            } else {
1301
-                // set the cache on property for the recursive loading call
1302
-                $this->_cache_on = $cache_on;
1303
-                // if not, then let's try and load it via the registry
1304
-                if ($loader && method_exists($this, $loader)) {
1305
-                    $dependency = $this->{$loader}($param_class);
1306
-                } else {
1307
-                    $dependency = LoaderFactory::getLoader()->load(
1308
-                        $param_class,
1309
-                        array(),
1310
-                        $cache_on
1311
-                    );
1312
-                }
1313
-            }
1314
-        }
1315
-        // did we successfully find the correct dependency ?
1316
-        if ($dependency instanceof $param_class) {
1317
-            // then let's inject it into the incoming array of arguments at the correct location
1318
-            $arguments[$index] = $dependency;
1319
-        }
1320
-        return $arguments;
1321
-    }
1322
-
1323
-
1324
-
1325
-    /**
1326
-     * _set_cached_class
1327
-     * attempts to cache the instantiated class locally
1328
-     * in one of the following places, in the following order:
1329
-     *        $this->{class_abbreviation}   ie:    $this->CART
1330
-     *        $this->{$class_name}          ie:    $this->Some_Class
1331
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1332
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1333
-     *
1334
-     * @param object $class_obj
1335
-     * @param string $class_name
1336
-     * @param string $class_prefix
1337
-     * @param bool   $from_db
1338
-     * @return void
1339
-     * @throws OutOfBoundsException
1340
-     */
1341
-    protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1342
-    {
1343
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1344
-            return;
1345
-        }
1346
-        // return newly instantiated class
1347
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1348
-        if ($class_abbreviation) {
1349
-            $this->{$class_abbreviation} = $class_obj;
1350
-            return;
1351
-        }
1352
-        $class_name = str_replace('\\', '_', $class_name);
1353
-        if (property_exists($this, $class_name)) {
1354
-            $this->{$class_name} = $class_obj;
1355
-            return;
1356
-        }
1357
-        if ($class_prefix === 'addon') {
1358
-            $this->addons->{$class_name} = $class_obj;
1359
-            return;
1360
-        }
1361
-        if (! $from_db) {
1362
-            $this->LIB->{$class_name} = $class_obj;
1363
-        }
1364
-    }
1365
-
1366
-
1367
-
1368
-    /**
1369
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1370
-     *
1371
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1372
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1373
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1374
-     * @param array  $arguments
1375
-     * @return object
1376
-     */
1377
-    public static function factory($classname, $arguments = array())
1378
-    {
1379
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1380
-        if ($loader instanceof Closure) {
1381
-            return $loader($arguments);
1382
-        }
1383
-        if (method_exists(self::instance(), $loader)) {
1384
-            return self::instance()->{$loader}($classname, $arguments);
1385
-        }
1386
-        return null;
1387
-    }
1388
-
1389
-
1390
-
1391
-    /**
1392
-     * Gets the addon by its class name
1393
-     *
1394
-     * @param string $class_name
1395
-     * @return EE_Addon
1396
-     * @throws OutOfBoundsException
1397
-     */
1398
-    public function getAddon($class_name)
1399
-    {
1400
-        $class_name = str_replace('\\', '_', $class_name);
1401
-        return $this->addons->{$class_name};
1402
-    }
1403
-
1404
-
1405
-    /**
1406
-     * removes the addon from the internal cache
1407
-     *
1408
-     * @param string $class_name
1409
-     * @return void
1410
-     */
1411
-    public function removeAddon($class_name)
1412
-    {
1413
-        $class_name = str_replace('\\', '_', $class_name);
1414
-        unset($this->addons->{$class_name});
1415
-    }
1416
-
1417
-
1418
-
1419
-    /**
1420
-     * Gets the addon by its name/slug (not classname. For that, just
1421
-     * use the get_addon() method above
1422
-     *
1423
-     * @param string $name
1424
-     * @return EE_Addon
1425
-     */
1426
-    public function get_addon_by_name($name)
1427
-    {
1428
-        foreach ($this->addons as $addon) {
1429
-            if ($addon->name() === $name) {
1430
-                return $addon;
1431
-            }
1432
-        }
1433
-        return null;
1434
-    }
1435
-
1436
-
1437
-
1438
-    /**
1439
-     * Gets an array of all the registered addons, where the keys are their names.
1440
-     * (ie, what each returns for their name() function)
1441
-     * They're already available on EE_Registry::instance()->addons as properties,
1442
-     * where each property's name is the addon's classname,
1443
-     * So if you just want to get the addon by classname,
1444
-     * OR use the get_addon() method above.
1445
-     * PLEASE  NOTE:
1446
-     * addons with Fully Qualified Class Names
1447
-     * have had the namespace separators converted to underscores,
1448
-     * so a classname like Fully\Qualified\ClassName
1449
-     * would have been converted to Fully_Qualified_ClassName
1450
-     *
1451
-     * @return EE_Addon[] where the KEYS are the addon's name()
1452
-     */
1453
-    public function get_addons_by_name()
1454
-    {
1455
-        $addons = array();
1456
-        foreach ($this->addons as $addon) {
1457
-            $addons[$addon->name()] = $addon;
1458
-        }
1459
-        return $addons;
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1465
-     * a stale copy of it around
1466
-     *
1467
-     * @param string $model_name
1468
-     * @return \EEM_Base
1469
-     * @throws \EE_Error
1470
-     */
1471
-    public function reset_model($model_name)
1472
-    {
1473
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1474
-            ? "EEM_{$model_name}"
1475
-            : $model_name;
1476
-        if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1477
-            return null;
1478
-        }
1479
-        //get that model reset it and make sure we nuke the old reference to it
1480
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name
1481
-            && is_callable(
1482
-                array($model_class_name, 'reset')
1483
-            )) {
1484
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1485
-        } else {
1486
-            throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1487
-        }
1488
-        return $this->LIB->{$model_class_name};
1489
-    }
1490
-
1491
-
1492
-
1493
-    /**
1494
-     * Resets the registry.
1495
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1496
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1497
-     * - $_dependency_map
1498
-     * - $_class_abbreviations
1499
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1500
-     * - $REQ:  Still on the same request so no need to change.
1501
-     * - $CAP: There is no site specific state in the EE_Capability class.
1502
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1503
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1504
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1505
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1506
-     *             switch or on the restore.
1507
-     * - $modules
1508
-     * - $shortcodes
1509
-     * - $widgets
1510
-     *
1511
-     * @param boolean $hard             [deprecated]
1512
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1513
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1514
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1515
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1516
-     *                                  client
1517
-     *                                  code instead can just change the model context to a different blog id if
1518
-     *                                  necessary
1519
-     * @return EE_Registry
1520
-     * @throws EE_Error
1521
-     * @throws ReflectionException
1522
-     */
1523
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1524
-    {
1525
-        $instance = self::instance();
1526
-        $instance->_cache_on = true;
1527
-        // reset some "special" classes
1528
-        EEH_Activation::reset();
1529
-        $hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1530
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1531
-        $instance->CART = null;
1532
-        $instance->MRM = null;
1533
-        $instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1534
-        //messages reset
1535
-        EED_Messages::reset();
1536
-        //handle of objects cached on LIB
1537
-        foreach (array('LIB', 'modules') as $cache) {
1538
-            foreach ($instance->{$cache} as $class_name => $class) {
1539
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1540
-                    unset($instance->{$cache}->{$class_name});
1541
-                }
1542
-            }
1543
-        }
1544
-        return $instance;
1545
-    }
1546
-
1547
-
1548
-
1549
-    /**
1550
-     * if passed object implements ResettableInterface, then call it's reset() method
1551
-     * if passed object implements InterminableInterface, then return false,
1552
-     * to indicate that it should NOT be cleared from the Registry cache
1553
-     *
1554
-     * @param      $object
1555
-     * @param bool $reset_models
1556
-     * @return bool returns true if cached object should be unset
1557
-     */
1558
-    private static function _reset_and_unset_object($object, $reset_models)
1559
-    {
1560
-        if (! is_object($object)) {
1561
-            // don't unset anything that's not an object
1562
-            return false;
1563
-        }
1564
-        if ($object instanceof EED_Module) {
1565
-            $object::reset();
1566
-            // don't unset modules
1567
-            return false;
1568
-        }
1569
-        if ($object instanceof ResettableInterface) {
1570
-            if ($object instanceof EEM_Base) {
1571
-                if ($reset_models) {
1572
-                    $object->reset();
1573
-                    return true;
1574
-                }
1575
-                return false;
1576
-            }
1577
-            $object->reset();
1578
-            return true;
1579
-        }
1580
-        if (! $object instanceof InterminableInterface) {
1581
-            return true;
1582
-        }
1583
-        return false;
1584
-    }
1585
-
1586
-
1587
-
1588
-    /**
1589
-     * Gets all the custom post type models defined
1590
-     *
1591
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1592
-     */
1593
-    public function cpt_models()
1594
-    {
1595
-        $cpt_models = array();
1596
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1597
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1598
-                $cpt_models[$short_name] = $classname;
1599
-            }
1600
-        }
1601
-        return $cpt_models;
1602
-    }
1603
-
1604
-
1605
-
1606
-    /**
1607
-     * @return \EE_Config
1608
-     */
1609
-    public static function CFG()
1610
-    {
1611
-        return self::instance()->CFG;
1612
-    }
26
+	/**
27
+	 * @var EE_Registry $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var EE_Dependency_Map $_dependency_map
33
+	 */
34
+	protected $_dependency_map;
35
+
36
+	/**
37
+	 * @var array $_class_abbreviations
38
+	 */
39
+	protected $_class_abbreviations = array();
40
+
41
+	/**
42
+	 * @var CommandBusInterface $BUS
43
+	 */
44
+	public $BUS;
45
+
46
+	/**
47
+	 * @var EE_Cart $CART
48
+	 */
49
+	public $CART;
50
+
51
+	/**
52
+	 * @var EE_Config $CFG
53
+	 */
54
+	public $CFG;
55
+
56
+	/**
57
+	 * @var EE_Network_Config $NET_CFG
58
+	 */
59
+	public $NET_CFG;
60
+
61
+	/**
62
+	 * StdClass object for storing library classes in
63
+	 *
64
+	 * @var StdClass $LIB
65
+	 */
66
+	public $LIB;
67
+
68
+	/**
69
+	 * @var EE_Request_Handler $REQ
70
+	 */
71
+	public $REQ;
72
+
73
+	/**
74
+	 * @var EE_Session $SSN
75
+	 */
76
+	public $SSN;
77
+
78
+	/**
79
+	 * @since 4.5.0
80
+	 * @var EE_Capabilities $CAP
81
+	 */
82
+	public $CAP;
83
+
84
+	/**
85
+	 * @since 4.9.0
86
+	 * @var EE_Message_Resource_Manager $MRM
87
+	 */
88
+	public $MRM;
89
+
90
+
91
+	/**
92
+	 * @var Registry $AssetsRegistry
93
+	 */
94
+	public $AssetsRegistry;
95
+
96
+	/**
97
+	 * StdClass object for holding addons which have registered themselves to work with EE core
98
+	 *
99
+	 * @var EE_Addon[] $addons
100
+	 */
101
+	public $addons;
102
+
103
+	/**
104
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
105
+	 *
106
+	 * @var EEM_Base[] $models
107
+	 */
108
+	public $models = array();
109
+
110
+	/**
111
+	 * @var EED_Module[] $modules
112
+	 */
113
+	public $modules;
114
+
115
+	/**
116
+	 * @var EES_Shortcode[] $shortcodes
117
+	 */
118
+	public $shortcodes;
119
+
120
+	/**
121
+	 * @var WP_Widget[] $widgets
122
+	 */
123
+	public $widgets;
124
+
125
+	/**
126
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
127
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
128
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
129
+	 * classnames (eg "EEM_Event")
130
+	 *
131
+	 * @var array $non_abstract_db_models
132
+	 */
133
+	public $non_abstract_db_models = array();
134
+
135
+
136
+	/**
137
+	 * internationalization for JS strings
138
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
139
+	 *    in js file:  var translatedString = eei18n.string_key;
140
+	 *
141
+	 * @var array $i18n_js_strings
142
+	 */
143
+	public static $i18n_js_strings = array();
144
+
145
+
146
+	/**
147
+	 * $main_file - path to espresso.php
148
+	 *
149
+	 * @var array $main_file
150
+	 */
151
+	public $main_file;
152
+
153
+	/**
154
+	 * array of ReflectionClass objects where the key is the class name
155
+	 *
156
+	 * @var ReflectionClass[] $_reflectors
157
+	 */
158
+	public $_reflectors;
159
+
160
+	/**
161
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
162
+	 *
163
+	 * @var boolean $_cache_on
164
+	 */
165
+	protected $_cache_on = true;
166
+
167
+
168
+
169
+	/**
170
+	 * @singleton method used to instantiate class object
171
+	 * @param  EE_Dependency_Map $dependency_map
172
+	 * @return EE_Registry instance
173
+	 * @throws InvalidArgumentException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws InvalidDataTypeException
176
+	 */
177
+	public static function instance(EE_Dependency_Map $dependency_map = null)
178
+	{
179
+		// check if class object is instantiated
180
+		if (! self::$_instance instanceof EE_Registry) {
181
+			self::$_instance = new self($dependency_map);
182
+		}
183
+		return self::$_instance;
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * protected constructor to prevent direct creation
190
+	 *
191
+	 * @Constructor
192
+	 * @param  EE_Dependency_Map $dependency_map
193
+	 * @throws InvalidDataTypeException
194
+	 * @throws InvalidInterfaceException
195
+	 * @throws InvalidArgumentException
196
+	 */
197
+	protected function __construct(EE_Dependency_Map $dependency_map)
198
+	{
199
+		$this->_dependency_map = $dependency_map;
200
+		// $registry_container = new RegistryContainer();
201
+		$this->LIB = new RegistryContainer();
202
+		$this->addons = new RegistryContainer();
203
+		$this->modules = new RegistryContainer();
204
+		$this->shortcodes = new RegistryContainer();
205
+		$this->widgets = new RegistryContainer();
206
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
207
+	}
208
+
209
+
210
+
211
+	/**
212
+	 * initialize
213
+	 *
214
+	 * @throws EE_Error
215
+	 * @throws ReflectionException
216
+	 */
217
+	public function initialize()
218
+	{
219
+		$this->_class_abbreviations = apply_filters(
220
+			'FHEE__EE_Registry____construct___class_abbreviations',
221
+			array(
222
+				'EE_Config'                                       => 'CFG',
223
+				'EE_Session'                                      => 'SSN',
224
+				'EE_Capabilities'                                 => 'CAP',
225
+				'EE_Cart'                                         => 'CART',
226
+				'EE_Network_Config'                               => 'NET_CFG',
227
+				'EE_Request_Handler'                              => 'REQ',
228
+				'EE_Message_Resource_Manager'                     => 'MRM',
229
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
230
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
231
+			)
232
+		);
233
+		$this->load_core('Base', array(), true);
234
+		// add our request and response objects to the cache
235
+		$request_loader = $this->_dependency_map->class_loader(
236
+			'EventEspresso\core\services\request\Request'
237
+		);
238
+		$this->_set_cached_class(
239
+			$request_loader(),
240
+			'EventEspresso\core\services\request\Request'
241
+		);
242
+		$response_loader = $this->_dependency_map->class_loader(
243
+			'EventEspresso\core\services\request\Response'
244
+		);
245
+		$this->_set_cached_class(
246
+			$response_loader(),
247
+			'EventEspresso\core\services\request\Response'
248
+		);
249
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
250
+	}
251
+
252
+
253
+
254
+	/**
255
+	 * @return void
256
+	 */
257
+	public function init()
258
+	{
259
+		// Get current page protocol
260
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
261
+		// Output admin-ajax.php URL with same protocol as current page
262
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
263
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
264
+	}
265
+
266
+
267
+
268
+	/**
269
+	 * localize_i18n_js_strings
270
+	 *
271
+	 * @return string
272
+	 */
273
+	public static function localize_i18n_js_strings()
274
+	{
275
+		$i18n_js_strings = (array)self::$i18n_js_strings;
276
+		foreach ($i18n_js_strings as $key => $value) {
277
+			if (is_scalar($value)) {
278
+				$i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
279
+			}
280
+		}
281
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @param mixed string | EED_Module $module
288
+	 * @throws EE_Error
289
+	 * @throws ReflectionException
290
+	 */
291
+	public function add_module($module)
292
+	{
293
+		if ($module instanceof EED_Module) {
294
+			$module_class = get_class($module);
295
+			$this->modules->{$module_class} = $module;
296
+		} else {
297
+			if ( ! class_exists('EE_Module_Request_Router', false)) {
298
+				$this->load_core('Module_Request_Router');
299
+			}
300
+			EE_Module_Request_Router::module_factory($module);
301
+		}
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @param string $module_name
308
+	 * @return mixed EED_Module | NULL
309
+	 */
310
+	public function get_module($module_name = '')
311
+	{
312
+		return isset($this->modules->{$module_name})
313
+			? $this->modules->{$module_name}
314
+			: null;
315
+	}
316
+
317
+
318
+
319
+	/**
320
+	 * loads core classes - must be singletons
321
+	 *
322
+	 * @param string $class_name - simple class name ie: session
323
+	 * @param mixed  $arguments
324
+	 * @param bool   $load_only
325
+	 * @return mixed
326
+	 * @throws EE_Error
327
+	 * @throws ReflectionException
328
+	 */
329
+	public function load_core($class_name, $arguments = array(), $load_only = false)
330
+	{
331
+		$core_paths = apply_filters(
332
+			'FHEE__EE_Registry__load_core__core_paths',
333
+			array(
334
+				EE_CORE,
335
+				EE_ADMIN,
336
+				EE_CPTS,
337
+				EE_CORE . 'data_migration_scripts' . DS,
338
+				EE_CORE . 'capabilities' . DS,
339
+				EE_CORE . 'request_stack' . DS,
340
+				EE_CORE . 'middleware' . DS,
341
+			)
342
+		);
343
+		// retrieve instantiated class
344
+		return $this->_load(
345
+			$core_paths,
346
+			'EE_',
347
+			$class_name,
348
+			'core',
349
+			$arguments,
350
+			false,
351
+			true,
352
+			$load_only
353
+		);
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * loads service classes
360
+	 *
361
+	 * @param string $class_name - simple class name ie: session
362
+	 * @param mixed  $arguments
363
+	 * @param bool   $load_only
364
+	 * @return mixed
365
+	 * @throws EE_Error
366
+	 * @throws ReflectionException
367
+	 */
368
+	public function load_service($class_name, $arguments = array(), $load_only = false)
369
+	{
370
+		$service_paths = apply_filters(
371
+			'FHEE__EE_Registry__load_service__service_paths',
372
+			array(
373
+				EE_CORE . 'services' . DS,
374
+			)
375
+		);
376
+		// retrieve instantiated class
377
+		return $this->_load(
378
+			$service_paths,
379
+			'EE_',
380
+			$class_name,
381
+			'class',
382
+			$arguments,
383
+			false,
384
+			true,
385
+			$load_only
386
+		);
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 * loads data_migration_scripts
393
+	 *
394
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
395
+	 * @param mixed  $arguments
396
+	 * @return EE_Data_Migration_Script_Base|mixed
397
+	 * @throws EE_Error
398
+	 * @throws ReflectionException
399
+	 */
400
+	public function load_dms($class_name, $arguments = array())
401
+	{
402
+		// retrieve instantiated class
403
+		return $this->_load(
404
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
405
+			'EE_DMS_',
406
+			$class_name,
407
+			'dms',
408
+			$arguments,
409
+			false,
410
+			false
411
+		);
412
+	}
413
+
414
+
415
+
416
+	/**
417
+	 * loads object creating classes - must be singletons
418
+	 *
419
+	 * @param string $class_name - simple class name ie: attendee
420
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
421
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
422
+	 *                           instantiate
423
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
424
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
425
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
426
+	 *                           (default)
427
+	 * @return EE_Base_Class | bool
428
+	 * @throws EE_Error
429
+	 * @throws ReflectionException
430
+	 */
431
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
432
+	{
433
+		$paths = apply_filters(
434
+			'FHEE__EE_Registry__load_class__paths', array(
435
+			EE_CORE,
436
+			EE_CLASSES,
437
+			EE_BUSINESS,
438
+		)
439
+		);
440
+		// retrieve instantiated class
441
+		return $this->_load(
442
+			$paths,
443
+			'EE_',
444
+			$class_name,
445
+			'class',
446
+			$arguments,
447
+			$from_db,
448
+			$cache,
449
+			$load_only
450
+		);
451
+	}
452
+
453
+
454
+
455
+	/**
456
+	 * loads helper classes - must be singletons
457
+	 *
458
+	 * @param string $class_name - simple class name ie: price
459
+	 * @param mixed  $arguments
460
+	 * @param bool   $load_only
461
+	 * @return EEH_Base | bool
462
+	 * @throws EE_Error
463
+	 * @throws ReflectionException
464
+	 */
465
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
466
+	{
467
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
468
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
469
+		// retrieve instantiated class
470
+		return $this->_load(
471
+			$helper_paths,
472
+			'EEH_',
473
+			$class_name,
474
+			'helper',
475
+			$arguments,
476
+			false,
477
+			true,
478
+			$load_only
479
+		);
480
+	}
481
+
482
+
483
+
484
+	/**
485
+	 * loads core classes - must be singletons
486
+	 *
487
+	 * @param string $class_name - simple class name ie: session
488
+	 * @param mixed  $arguments
489
+	 * @param bool   $load_only
490
+	 * @param bool   $cache      whether to cache the object or not.
491
+	 * @return mixed
492
+	 * @throws EE_Error
493
+	 * @throws ReflectionException
494
+	 */
495
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
496
+	{
497
+		$paths = array(
498
+			EE_LIBRARIES,
499
+			EE_LIBRARIES . 'messages' . DS,
500
+			EE_LIBRARIES . 'shortcodes' . DS,
501
+			EE_LIBRARIES . 'qtips' . DS,
502
+			EE_LIBRARIES . 'payment_methods' . DS,
503
+		);
504
+		// retrieve instantiated class
505
+		return $this->_load(
506
+			$paths,
507
+			'EE_',
508
+			$class_name,
509
+			'lib',
510
+			$arguments,
511
+			false,
512
+			$cache,
513
+			$load_only
514
+		);
515
+	}
516
+
517
+
518
+
519
+	/**
520
+	 * loads model classes - must be singletons
521
+	 *
522
+	 * @param string $class_name - simple class name ie: price
523
+	 * @param mixed  $arguments
524
+	 * @param bool   $load_only
525
+	 * @return EEM_Base | bool
526
+	 * @throws EE_Error
527
+	 * @throws ReflectionException
528
+	 */
529
+	public function load_model($class_name, $arguments = array(), $load_only = false)
530
+	{
531
+		$paths = apply_filters(
532
+			'FHEE__EE_Registry__load_model__paths', array(
533
+			EE_MODELS,
534
+			EE_CORE,
535
+		)
536
+		);
537
+		// retrieve instantiated class
538
+		return $this->_load(
539
+			$paths,
540
+			'EEM_',
541
+			$class_name,
542
+			'model',
543
+			$arguments,
544
+			false,
545
+			true,
546
+			$load_only
547
+		);
548
+	}
549
+
550
+
551
+
552
+	/**
553
+	 * loads model classes - must be singletons
554
+	 *
555
+	 * @param string $class_name - simple class name ie: price
556
+	 * @param mixed  $arguments
557
+	 * @param bool   $load_only
558
+	 * @return mixed | bool
559
+	 * @throws EE_Error
560
+	 * @throws ReflectionException
561
+	 */
562
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
563
+	{
564
+		$paths = array(
565
+			EE_MODELS . 'fields' . DS,
566
+			EE_MODELS . 'helpers' . DS,
567
+			EE_MODELS . 'relations' . DS,
568
+			EE_MODELS . 'strategies' . DS,
569
+		);
570
+		// retrieve instantiated class
571
+		return $this->_load(
572
+			$paths,
573
+			'EE_',
574
+			$class_name,
575
+			'',
576
+			$arguments,
577
+			false,
578
+			true,
579
+			$load_only
580
+		);
581
+	}
582
+
583
+
584
+
585
+	/**
586
+	 * Determines if $model_name is the name of an actual EE model.
587
+	 *
588
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
589
+	 * @return boolean
590
+	 */
591
+	public function is_model_name($model_name)
592
+	{
593
+		return isset($this->models[$model_name]);
594
+	}
595
+
596
+
597
+
598
+	/**
599
+	 * generic class loader
600
+	 *
601
+	 * @param string $path_to_file - directory path to file location, not including filename
602
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
603
+	 * @param string $type         - file type - core? class? helper? model?
604
+	 * @param mixed  $arguments
605
+	 * @param bool   $load_only
606
+	 * @return mixed
607
+	 * @throws EE_Error
608
+	 * @throws ReflectionException
609
+	 */
610
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
611
+	{
612
+		// retrieve instantiated class
613
+		return $this->_load(
614
+			$path_to_file,
615
+			'',
616
+			$file_name,
617
+			$type,
618
+			$arguments,
619
+			false,
620
+			true,
621
+			$load_only
622
+		);
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * @param string $path_to_file - directory path to file location, not including filename
629
+	 * @param string $class_name   - full class name  ie:  My_Class
630
+	 * @param string $type         - file type - core? class? helper? model?
631
+	 * @param mixed  $arguments
632
+	 * @param bool   $load_only
633
+	 * @return bool|EE_Addon|object
634
+	 * @throws EE_Error
635
+	 * @throws ReflectionException
636
+	 */
637
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
638
+	{
639
+		// retrieve instantiated class
640
+		return $this->_load(
641
+			$path_to_file,
642
+			'addon',
643
+			$class_name,
644
+			$type,
645
+			$arguments,
646
+			false,
647
+			true,
648
+			$load_only
649
+		);
650
+	}
651
+
652
+
653
+
654
+	/**
655
+	 * instantiates, caches, and automatically resolves dependencies
656
+	 * for classes that use a Fully Qualified Class Name.
657
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
658
+	 * then you need to use one of the existing load_*() methods
659
+	 * which can resolve the classname and filepath from the passed arguments
660
+	 *
661
+	 * @param bool|string $class_name   Fully Qualified Class Name
662
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
663
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
664
+	 * @param bool        $from_db      some classes are instantiated from the db
665
+	 *                                  and thus call a different method to instantiate
666
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
667
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
668
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
669
+	 *                                  object = class loaded and instantiated successfully.
670
+	 *                                  bool = fail or success when $load_only is true
671
+	 * @throws EE_Error
672
+	 * @throws ReflectionException
673
+	 */
674
+	public function create(
675
+		$class_name = false,
676
+		$arguments = array(),
677
+		$cache = false,
678
+		$from_db = false,
679
+		$load_only = false,
680
+		$addon = false
681
+	) {
682
+		$class_name = ltrim($class_name, '\\');
683
+		$class_name = $this->_dependency_map->get_alias($class_name);
684
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
685
+		// if a non-FQCN was passed, then verifyClassExists() might return an object
686
+		// or it could return null if the class just could not be found anywhere
687
+		if ($class_exists instanceof $class_name || $class_exists === null){
688
+			// either way, return the results
689
+			return $class_exists;
690
+		}
691
+		$class_name = $class_exists;
692
+		// if we're only loading the class and it already exists, then let's just return true immediately
693
+		if ($load_only) {
694
+			return true;
695
+		}
696
+		$addon = $addon
697
+			? 'addon'
698
+			: '';
699
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
700
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
701
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
702
+		if ($this->_cache_on && $cache && ! $load_only) {
703
+			// return object if it's already cached
704
+			$cached_class = $this->_get_cached_class($class_name, $addon);
705
+			if ($cached_class !== null) {
706
+				return $cached_class;
707
+			}
708
+		}
709
+		// obtain the loader method from the dependency map
710
+		$loader = $this->_dependency_map->class_loader($class_name);
711
+		// instantiate the requested object
712
+		if ($loader instanceof Closure) {
713
+			$class_obj = $loader($arguments);
714
+		} else if ($loader && method_exists($this, $loader)) {
715
+			$class_obj = $this->{$loader}($class_name, $arguments);
716
+		} else {
717
+			$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
718
+		}
719
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
720
+			// save it for later... kinda like gum  { : $
721
+			$this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
722
+		}
723
+		$this->_cache_on = true;
724
+		return $class_obj;
725
+	}
726
+
727
+
728
+
729
+	/**
730
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
731
+	 *
732
+	 * @param string $class_name
733
+	 * @param array  $arguments
734
+	 * @param int    $attempt
735
+	 * @return mixed
736
+	 */
737
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1) {
738
+		if (is_object($class_name) || class_exists($class_name)) {
739
+			return $class_name;
740
+		}
741
+		switch ($attempt) {
742
+			case 1:
743
+				// if it's a FQCN then maybe the class is registered with a preceding \
744
+				$class_name = strpos($class_name, '\\') !== false
745
+					? '\\' . ltrim($class_name, '\\')
746
+					: $class_name;
747
+				break;
748
+			case 2:
749
+				//
750
+				$loader = $this->_dependency_map->class_loader($class_name);
751
+				if ($loader && method_exists($this, $loader)) {
752
+					return $this->{$loader}($class_name, $arguments);
753
+				}
754
+				break;
755
+			case 3:
756
+			default;
757
+				return null;
758
+		}
759
+		$attempt++;
760
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
761
+	}
762
+
763
+
764
+
765
+	/**
766
+	 * instantiates, caches, and injects dependencies for classes
767
+	 *
768
+	 * @param array       $file_paths   an array of paths to folders to look in
769
+	 * @param string      $class_prefix EE  or EEM or... ???
770
+	 * @param bool|string $class_name   $class name
771
+	 * @param string      $type         file type - core? class? helper? model?
772
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
773
+	 * @param bool        $from_db      some classes are instantiated from the db
774
+	 *                                  and thus call a different method to instantiate
775
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
776
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
777
+	 * @return bool|null|object null = failure to load or instantiate class object.
778
+	 *                                  object = class loaded and instantiated successfully.
779
+	 *                                  bool = fail or success when $load_only is true
780
+	 * @throws EE_Error
781
+	 * @throws ReflectionException
782
+	 */
783
+	protected function _load(
784
+		$file_paths = array(),
785
+		$class_prefix = 'EE_',
786
+		$class_name = false,
787
+		$type = 'class',
788
+		$arguments = array(),
789
+		$from_db = false,
790
+		$cache = true,
791
+		$load_only = false
792
+	) {
793
+		$class_name = ltrim($class_name, '\\');
794
+		// strip php file extension
795
+		$class_name = str_replace('.php', '', trim($class_name));
796
+		// does the class have a prefix ?
797
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
798
+			// make sure $class_prefix is uppercase
799
+			$class_prefix = strtoupper(trim($class_prefix));
800
+			// add class prefix ONCE!!!
801
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
802
+		}
803
+		$class_name = $this->_dependency_map->get_alias($class_name);
804
+		$class_exists = class_exists($class_name, false);
805
+		// if we're only loading the class and it already exists, then let's just return true immediately
806
+		if ($load_only && $class_exists) {
807
+			return true;
808
+		}
809
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
810
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
811
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
812
+		if ($this->_cache_on && $cache && ! $load_only) {
813
+			// return object if it's already cached
814
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix);
815
+			if ($cached_class !== null) {
816
+				return $cached_class;
817
+			}
818
+		}
819
+		// if the class doesn't already exist.. then we need to try and find the file and load it
820
+		if (! $class_exists) {
821
+			// get full path to file
822
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
823
+			// load the file
824
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
825
+			// if loading failed, or we are only loading a file but NOT instantiating an object
826
+			if (! $loaded || $load_only) {
827
+				// return boolean if only loading, or null if an object was expected
828
+				return $load_only
829
+					? $loaded
830
+					: null;
831
+			}
832
+		}
833
+		// instantiate the requested object
834
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
835
+		if ($this->_cache_on && $cache) {
836
+			// save it for later... kinda like gum  { : $
837
+			$this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
838
+		}
839
+		$this->_cache_on = true;
840
+		return $class_obj;
841
+	}
842
+
843
+
844
+
845
+	/**
846
+	 * @param string $class_name
847
+	 * @param string $default have to specify something, but not anything that will conflict
848
+	 * @return mixed|string
849
+	 */
850
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
851
+	{
852
+		return isset($this->_class_abbreviations[$class_name])
853
+			? $this->_class_abbreviations[$class_name]
854
+			: $default;
855
+	}
856
+
857
+	/**
858
+	 * attempts to find a cached version of the requested class
859
+	 * by looking in the following places:
860
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
861
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
862
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
863
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
864
+	 *
865
+	 * @param string $class_name
866
+	 * @param string $class_prefix
867
+	 * @return mixed
868
+	 * @throws OutOfBoundsException
869
+	 */
870
+	protected function _get_cached_class($class_name, $class_prefix = '')
871
+	{
872
+		if ($class_name === 'EE_Registry') {
873
+			return $this;
874
+		}
875
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
876
+		$class_name = str_replace('\\', '_', $class_name);
877
+		// check if class has already been loaded, and return it if it has been
878
+		if (isset($this->{$class_abbreviation})) {
879
+			return $this->{$class_abbreviation};
880
+		}
881
+		if (isset ($this->{$class_name})) {
882
+			return $this->{$class_name};
883
+		}
884
+		if (isset ($this->LIB->{$class_name})) {
885
+			return $this->LIB->{$class_name};
886
+		}
887
+		if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
888
+			return $this->addons->{$class_name};
889
+		}
890
+		return null;
891
+	}
892
+
893
+
894
+
895
+	/**
896
+	 * removes a cached version of the requested class
897
+	 *
898
+	 * @param string  $class_name
899
+	 * @param boolean $addon
900
+	 * @return boolean
901
+	 * @throws OutOfBoundsException
902
+	 */
903
+	public function clear_cached_class($class_name, $addon = false)
904
+	{
905
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
906
+		$class_name = str_replace('\\', '_', $class_name);
907
+		// check if class has already been loaded, and return it if it has been
908
+		if (isset($this->{$class_abbreviation})) {
909
+			$this->{$class_abbreviation} = null;
910
+			return true;
911
+		}
912
+		if (isset($this->{$class_name})) {
913
+			$this->{$class_name} = null;
914
+			return true;
915
+		}
916
+		if (isset($this->LIB->{$class_name})) {
917
+			unset($this->LIB->{$class_name});
918
+			return true;
919
+		}
920
+		if ($addon && isset($this->addons->{$class_name})) {
921
+			unset($this->addons->{$class_name});
922
+			return true;
923
+		}
924
+		return false;
925
+	}
926
+
927
+
928
+
929
+	/**
930
+	 * attempts to find a full valid filepath for the requested class.
931
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
932
+	 * then returns that path if the target file has been found and is readable
933
+	 *
934
+	 * @param string $class_name
935
+	 * @param string $type
936
+	 * @param array  $file_paths
937
+	 * @return string | bool
938
+	 */
939
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
940
+	{
941
+		// make sure $file_paths is an array
942
+		$file_paths = is_array($file_paths)
943
+			? $file_paths
944
+			: array($file_paths);
945
+		// cycle thru paths
946
+		foreach ($file_paths as $key => $file_path) {
947
+			// convert all separators to proper DS, if no filepath, then use EE_CLASSES
948
+			$file_path = $file_path
949
+				? str_replace(array('/', '\\'), DS, $file_path)
950
+				: EE_CLASSES;
951
+			// prep file type
952
+			$type = ! empty($type)
953
+				? trim($type, '.') . '.'
954
+				: '';
955
+			// build full file path
956
+			$file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
957
+			//does the file exist and can be read ?
958
+			if (is_readable($file_paths[$key])) {
959
+				return $file_paths[$key];
960
+			}
961
+		}
962
+		return false;
963
+	}
964
+
965
+
966
+
967
+	/**
968
+	 * basically just performs a require_once()
969
+	 * but with some error handling
970
+	 *
971
+	 * @param  string $path
972
+	 * @param  string $class_name
973
+	 * @param  string $type
974
+	 * @param  array  $file_paths
975
+	 * @return bool
976
+	 * @throws EE_Error
977
+	 * @throws ReflectionException
978
+	 */
979
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
980
+	{
981
+		$this->resolve_legacy_class_parent($class_name);
982
+		// don't give up! you gotta...
983
+		try {
984
+			//does the file exist and can it be read ?
985
+			if (! $path) {
986
+				// just in case the file has already been autoloaded,
987
+				// but discrepancies in the naming schema are preventing it from
988
+				// being loaded via one of the EE_Registry::load_*() methods,
989
+				// then let's try one last hail mary before throwing an exception
990
+				// and call class_exists() again, but with autoloading turned ON
991
+				if(class_exists($class_name)) {
992
+					return true;
993
+				}
994
+				// so sorry, can't find the file
995
+				throw new EE_Error (
996
+					sprintf(
997
+						esc_html__(
998
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
999
+							'event_espresso'
1000
+						),
1001
+						trim($type, '.'),
1002
+						$class_name,
1003
+						'<br />' . implode(',<br />', $file_paths)
1004
+					)
1005
+				);
1006
+			}
1007
+			// get the file
1008
+			require_once($path);
1009
+			// if the class isn't already declared somewhere
1010
+			if (class_exists($class_name, false) === false) {
1011
+				// so sorry, not a class
1012
+				throw new EE_Error(
1013
+					sprintf(
1014
+						esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
1015
+						$type,
1016
+						$path,
1017
+						$class_name
1018
+					)
1019
+				);
1020
+			}
1021
+		} catch (EE_Error $e) {
1022
+			$e->get_error();
1023
+			return false;
1024
+		}
1025
+		return true;
1026
+	}
1027
+
1028
+
1029
+
1030
+	/**
1031
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1032
+	 * before their class declaration in order to ensure that the parent class was loaded.
1033
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1034
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1035
+	 *
1036
+	 * @param string $class_name
1037
+	 */
1038
+	protected function resolve_legacy_class_parent($class_name = '')
1039
+	{
1040
+		try {
1041
+			$legacy_parent_class_map = array(
1042
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
1043
+			);
1044
+			if(isset($legacy_parent_class_map[$class_name])) {
1045
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
1046
+			}
1047
+		} catch (Exception $exception) {
1048
+		}
1049
+	}
1050
+
1051
+
1052
+
1053
+	/**
1054
+	 * _create_object
1055
+	 * Attempts to instantiate the requested class via any of the
1056
+	 * commonly used instantiation methods employed throughout EE.
1057
+	 * The priority for instantiation is as follows:
1058
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1059
+	 *        - model objects via their 'new_instance_from_db' method
1060
+	 *        - model objects via their 'new_instance' method
1061
+	 *        - "singleton" classes" via their 'instance' method
1062
+	 *    - standard instantiable classes via their __constructor
1063
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1064
+	 * then the constructor for the requested class will be examined to determine
1065
+	 * if any dependencies exist, and if they can be injected.
1066
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1067
+	 *
1068
+	 * @param string $class_name
1069
+	 * @param array  $arguments
1070
+	 * @param string $type
1071
+	 * @param bool   $from_db
1072
+	 * @return null|object
1073
+	 * @throws EE_Error
1074
+	 * @throws ReflectionException
1075
+	 */
1076
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1077
+	{
1078
+		// create reflection
1079
+		$reflector = $this->get_ReflectionClass($class_name);
1080
+		// make sure arguments are an array
1081
+		$arguments = is_array($arguments)
1082
+			? $arguments
1083
+			: array($arguments);
1084
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1085
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1086
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1087
+			? $arguments
1088
+			: array($arguments);
1089
+		// attempt to inject dependencies ?
1090
+		if ($this->_dependency_map->has($class_name)) {
1091
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1092
+		}
1093
+		// instantiate the class if possible
1094
+		if ($reflector->isAbstract()) {
1095
+			// nothing to instantiate, loading file was enough
1096
+			// does not throw an exception so $instantiation_mode is unused
1097
+			// $instantiation_mode = "1) no constructor abstract class";
1098
+			return true;
1099
+		}
1100
+		if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1101
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1102
+			// $instantiation_mode = "2) no constructor but instantiable";
1103
+			return $reflector->newInstance();
1104
+		}
1105
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1106
+			// $instantiation_mode = "3) new_instance_from_db()";
1107
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1108
+		}
1109
+		if (method_exists($class_name, 'new_instance')) {
1110
+			// $instantiation_mode = "4) new_instance()";
1111
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1112
+		}
1113
+		if (method_exists($class_name, 'instance')) {
1114
+			// $instantiation_mode = "5) instance()";
1115
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1116
+		}
1117
+		if ($reflector->isInstantiable()) {
1118
+			// $instantiation_mode = "6) constructor";
1119
+			return $reflector->newInstanceArgs($arguments);
1120
+		}
1121
+		// heh ? something's not right !
1122
+		throw new EE_Error(
1123
+			sprintf(
1124
+				__('The %s file %s could not be instantiated.', 'event_espresso'),
1125
+				$type,
1126
+				$class_name
1127
+			)
1128
+		);
1129
+	}
1130
+
1131
+
1132
+
1133
+	/**
1134
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1135
+	 * @param array $array
1136
+	 * @return bool
1137
+	 */
1138
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1139
+	{
1140
+		return ! empty($array)
1141
+			? array_keys($array) === range(0, count($array) - 1)
1142
+			: true;
1143
+	}
1144
+
1145
+
1146
+
1147
+	/**
1148
+	 * getReflectionClass
1149
+	 * checks if a ReflectionClass object has already been generated for a class
1150
+	 * and returns that instead of creating a new one
1151
+	 *
1152
+	 * @param string $class_name
1153
+	 * @return ReflectionClass
1154
+	 * @throws ReflectionException
1155
+	 */
1156
+	public function get_ReflectionClass($class_name)
1157
+	{
1158
+		if (
1159
+			! isset($this->_reflectors[$class_name])
1160
+			|| ! $this->_reflectors[$class_name] instanceof ReflectionClass
1161
+		) {
1162
+			$this->_reflectors[$class_name] = new ReflectionClass($class_name);
1163
+		}
1164
+		return $this->_reflectors[$class_name];
1165
+	}
1166
+
1167
+
1168
+
1169
+	/**
1170
+	 * _resolve_dependencies
1171
+	 * examines the constructor for the requested class to determine
1172
+	 * if any dependencies exist, and if they can be injected.
1173
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1174
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1175
+	 * For example:
1176
+	 *        if attempting to load a class "Foo" with the following constructor:
1177
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1178
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1179
+	 *        but only IF they are NOT already present in the incoming arguments array,
1180
+	 *        and the correct classes can be loaded
1181
+	 *
1182
+	 * @param ReflectionClass $reflector
1183
+	 * @param string          $class_name
1184
+	 * @param array           $arguments
1185
+	 * @return array
1186
+	 * @throws EE_Error
1187
+	 * @throws ReflectionException
1188
+	 */
1189
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1190
+	{
1191
+		// let's examine the constructor
1192
+		$constructor = $reflector->getConstructor();
1193
+		// whu? huh? nothing?
1194
+		if (! $constructor) {
1195
+			return $arguments;
1196
+		}
1197
+		// get constructor parameters
1198
+		$params = $constructor->getParameters();
1199
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1200
+		$argument_keys = array_keys($arguments);
1201
+		// now loop thru all of the constructors expected parameters
1202
+		foreach ($params as $index => $param) {
1203
+			// is this a dependency for a specific class ?
1204
+			$param_class = $param->getClass()
1205
+				? $param->getClass()->name
1206
+				: null;
1207
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1208
+			$param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1209
+				? $this->_dependency_map->get_alias($param_class, $class_name)
1210
+				: $param_class;
1211
+			if (
1212
+				// param is not even a class
1213
+				$param_class === null
1214
+				// and something already exists in the incoming arguments for this param
1215
+				&& array_key_exists($index, $argument_keys)
1216
+				&& array_key_exists($argument_keys[$index], $arguments)
1217
+			) {
1218
+				// so let's skip this argument and move on to the next
1219
+				continue;
1220
+			}
1221
+			if (
1222
+				// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1223
+				$param_class !== null
1224
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1225
+				&& $arguments[$argument_keys[$index]] instanceof $param_class
1226
+			) {
1227
+				// skip this argument and move on to the next
1228
+				continue;
1229
+			}
1230
+			if (
1231
+				// parameter is type hinted as a class, and should be injected
1232
+				$param_class !== null
1233
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1234
+			) {
1235
+				$arguments = $this->_resolve_dependency(
1236
+					$class_name,
1237
+					$param_class,
1238
+					$arguments,
1239
+					$index,
1240
+					$argument_keys
1241
+				);
1242
+			} else {
1243
+				try {
1244
+					$arguments[$index] = $param->isDefaultValueAvailable()
1245
+						? $param->getDefaultValue()
1246
+						: null;
1247
+				} catch (ReflectionException $e) {
1248
+					throw new ReflectionException(
1249
+						sprintf(
1250
+							esc_html__('%1$s for parameter "$%2$s on classname "%3$s"', 'event_espresso'),
1251
+							$e->getMessage(),
1252
+							$param->getName(),
1253
+							$class_name
1254
+						)
1255
+					);
1256
+				}
1257
+			}
1258
+		}
1259
+		return $arguments;
1260
+	}
1261
+
1262
+
1263
+
1264
+	/**
1265
+	 * @param string $class_name
1266
+	 * @param string $param_class
1267
+	 * @param array  $arguments
1268
+	 * @param mixed  $index
1269
+	 * @param array  $argument_keys
1270
+	 * @return array
1271
+	 * @throws EE_Error
1272
+	 * @throws ReflectionException
1273
+	 * @throws InvalidArgumentException
1274
+	 * @throws InvalidInterfaceException
1275
+	 * @throws InvalidDataTypeException
1276
+	 */
1277
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1278
+	{
1279
+		$dependency = null;
1280
+		// should dependency be loaded from cache ?
1281
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1282
+			$class_name,
1283
+			$param_class
1284
+		);
1285
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1286
+		// we might have a dependency...
1287
+		// let's MAYBE try and find it in our cache if that's what's been requested
1288
+		$cached_class = $cache_on
1289
+			? $this->_get_cached_class($param_class)
1290
+			: null;
1291
+		// and grab it if it exists
1292
+		if ($cached_class instanceof $param_class) {
1293
+			$dependency = $cached_class;
1294
+		} else if ($param_class !== $class_name) {
1295
+			// obtain the loader method from the dependency map
1296
+			$loader = $this->_dependency_map->class_loader($param_class);
1297
+			// is loader a custom closure ?
1298
+			if ($loader instanceof Closure) {
1299
+				$dependency = $loader($arguments);
1300
+			} else {
1301
+				// set the cache on property for the recursive loading call
1302
+				$this->_cache_on = $cache_on;
1303
+				// if not, then let's try and load it via the registry
1304
+				if ($loader && method_exists($this, $loader)) {
1305
+					$dependency = $this->{$loader}($param_class);
1306
+				} else {
1307
+					$dependency = LoaderFactory::getLoader()->load(
1308
+						$param_class,
1309
+						array(),
1310
+						$cache_on
1311
+					);
1312
+				}
1313
+			}
1314
+		}
1315
+		// did we successfully find the correct dependency ?
1316
+		if ($dependency instanceof $param_class) {
1317
+			// then let's inject it into the incoming array of arguments at the correct location
1318
+			$arguments[$index] = $dependency;
1319
+		}
1320
+		return $arguments;
1321
+	}
1322
+
1323
+
1324
+
1325
+	/**
1326
+	 * _set_cached_class
1327
+	 * attempts to cache the instantiated class locally
1328
+	 * in one of the following places, in the following order:
1329
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1330
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1331
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1332
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1333
+	 *
1334
+	 * @param object $class_obj
1335
+	 * @param string $class_name
1336
+	 * @param string $class_prefix
1337
+	 * @param bool   $from_db
1338
+	 * @return void
1339
+	 * @throws OutOfBoundsException
1340
+	 */
1341
+	protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1342
+	{
1343
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1344
+			return;
1345
+		}
1346
+		// return newly instantiated class
1347
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1348
+		if ($class_abbreviation) {
1349
+			$this->{$class_abbreviation} = $class_obj;
1350
+			return;
1351
+		}
1352
+		$class_name = str_replace('\\', '_', $class_name);
1353
+		if (property_exists($this, $class_name)) {
1354
+			$this->{$class_name} = $class_obj;
1355
+			return;
1356
+		}
1357
+		if ($class_prefix === 'addon') {
1358
+			$this->addons->{$class_name} = $class_obj;
1359
+			return;
1360
+		}
1361
+		if (! $from_db) {
1362
+			$this->LIB->{$class_name} = $class_obj;
1363
+		}
1364
+	}
1365
+
1366
+
1367
+
1368
+	/**
1369
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1370
+	 *
1371
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1372
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1373
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1374
+	 * @param array  $arguments
1375
+	 * @return object
1376
+	 */
1377
+	public static function factory($classname, $arguments = array())
1378
+	{
1379
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1380
+		if ($loader instanceof Closure) {
1381
+			return $loader($arguments);
1382
+		}
1383
+		if (method_exists(self::instance(), $loader)) {
1384
+			return self::instance()->{$loader}($classname, $arguments);
1385
+		}
1386
+		return null;
1387
+	}
1388
+
1389
+
1390
+
1391
+	/**
1392
+	 * Gets the addon by its class name
1393
+	 *
1394
+	 * @param string $class_name
1395
+	 * @return EE_Addon
1396
+	 * @throws OutOfBoundsException
1397
+	 */
1398
+	public function getAddon($class_name)
1399
+	{
1400
+		$class_name = str_replace('\\', '_', $class_name);
1401
+		return $this->addons->{$class_name};
1402
+	}
1403
+
1404
+
1405
+	/**
1406
+	 * removes the addon from the internal cache
1407
+	 *
1408
+	 * @param string $class_name
1409
+	 * @return void
1410
+	 */
1411
+	public function removeAddon($class_name)
1412
+	{
1413
+		$class_name = str_replace('\\', '_', $class_name);
1414
+		unset($this->addons->{$class_name});
1415
+	}
1416
+
1417
+
1418
+
1419
+	/**
1420
+	 * Gets the addon by its name/slug (not classname. For that, just
1421
+	 * use the get_addon() method above
1422
+	 *
1423
+	 * @param string $name
1424
+	 * @return EE_Addon
1425
+	 */
1426
+	public function get_addon_by_name($name)
1427
+	{
1428
+		foreach ($this->addons as $addon) {
1429
+			if ($addon->name() === $name) {
1430
+				return $addon;
1431
+			}
1432
+		}
1433
+		return null;
1434
+	}
1435
+
1436
+
1437
+
1438
+	/**
1439
+	 * Gets an array of all the registered addons, where the keys are their names.
1440
+	 * (ie, what each returns for their name() function)
1441
+	 * They're already available on EE_Registry::instance()->addons as properties,
1442
+	 * where each property's name is the addon's classname,
1443
+	 * So if you just want to get the addon by classname,
1444
+	 * OR use the get_addon() method above.
1445
+	 * PLEASE  NOTE:
1446
+	 * addons with Fully Qualified Class Names
1447
+	 * have had the namespace separators converted to underscores,
1448
+	 * so a classname like Fully\Qualified\ClassName
1449
+	 * would have been converted to Fully_Qualified_ClassName
1450
+	 *
1451
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1452
+	 */
1453
+	public function get_addons_by_name()
1454
+	{
1455
+		$addons = array();
1456
+		foreach ($this->addons as $addon) {
1457
+			$addons[$addon->name()] = $addon;
1458
+		}
1459
+		return $addons;
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1465
+	 * a stale copy of it around
1466
+	 *
1467
+	 * @param string $model_name
1468
+	 * @return \EEM_Base
1469
+	 * @throws \EE_Error
1470
+	 */
1471
+	public function reset_model($model_name)
1472
+	{
1473
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1474
+			? "EEM_{$model_name}"
1475
+			: $model_name;
1476
+		if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1477
+			return null;
1478
+		}
1479
+		//get that model reset it and make sure we nuke the old reference to it
1480
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name
1481
+			&& is_callable(
1482
+				array($model_class_name, 'reset')
1483
+			)) {
1484
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1485
+		} else {
1486
+			throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1487
+		}
1488
+		return $this->LIB->{$model_class_name};
1489
+	}
1490
+
1491
+
1492
+
1493
+	/**
1494
+	 * Resets the registry.
1495
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1496
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1497
+	 * - $_dependency_map
1498
+	 * - $_class_abbreviations
1499
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1500
+	 * - $REQ:  Still on the same request so no need to change.
1501
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1502
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1503
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1504
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1505
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1506
+	 *             switch or on the restore.
1507
+	 * - $modules
1508
+	 * - $shortcodes
1509
+	 * - $widgets
1510
+	 *
1511
+	 * @param boolean $hard             [deprecated]
1512
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1513
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1514
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1515
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1516
+	 *                                  client
1517
+	 *                                  code instead can just change the model context to a different blog id if
1518
+	 *                                  necessary
1519
+	 * @return EE_Registry
1520
+	 * @throws EE_Error
1521
+	 * @throws ReflectionException
1522
+	 */
1523
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1524
+	{
1525
+		$instance = self::instance();
1526
+		$instance->_cache_on = true;
1527
+		// reset some "special" classes
1528
+		EEH_Activation::reset();
1529
+		$hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1530
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1531
+		$instance->CART = null;
1532
+		$instance->MRM = null;
1533
+		$instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1534
+		//messages reset
1535
+		EED_Messages::reset();
1536
+		//handle of objects cached on LIB
1537
+		foreach (array('LIB', 'modules') as $cache) {
1538
+			foreach ($instance->{$cache} as $class_name => $class) {
1539
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1540
+					unset($instance->{$cache}->{$class_name});
1541
+				}
1542
+			}
1543
+		}
1544
+		return $instance;
1545
+	}
1546
+
1547
+
1548
+
1549
+	/**
1550
+	 * if passed object implements ResettableInterface, then call it's reset() method
1551
+	 * if passed object implements InterminableInterface, then return false,
1552
+	 * to indicate that it should NOT be cleared from the Registry cache
1553
+	 *
1554
+	 * @param      $object
1555
+	 * @param bool $reset_models
1556
+	 * @return bool returns true if cached object should be unset
1557
+	 */
1558
+	private static function _reset_and_unset_object($object, $reset_models)
1559
+	{
1560
+		if (! is_object($object)) {
1561
+			// don't unset anything that's not an object
1562
+			return false;
1563
+		}
1564
+		if ($object instanceof EED_Module) {
1565
+			$object::reset();
1566
+			// don't unset modules
1567
+			return false;
1568
+		}
1569
+		if ($object instanceof ResettableInterface) {
1570
+			if ($object instanceof EEM_Base) {
1571
+				if ($reset_models) {
1572
+					$object->reset();
1573
+					return true;
1574
+				}
1575
+				return false;
1576
+			}
1577
+			$object->reset();
1578
+			return true;
1579
+		}
1580
+		if (! $object instanceof InterminableInterface) {
1581
+			return true;
1582
+		}
1583
+		return false;
1584
+	}
1585
+
1586
+
1587
+
1588
+	/**
1589
+	 * Gets all the custom post type models defined
1590
+	 *
1591
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1592
+	 */
1593
+	public function cpt_models()
1594
+	{
1595
+		$cpt_models = array();
1596
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1597
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1598
+				$cpt_models[$short_name] = $classname;
1599
+			}
1600
+		}
1601
+		return $cpt_models;
1602
+	}
1603
+
1604
+
1605
+
1606
+	/**
1607
+	 * @return \EE_Config
1608
+	 */
1609
+	public static function CFG()
1610
+	{
1611
+		return self::instance()->CFG;
1612
+	}
1613 1613
 
1614 1614
 
1615 1615
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_CPT.core.php 2 patches
Indentation   +1432 added lines, -1432 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\services\request\middleware\RecommendedVersions;
4 4
 
5 5
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
6
-    exit('No direct script access allowed');
6
+	exit('No direct script access allowed');
7 7
 }
8 8
 
9 9
 /**
@@ -28,470 +28,470 @@  discard block
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    /**
32
-     * This gets set in _setup_cpt
33
-     * It will contain the object for the custom post type.
34
-     *
35
-     * @var EE_CPT_Base
36
-     */
37
-    protected $_cpt_object;
38
-
39
-
40
-
41
-    /**
42
-     * a boolean flag to set whether the current route is a cpt route or not.
43
-     *
44
-     * @var bool
45
-     */
46
-    protected $_cpt_route = false;
47
-
48
-
49
-
50
-    /**
51
-     * This property allows cpt classes to define multiple routes as cpt routes.
52
-     * //in this array we define what the custom post type for this route is.
53
-     * array(
54
-     * 'route_name' => 'custom_post_type_slug'
55
-     * )
56
-     *
57
-     * @var array
58
-     */
59
-    protected $_cpt_routes = array();
60
-
31
+	/**
32
+	 * This gets set in _setup_cpt
33
+	 * It will contain the object for the custom post type.
34
+	 *
35
+	 * @var EE_CPT_Base
36
+	 */
37
+	protected $_cpt_object;
38
+
39
+
40
+
41
+	/**
42
+	 * a boolean flag to set whether the current route is a cpt route or not.
43
+	 *
44
+	 * @var bool
45
+	 */
46
+	protected $_cpt_route = false;
47
+
48
+
49
+
50
+	/**
51
+	 * This property allows cpt classes to define multiple routes as cpt routes.
52
+	 * //in this array we define what the custom post type for this route is.
53
+	 * array(
54
+	 * 'route_name' => 'custom_post_type_slug'
55
+	 * )
56
+	 *
57
+	 * @var array
58
+	 */
59
+	protected $_cpt_routes = array();
60
+
61 61
 
62 62
 
63
-    /**
64
-     * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
65
-     * in this format:
66
-     * array(
67
-     * 'post_type_slug' => 'edit_route'
68
-     * )
69
-     *
70
-     * @var array
71
-     */
72
-    protected $_cpt_edit_routes = array();
73
-
74
-
75
-
76
-    /**
77
-     * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
78
-     * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
79
-     * _cpt_model_names property should be in the following format: array(
80
-     * 'route_defined_by_action_param' => 'Model_Name')
81
-     *
82
-     * @var array $_cpt_model_names
83
-     */
84
-    protected $_cpt_model_names = array();
85
-
86
-
87
-    /**
88
-     * @var EE_CPT_Base
89
-     */
90
-    protected $_cpt_model_obj = false;
91
-
92
-
93
-
94
-    /**
95
-     * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
96
-     * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
97
-     * the _register_autosave_containers() method so that we don't override any other containers already registered.
98
-     * Registration of containers should be done before load_page_dependencies() is run.
99
-     *
100
-     * @var array()
101
-     */
102
-    protected $_autosave_containers = array();
103
-    protected $_autosave_fields = array();
104
-
105
-    /**
106
-     * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
107
-     * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
108
-     *
109
-     * @var array
110
-     */
111
-    protected $_pagenow_map;
112
-
113
-
114
-
115
-    /**
116
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
117
-     * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
118
-     * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
119
-     * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
120
-     * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
121
-     *
122
-     * @access protected
123
-     * @abstract
124
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
125
-     * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
126
-     * @return void
127
-     */
128
-    abstract protected function _insert_update_cpt_item($post_id, $post);
129
-
130
-
131
-
132
-    /**
133
-     * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
134
-     *
135
-     * @abstract
136
-     * @access public
137
-     * @param  string $post_id The ID of the cpt that was trashed
138
-     * @return void
139
-     */
140
-    abstract public function trash_cpt_item($post_id);
141
-
142
-
143
-
144
-    /**
145
-     * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
146
-     *
147
-     * @param  string $post_id theID of the cpt that was untrashed
148
-     * @return void
149
-     */
150
-    abstract public function restore_cpt_item($post_id);
151
-
152
-
153
-
154
-    /**
155
-     * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
156
-     * from the db
157
-     *
158
-     * @param  string $post_id the ID of the cpt that was deleted
159
-     * @return void
160
-     */
161
-    abstract public function delete_cpt_item($post_id);
162
-
163
-
164
-
165
-    /**
166
-     * Just utilizing the method EE_Admin exposes for doing things before page setup.
167
-     *
168
-     * @access protected
169
-     * @return void
170
-     */
171
-    protected function _before_page_setup()
172
-    {
173
-        $page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
174
-        $this->_cpt_routes = array_merge(array(
175
-            'create_new' => $this->page_slug,
176
-            'edit'       => $this->page_slug,
177
-            'trash'      => $this->page_slug,
178
-        ), $this->_cpt_routes);
179
-        //let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
180
-        $this->_cpt_object = isset($this->_req_data['action']) && isset($this->_cpt_routes[$this->_req_data['action']])
181
-            ? get_post_type_object($this->_cpt_routes[$this->_req_data['action']])
182
-            : get_post_type_object($page);
183
-        //tweak pagenow for page loading.
184
-        if ( ! $this->_pagenow_map) {
185
-            $this->_pagenow_map = array(
186
-                'create_new' => 'post-new.php',
187
-                'edit'       => 'post.php',
188
-                'trash'      => 'post.php',
189
-            );
190
-        }
191
-        add_action('current_screen', array($this, 'modify_pagenow'));
192
-        //TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
193
-        //get current page from autosave
194
-        $current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
195
-            ? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
196
-            : null;
197
-        $this->_current_page = isset($this->_req_data['current_page'])
198
-            ? $this->_req_data['current_page']
199
-            : $current_page;
200
-        //autosave... make sure its only for the correct page
201
-        //if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
202
-            //setup autosave ajax hook
203
-            //add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
204
-        //}
205
-    }
206
-
207
-
208
-
209
-    /**
210
-     * Simply ensure that we simulate the correct post route for cpt screens
211
-     *
212
-     * @param WP_Screen $current_screen
213
-     * @return void
214
-     */
215
-    public function modify_pagenow($current_screen)
216
-    {
217
-        global $pagenow, $hook_suffix;
218
-        //possibly reset pagenow.
219
-        if ( ! empty($this->_req_data['page'])
220
-             && $this->_req_data['page'] == $this->page_slug
221
-             && ! empty($this->_req_data['action'])
222
-             && isset($this->_pagenow_map[$this->_req_data['action']])
223
-        ) {
224
-            $pagenow = $this->_pagenow_map[$this->_req_data['action']];
225
-            $hook_suffix = $pagenow;
226
-        }
227
-    }
228
-
229
-
230
-
231
-    /**
232
-     * This method is used to register additional autosave containers to the _autosave_containers property.
233
-     *
234
-     * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
235
-     *       automatically register the id for the post metabox as a container.
236
-     * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
237
-     *                    you would send along the id of a metabox container.
238
-     * @return void
239
-     */
240
-    protected function _register_autosave_containers($ids)
241
-    {
242
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array)$ids);
243
-    }
244
-
245
-
246
-
247
-    /**
248
-     * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
249
-     * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
250
-     */
251
-    protected function _set_autosave_containers()
252
-    {
253
-        global $wp_meta_boxes;
254
-        $containers = array();
255
-        if (empty($wp_meta_boxes)) {
256
-            return;
257
-        }
258
-        $current_metaboxes = isset($wp_meta_boxes[$this->page_slug]) ? $wp_meta_boxes[$this->page_slug] : array();
259
-        foreach ($current_metaboxes as $box_context) {
260
-            foreach ($box_context as $box_details) {
261
-                foreach ($box_details as $box) {
262
-                    if (
263
-                        is_array($box['callback'])
264
-                        && (
265
-                            $box['callback'][0] instanceof EE_Admin_Page
266
-                            || $box['callback'][0] instanceof EE_Admin_Hooks
267
-                        )
268
-                    ) {
269
-                        $containers[] = $box['id'];
270
-                    }
271
-                }
272
-            }
273
-        }
274
-        $this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
275
-        //add hidden inputs container
276
-        $this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
277
-    }
278
-
279
-
280
-
281
-    protected function _load_autosave_scripts_styles()
282
-    {
283
-        /*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
63
+	/**
64
+	 * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
65
+	 * in this format:
66
+	 * array(
67
+	 * 'post_type_slug' => 'edit_route'
68
+	 * )
69
+	 *
70
+	 * @var array
71
+	 */
72
+	protected $_cpt_edit_routes = array();
73
+
74
+
75
+
76
+	/**
77
+	 * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
78
+	 * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
79
+	 * _cpt_model_names property should be in the following format: array(
80
+	 * 'route_defined_by_action_param' => 'Model_Name')
81
+	 *
82
+	 * @var array $_cpt_model_names
83
+	 */
84
+	protected $_cpt_model_names = array();
85
+
86
+
87
+	/**
88
+	 * @var EE_CPT_Base
89
+	 */
90
+	protected $_cpt_model_obj = false;
91
+
92
+
93
+
94
+	/**
95
+	 * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
96
+	 * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
97
+	 * the _register_autosave_containers() method so that we don't override any other containers already registered.
98
+	 * Registration of containers should be done before load_page_dependencies() is run.
99
+	 *
100
+	 * @var array()
101
+	 */
102
+	protected $_autosave_containers = array();
103
+	protected $_autosave_fields = array();
104
+
105
+	/**
106
+	 * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
107
+	 * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
108
+	 *
109
+	 * @var array
110
+	 */
111
+	protected $_pagenow_map;
112
+
113
+
114
+
115
+	/**
116
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
117
+	 * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
118
+	 * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
119
+	 * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
120
+	 * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
121
+	 *
122
+	 * @access protected
123
+	 * @abstract
124
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
125
+	 * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
126
+	 * @return void
127
+	 */
128
+	abstract protected function _insert_update_cpt_item($post_id, $post);
129
+
130
+
131
+
132
+	/**
133
+	 * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
134
+	 *
135
+	 * @abstract
136
+	 * @access public
137
+	 * @param  string $post_id The ID of the cpt that was trashed
138
+	 * @return void
139
+	 */
140
+	abstract public function trash_cpt_item($post_id);
141
+
142
+
143
+
144
+	/**
145
+	 * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
146
+	 *
147
+	 * @param  string $post_id theID of the cpt that was untrashed
148
+	 * @return void
149
+	 */
150
+	abstract public function restore_cpt_item($post_id);
151
+
152
+
153
+
154
+	/**
155
+	 * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
156
+	 * from the db
157
+	 *
158
+	 * @param  string $post_id the ID of the cpt that was deleted
159
+	 * @return void
160
+	 */
161
+	abstract public function delete_cpt_item($post_id);
162
+
163
+
164
+
165
+	/**
166
+	 * Just utilizing the method EE_Admin exposes for doing things before page setup.
167
+	 *
168
+	 * @access protected
169
+	 * @return void
170
+	 */
171
+	protected function _before_page_setup()
172
+	{
173
+		$page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
174
+		$this->_cpt_routes = array_merge(array(
175
+			'create_new' => $this->page_slug,
176
+			'edit'       => $this->page_slug,
177
+			'trash'      => $this->page_slug,
178
+		), $this->_cpt_routes);
179
+		//let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
180
+		$this->_cpt_object = isset($this->_req_data['action']) && isset($this->_cpt_routes[$this->_req_data['action']])
181
+			? get_post_type_object($this->_cpt_routes[$this->_req_data['action']])
182
+			: get_post_type_object($page);
183
+		//tweak pagenow for page loading.
184
+		if ( ! $this->_pagenow_map) {
185
+			$this->_pagenow_map = array(
186
+				'create_new' => 'post-new.php',
187
+				'edit'       => 'post.php',
188
+				'trash'      => 'post.php',
189
+			);
190
+		}
191
+		add_action('current_screen', array($this, 'modify_pagenow'));
192
+		//TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
193
+		//get current page from autosave
194
+		$current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
195
+			? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
196
+			: null;
197
+		$this->_current_page = isset($this->_req_data['current_page'])
198
+			? $this->_req_data['current_page']
199
+			: $current_page;
200
+		//autosave... make sure its only for the correct page
201
+		//if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
202
+			//setup autosave ajax hook
203
+			//add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
204
+		//}
205
+	}
206
+
207
+
208
+
209
+	/**
210
+	 * Simply ensure that we simulate the correct post route for cpt screens
211
+	 *
212
+	 * @param WP_Screen $current_screen
213
+	 * @return void
214
+	 */
215
+	public function modify_pagenow($current_screen)
216
+	{
217
+		global $pagenow, $hook_suffix;
218
+		//possibly reset pagenow.
219
+		if ( ! empty($this->_req_data['page'])
220
+			 && $this->_req_data['page'] == $this->page_slug
221
+			 && ! empty($this->_req_data['action'])
222
+			 && isset($this->_pagenow_map[$this->_req_data['action']])
223
+		) {
224
+			$pagenow = $this->_pagenow_map[$this->_req_data['action']];
225
+			$hook_suffix = $pagenow;
226
+		}
227
+	}
228
+
229
+
230
+
231
+	/**
232
+	 * This method is used to register additional autosave containers to the _autosave_containers property.
233
+	 *
234
+	 * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
235
+	 *       automatically register the id for the post metabox as a container.
236
+	 * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
237
+	 *                    you would send along the id of a metabox container.
238
+	 * @return void
239
+	 */
240
+	protected function _register_autosave_containers($ids)
241
+	{
242
+		$this->_autosave_containers = array_merge($this->_autosave_fields, (array)$ids);
243
+	}
244
+
245
+
246
+
247
+	/**
248
+	 * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
249
+	 * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
250
+	 */
251
+	protected function _set_autosave_containers()
252
+	{
253
+		global $wp_meta_boxes;
254
+		$containers = array();
255
+		if (empty($wp_meta_boxes)) {
256
+			return;
257
+		}
258
+		$current_metaboxes = isset($wp_meta_boxes[$this->page_slug]) ? $wp_meta_boxes[$this->page_slug] : array();
259
+		foreach ($current_metaboxes as $box_context) {
260
+			foreach ($box_context as $box_details) {
261
+				foreach ($box_details as $box) {
262
+					if (
263
+						is_array($box['callback'])
264
+						&& (
265
+							$box['callback'][0] instanceof EE_Admin_Page
266
+							|| $box['callback'][0] instanceof EE_Admin_Hooks
267
+						)
268
+					) {
269
+						$containers[] = $box['id'];
270
+					}
271
+				}
272
+			}
273
+		}
274
+		$this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
275
+		//add hidden inputs container
276
+		$this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
277
+	}
278
+
279
+
280
+
281
+	protected function _load_autosave_scripts_styles()
282
+	{
283
+		/*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
284 284
         wp_enqueue_script('cpt-autosave');/**/ //todo re-enable when we start doing autosave again in 4.2
285 285
 
286
-        //filter _autosave_containers
287
-        $containers = apply_filters('FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
288
-            $this->_autosave_containers, $this);
289
-        $containers = apply_filters('FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
290
-            $containers, $this);
291
-
292
-        wp_localize_script('event_editor_js', 'EE_AUTOSAVE_IDS',
293
-            $containers); //todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
294
-
295
-        $unsaved_data_msg = array(
296
-            'eventmsg'     => sprintf(__("The changes you made to this %s will be lost if you navigate away from this page.",
297
-                'event_espresso'), $this->_cpt_object->labels->singular_name),
298
-            'inputChanged' => 0,
299
-        );
300
-        wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
301
-    }
302
-
303
-
304
-
305
-    public function load_page_dependencies()
306
-    {
307
-        try {
308
-            $this->_load_page_dependencies();
309
-        } catch (EE_Error $e) {
310
-            $e->get_error();
311
-        }
312
-    }
313
-
314
-
315
-
316
-    /**
317
-     * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
318
-     *
319
-     * @access protected
320
-     * @return void
321
-     */
322
-    protected function _load_page_dependencies()
323
-    {
324
-        //we only add stuff if this is a cpt_route!
325
-        if ( ! $this->_cpt_route) {
326
-            parent::_load_page_dependencies();
327
-            return;
328
-        }
329
-        // now let's do some automatic filters into the wp_system
330
-        // and we'll check to make sure the CHILD class
331
-        // automatically has the required methods in place.
332
-        // the following filters are for setting all the redirects
333
-        // on DEFAULT WP custom post type actions
334
-        // let's add a hidden input to the post-edit form
335
-        // so we know when we have to trigger our custom redirects!
336
-        // Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
337
-        add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
338
-        // inject our Admin page nav tabs...
339
-        // let's make sure the nav tabs are set if they aren't already
340
-        // if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
341
-        add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
342
-        // modify the post_updated messages array
343
-        add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
344
-        // add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
345
-        // cpts use the same format for shortlinks as posts!
346
-        add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
347
-        // This basically allows us to change the title of the "publish" metabox area
348
-        // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
349
-        if ( ! empty($this->_labels['publishbox'])) {
350
-            $box_label = is_array($this->_labels['publishbox'])
351
-                         && isset($this->_labels['publishbox'][$this->_req_action])
352
-                    ? $this->_labels['publishbox'][$this->_req_action]
353
-                    : $this->_labels['publishbox'];
354
-            add_meta_box(
355
-                'submitdiv',
356
-                $box_label,
357
-                'post_submit_meta_box',
358
-                $this->_cpt_routes[$this->_req_action],
359
-                'side',
360
-                'core'
361
-            );
362
-        }
363
-        //let's add page_templates metabox if this cpt added support for it.
364
-        if ($this->_supports_page_templates($this->_cpt_object->name)) {
365
-            add_meta_box(
366
-                'page_templates',
367
-                __('Page Template', 'event_espresso'),
368
-                array($this, 'page_template_meta_box'),
369
-                $this->_cpt_routes[$this->_req_action],
370
-                'side',
371
-                'default'
372
-            );
373
-        }
374
-        //this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
375
-        if (method_exists($this, 'extra_permalink_field_buttons')) {
376
-            add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
377
-        }
378
-        //add preview button
379
-        add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
380
-        //insert our own post_stati dropdown
381
-        add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
382
-        //This allows adding additional information to the publish post submitbox on the wp post edit form
383
-        if (method_exists($this, 'extra_misc_actions_publish_box')) {
384
-            add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
385
-        }
386
-        // This allows for adding additional stuff after the title field on the wp post edit form.
387
-        // This is also before the wp_editor for post description field.
388
-        if (method_exists($this, 'edit_form_after_title')) {
389
-            add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
390
-        }
391
-        /**
392
-         * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
393
-         */
394
-        add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
395
-        parent::_load_page_dependencies();
396
-        // notice we are ALSO going to load the pagenow hook set for this route
397
-        // (see _before_page_setup for the reset of the pagenow global ).
398
-        // This is for any plugins that are doing things properly
399
-        // and hooking into the load page hook for core wp cpt routes.
400
-        global $pagenow;
401
-        do_action('load-' . $pagenow);
402
-        $this->modify_current_screen();
403
-        add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
404
-        //we route REALLY early.
405
-        try {
406
-            $this->_route_admin_request();
407
-        } catch (EE_Error $e) {
408
-            $e->get_error();
409
-        }
410
-    }
411
-
412
-
413
-
414
-    /**
415
-     * Since we don't want users going to default core wp routes, this will check any wp urls run through the
416
-     * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
417
-     * route instead.
418
-     *
419
-     * @param string $good_protocol_url The escaped url.
420
-     * @param string $original_url      The original url.
421
-     * @param string $_context          The context sent to the esc_url method.
422
-     * @return string possibly a new url for our route.
423
-     */
424
-    public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
425
-    {
426
-        $routes_to_match = array(
427
-            0 => array(
428
-                'edit.php?post_type=espresso_attendees',
429
-                'admin.php?page=espresso_registrations&action=contact_list',
430
-            ),
431
-            1 => array(
432
-                'edit.php?post_type=' . $this->_cpt_object->name,
433
-                'admin.php?page=' . $this->_cpt_object->name,
434
-            ),
435
-        );
436
-        foreach ($routes_to_match as $route_matches) {
437
-            if (strpos($good_protocol_url, $route_matches[0]) !== false) {
438
-                return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
439
-            }
440
-        }
441
-        return $good_protocol_url;
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     * Determine whether the current cpt supports page templates or not.
448
-     *
449
-     * @since %VER%
450
-     * @param string $cpt_name The cpt slug we're checking on.
451
-     * @return bool True supported, false not.
452
-     */
453
-    private function _supports_page_templates($cpt_name)
454
-    {
455
-
456
-        $cpt_args = EE_Register_CPTs::get_CPTs();
457
-        $cpt_args = isset($cpt_args[$cpt_name]) ? $cpt_args[$cpt_name]['args'] : array();
458
-        $cpt_has_support = ! empty($cpt_args['page_templates']);
459
-
460
-        //if the installed version of WP is > 4.7 we do some additional checks.
461
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
462
-            $post_templates = wp_get_theme()->get_post_templates();
463
-            //if there are $post_templates for this cpt, then we return false for this method because
464
-            //that means we aren't going to load our page template manager and leave that up to the native
465
-            //cpt template manager.
466
-            $cpt_has_support = ! isset($post_templates[$cpt_name]) ? $cpt_has_support : false;
467
-        }
468
-
469
-        return $cpt_has_support;
470
-    }
471
-
472
-
473
-    /**
474
-     * Callback for the page_templates metabox selector.
475
-     *
476
-     * @since %VER%
477
-     * @return void
478
-     */
479
-    public function page_template_meta_box()
480
-    {
481
-        global $post;
482
-        $template = '';
483
-
484
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
485
-            $page_template_count = count(get_page_templates());
486
-        } else {
487
-            $page_template_count = count(get_page_templates($post));
488
-        };
489
-
490
-        if ($page_template_count) {
491
-            $page_template = get_post_meta($post->ID, '_wp_page_template', true);
492
-            $template      = ! empty($page_template) ? $page_template : '';
493
-        }
494
-        ?>
286
+		//filter _autosave_containers
287
+		$containers = apply_filters('FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
288
+			$this->_autosave_containers, $this);
289
+		$containers = apply_filters('FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
290
+			$containers, $this);
291
+
292
+		wp_localize_script('event_editor_js', 'EE_AUTOSAVE_IDS',
293
+			$containers); //todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
294
+
295
+		$unsaved_data_msg = array(
296
+			'eventmsg'     => sprintf(__("The changes you made to this %s will be lost if you navigate away from this page.",
297
+				'event_espresso'), $this->_cpt_object->labels->singular_name),
298
+			'inputChanged' => 0,
299
+		);
300
+		wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
301
+	}
302
+
303
+
304
+
305
+	public function load_page_dependencies()
306
+	{
307
+		try {
308
+			$this->_load_page_dependencies();
309
+		} catch (EE_Error $e) {
310
+			$e->get_error();
311
+		}
312
+	}
313
+
314
+
315
+
316
+	/**
317
+	 * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
318
+	 *
319
+	 * @access protected
320
+	 * @return void
321
+	 */
322
+	protected function _load_page_dependencies()
323
+	{
324
+		//we only add stuff if this is a cpt_route!
325
+		if ( ! $this->_cpt_route) {
326
+			parent::_load_page_dependencies();
327
+			return;
328
+		}
329
+		// now let's do some automatic filters into the wp_system
330
+		// and we'll check to make sure the CHILD class
331
+		// automatically has the required methods in place.
332
+		// the following filters are for setting all the redirects
333
+		// on DEFAULT WP custom post type actions
334
+		// let's add a hidden input to the post-edit form
335
+		// so we know when we have to trigger our custom redirects!
336
+		// Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
337
+		add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
338
+		// inject our Admin page nav tabs...
339
+		// let's make sure the nav tabs are set if they aren't already
340
+		// if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
341
+		add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
342
+		// modify the post_updated messages array
343
+		add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
344
+		// add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
345
+		// cpts use the same format for shortlinks as posts!
346
+		add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
347
+		// This basically allows us to change the title of the "publish" metabox area
348
+		// on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
349
+		if ( ! empty($this->_labels['publishbox'])) {
350
+			$box_label = is_array($this->_labels['publishbox'])
351
+						 && isset($this->_labels['publishbox'][$this->_req_action])
352
+					? $this->_labels['publishbox'][$this->_req_action]
353
+					: $this->_labels['publishbox'];
354
+			add_meta_box(
355
+				'submitdiv',
356
+				$box_label,
357
+				'post_submit_meta_box',
358
+				$this->_cpt_routes[$this->_req_action],
359
+				'side',
360
+				'core'
361
+			);
362
+		}
363
+		//let's add page_templates metabox if this cpt added support for it.
364
+		if ($this->_supports_page_templates($this->_cpt_object->name)) {
365
+			add_meta_box(
366
+				'page_templates',
367
+				__('Page Template', 'event_espresso'),
368
+				array($this, 'page_template_meta_box'),
369
+				$this->_cpt_routes[$this->_req_action],
370
+				'side',
371
+				'default'
372
+			);
373
+		}
374
+		//this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
375
+		if (method_exists($this, 'extra_permalink_field_buttons')) {
376
+			add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
377
+		}
378
+		//add preview button
379
+		add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
380
+		//insert our own post_stati dropdown
381
+		add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
382
+		//This allows adding additional information to the publish post submitbox on the wp post edit form
383
+		if (method_exists($this, 'extra_misc_actions_publish_box')) {
384
+			add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
385
+		}
386
+		// This allows for adding additional stuff after the title field on the wp post edit form.
387
+		// This is also before the wp_editor for post description field.
388
+		if (method_exists($this, 'edit_form_after_title')) {
389
+			add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
390
+		}
391
+		/**
392
+		 * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
393
+		 */
394
+		add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
395
+		parent::_load_page_dependencies();
396
+		// notice we are ALSO going to load the pagenow hook set for this route
397
+		// (see _before_page_setup for the reset of the pagenow global ).
398
+		// This is for any plugins that are doing things properly
399
+		// and hooking into the load page hook for core wp cpt routes.
400
+		global $pagenow;
401
+		do_action('load-' . $pagenow);
402
+		$this->modify_current_screen();
403
+		add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
404
+		//we route REALLY early.
405
+		try {
406
+			$this->_route_admin_request();
407
+		} catch (EE_Error $e) {
408
+			$e->get_error();
409
+		}
410
+	}
411
+
412
+
413
+
414
+	/**
415
+	 * Since we don't want users going to default core wp routes, this will check any wp urls run through the
416
+	 * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
417
+	 * route instead.
418
+	 *
419
+	 * @param string $good_protocol_url The escaped url.
420
+	 * @param string $original_url      The original url.
421
+	 * @param string $_context          The context sent to the esc_url method.
422
+	 * @return string possibly a new url for our route.
423
+	 */
424
+	public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
425
+	{
426
+		$routes_to_match = array(
427
+			0 => array(
428
+				'edit.php?post_type=espresso_attendees',
429
+				'admin.php?page=espresso_registrations&action=contact_list',
430
+			),
431
+			1 => array(
432
+				'edit.php?post_type=' . $this->_cpt_object->name,
433
+				'admin.php?page=' . $this->_cpt_object->name,
434
+			),
435
+		);
436
+		foreach ($routes_to_match as $route_matches) {
437
+			if (strpos($good_protocol_url, $route_matches[0]) !== false) {
438
+				return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
439
+			}
440
+		}
441
+		return $good_protocol_url;
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 * Determine whether the current cpt supports page templates or not.
448
+	 *
449
+	 * @since %VER%
450
+	 * @param string $cpt_name The cpt slug we're checking on.
451
+	 * @return bool True supported, false not.
452
+	 */
453
+	private function _supports_page_templates($cpt_name)
454
+	{
455
+
456
+		$cpt_args = EE_Register_CPTs::get_CPTs();
457
+		$cpt_args = isset($cpt_args[$cpt_name]) ? $cpt_args[$cpt_name]['args'] : array();
458
+		$cpt_has_support = ! empty($cpt_args['page_templates']);
459
+
460
+		//if the installed version of WP is > 4.7 we do some additional checks.
461
+		if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
462
+			$post_templates = wp_get_theme()->get_post_templates();
463
+			//if there are $post_templates for this cpt, then we return false for this method because
464
+			//that means we aren't going to load our page template manager and leave that up to the native
465
+			//cpt template manager.
466
+			$cpt_has_support = ! isset($post_templates[$cpt_name]) ? $cpt_has_support : false;
467
+		}
468
+
469
+		return $cpt_has_support;
470
+	}
471
+
472
+
473
+	/**
474
+	 * Callback for the page_templates metabox selector.
475
+	 *
476
+	 * @since %VER%
477
+	 * @return void
478
+	 */
479
+	public function page_template_meta_box()
480
+	{
481
+		global $post;
482
+		$template = '';
483
+
484
+		if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
485
+			$page_template_count = count(get_page_templates());
486
+		} else {
487
+			$page_template_count = count(get_page_templates($post));
488
+		};
489
+
490
+		if ($page_template_count) {
491
+			$page_template = get_post_meta($post->ID, '_wp_page_template', true);
492
+			$template      = ! empty($page_template) ? $page_template : '';
493
+		}
494
+		?>
495 495
         <p><strong><?php _e('Template') ?></strong></p>
496 496
         <label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select
497 497
             name="page_template" id="page_template">
@@ -499,450 +499,450 @@  discard block
 block discarded – undo
499 499
         <?php page_template_dropdown($template); ?>
500 500
     </select>
501 501
         <?php
502
-    }
503
-
504
-
505
-
506
-    /**
507
-     * if this post is a draft or scheduled post then we provide a preview button for user to click
508
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
509
-     *
510
-     * @param  string $return    the current html
511
-     * @param  int    $id        the post id for the page
512
-     * @param  string $new_title What the title is
513
-     * @param  string $new_slug  what the slug is
514
-     * @return string            The new html string for the permalink area
515
-     */
516
-    public function preview_button_html($return, $id, $new_title, $new_slug)
517
-    {
518
-        $post = get_post($id);
519
-        if ('publish' !== get_post_status($post)) {
520
-            //include shims for the `get_preview_post_link` function
521
-            require_once( EE_CORE . 'wordpress-shims.php' );
522
-            $return .= '<span_id="view-post-btn"><a target="_blank" href="'
523
-                       . get_preview_post_link($id)
524
-                       . '" class="button button-small">'
525
-                       . __('Preview', 'event_espresso')
526
-                       . '</a></span>'
527
-                       . "\n";
528
-        }
529
-        return $return;
530
-    }
531
-
532
-
533
-
534
-    /**
535
-     * add our custom post stati dropdown on the wp post page for this cpt
536
-     *
537
-     * @return void
538
-     */
539
-    public function custom_post_stati_dropdown()
540
-    {
541
-
542
-        $statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
543
-        $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
544
-            ? $statuses[$this->_cpt_model_obj->status()]
545
-            : '';
546
-        $template_args    = array(
547
-            'cur_status'            => $this->_cpt_model_obj->status(),
548
-            'statuses'              => $statuses,
549
-            'cur_status_label'      => $cur_status_label,
550
-            'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
551
-        );
552
-        //we'll add a trash post status (WP doesn't add one for some reason)
553
-        if ($this->_cpt_model_obj->status() === 'trash') {
554
-            $template_args['cur_status_label'] = __('Trashed', 'event_espresso');
555
-            $statuses['trash']                 = __('Trashed', 'event_espresso');
556
-            $template_args['statuses']         = $statuses;
557
-        }
558
-
559
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
560
-        EEH_Template::display_template($template, $template_args);
561
-    }
562
-
563
-
564
-
565
-    public function setup_autosave_hooks()
566
-    {
567
-        $this->_set_autosave_containers();
568
-        $this->_load_autosave_scripts_styles();
569
-    }
570
-
571
-
572
-
573
-    /**
574
-     * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
575
-     * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
576
-     * for the nonce in here, but then this method looks for two things:
577
-     * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
578
-     * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
579
-     * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
580
-     * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
581
-     * template args.
582
-     *    1. $template_args['error'] = IF there is an error you can add the message in here.
583
-     *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
584
-     *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
585
-     *    $this->_template_args['data']['items'] = array(
586
-     *        'event-datetime-ids' => '1,2,3';
587
-     *    );
588
-     *    Keep in mind the following things:
589
-     *    - "where" index is for the input with the id as that string.
590
-     *    - "what" index is what will be used for the value of that input.
591
-     *
592
-     * @return void
593
-     */
594
-    public function do_extra_autosave_stuff()
595
-    {
596
-        //next let's check for the autosave nonce (we'll use _verify_nonce )
597
-        $nonce = isset($this->_req_data['autosavenonce'])
598
-                ? $this->_req_data['autosavenonce']
599
-                : null;
600
-        $this->_verify_nonce($nonce, 'autosave');
601
-        //make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
602
-        if ( ! defined('DOING_AUTOSAVE')) {
603
-            define('DOING_AUTOSAVE', true);
604
-        }
605
-        //if we made it here then the nonce checked out.  Let's run our methods and actions
606
-        $autosave = "_ee_autosave_{$this->_current_view}";
607
-        if (method_exists($this, $autosave)) {
608
-            $this->$autosave();
609
-        } else {
610
-            $this->_template_args['success'] = true;
611
-        }
612
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
613
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
614
-        //now let's return json
615
-        $this->_return_json();
616
-    }
617
-
618
-
619
-
620
-    /**
621
-     * This takes care of setting up default routes and pages that utilize the core WP admin pages.
622
-     * Child classes can override the defaults (in cases for adding metaboxes etc.)
623
-     * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
624
-     *
625
-     * @access protected
626
-     * @throws EE_Error
627
-     * @return void
628
-     */
629
-    protected function _extend_page_config_for_cpt()
630
-    {
631
-        //before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
632
-        if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
633
-            return;
634
-        }
635
-        //set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
636
-        if ( ! empty($this->_cpt_object)) {
637
-            $this->_page_routes = array_merge(array(
638
-                'create_new' => '_create_new_cpt_item',
639
-                'edit'       => '_edit_cpt_item',
640
-            ), $this->_page_routes);
641
-            $this->_page_config = array_merge(array(
642
-                'create_new' => array(
643
-                    'nav'           => array(
644
-                        'label' => $this->_cpt_object->labels->add_new_item,
645
-                        'order' => 5,
646
-                    ),
647
-                    'require_nonce' => false,
648
-                ),
649
-                'edit'       => array(
650
-                    'nav'           => array(
651
-                        'label'      => $this->_cpt_object->labels->edit_item,
652
-                        'order'      => 5,
653
-                        'persistent' => false,
654
-                        'url'        => '',
655
-                    ),
656
-                    'require_nonce' => false,
657
-                ),
658
-            ),
659
-                $this->_page_config
660
-            );
661
-        }
662
-        //load the next section only if this is a matching cpt route as set in the cpt routes array.
663
-        if ( ! isset($this->_cpt_routes[$this->_req_action])) {
664
-            return;
665
-        }
666
-        $this->_cpt_route = isset($this->_cpt_routes[$this->_req_action]) ? true : false;
667
-        //add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
668
-        if (empty($this->_cpt_object)) {
669
-            $msg = sprintf(__('This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).'),
670
-                $this->page_slug, $this->_req_action, get_class($this));
671
-            throw new EE_Error($msg);
672
-        }
673
-        if ($this->_cpt_route) {
674
-            $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
675
-            $this->_set_model_object($id);
676
-        }
677
-    }
678
-
679
-
680
-
681
-    /**
682
-     * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
683
-     *
684
-     * @access protected
685
-     * @param int  $id The id to retrieve the model object for. If empty we set a default object.
686
-     * @param bool $ignore_route_check
687
-     * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
688
-     * @throws EE_Error
689
-     */
690
-    protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
691
-    {
692
-        $model = null;
693
-        if (
694
-            empty($this->_cpt_model_names)
695
-            || (
696
-                ! $ignore_route_check
697
-                && ! isset($this->_cpt_routes[$this->_req_action])
698
-            ) || (
699
-                $this->_cpt_model_obj instanceof EE_CPT_Base
700
-                && $this->_cpt_model_obj->ID() === $id
701
-            )
702
-        ) {
703
-            //get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
704
-            return;
705
-        }
706
-        //if ignore_route_check is true, then get the model name via EE_Register_CPTs
707
-        if ($ignore_route_check) {
708
-            $model_names = EE_Register_CPTs::get_cpt_model_names();
709
-            $post_type   = get_post_type($id);
710
-            if (isset($model_names[$post_type])) {
711
-                $model = EE_Registry::instance()->load_model($model_names[$post_type]);
712
-            }
713
-        } else {
714
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[$this->_req_action]);
715
-        }
716
-        if ($model instanceof EEM_Base) {
717
-            $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
718
-        }
719
-        do_action(
720
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
721
-            $this->_cpt_model_obj,
722
-            $req_type
723
-        );
724
-    }
725
-
726
-
727
-
728
-    /**
729
-     * admin_init_global
730
-     * This runs all the code that we want executed within the WP admin_init hook.
731
-     * This method executes for ALL EE Admin pages.
732
-     *
733
-     * @access public
734
-     * @return void
735
-     */
736
-    public function admin_init_global()
737
-    {
738
-        $post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
739
-        //its possible this is a new save so let's catch that instead
740
-        $post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
741
-        $post_type = $post ? $post->post_type : false;
742
-        $current_route = isset($this->_req_data['current_route'])
743
-            ? $this->_req_data['current_route']
744
-            : 'shouldneverwork';
745
-        $route_to_check = $post_type && isset($this->_cpt_routes[$current_route])
746
-            ? $this->_cpt_routes[$current_route]
747
-            : '';
748
-        add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
749
-        add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
750
-        if ($post_type === $route_to_check) {
751
-            add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
752
-        }
753
-        //now let's filter redirect if we're on a revision page and the revision is for an event CPT.
754
-        $revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
755
-        if ( ! empty($revision)) {
756
-            $action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
757
-            //doing a restore?
758
-            if ( ! empty($action) && $action === 'restore') {
759
-                //get post for revision
760
-                $rev_post = get_post($revision);
761
-                $rev_parent = get_post($rev_post->post_parent);
762
-                //only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
763
-                if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
764
-                    add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
765
-                    //restores of revisions
766
-                    add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
767
-                }
768
-            }
769
-        }
770
-        //NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
771
-        if ($post_type && $post_type === $route_to_check) {
772
-            //$post_id, $post
773
-            add_action('save_post', array($this, 'insert_update'), 10, 3);
774
-            //$post_id
775
-            add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
776
-            add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
777
-            add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
778
-            add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
779
-        }
780
-    }
781
-
782
-
783
-
784
-    /**
785
-     * Callback for the WordPress trashed_post hook.
786
-     * Execute some basic checks before calling the trash_cpt_item declared in the child class.
787
-     *
788
-     * @param int $post_id
789
-     * @throws \EE_Error
790
-     */
791
-    public function before_trash_cpt_item($post_id)
792
-    {
793
-        $this->_set_model_object($post_id, true, 'trash');
794
-        //if our cpt object isn't existent then get out immediately.
795
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
796
-            return;
797
-        }
798
-        $this->trash_cpt_item($post_id);
799
-    }
800
-
801
-
802
-
803
-    /**
804
-     * Callback for the WordPress untrashed_post hook.
805
-     * Execute some basic checks before calling the restore_cpt_method in the child class.
806
-     *
807
-     * @param $post_id
808
-     * @throws \EE_Error
809
-     */
810
-    public function before_restore_cpt_item($post_id)
811
-    {
812
-        $this->_set_model_object($post_id, true, 'restore');
813
-        //if our cpt object isn't existent then get out immediately.
814
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
815
-            return;
816
-        }
817
-        $this->restore_cpt_item($post_id);
818
-    }
819
-
820
-
821
-
822
-    /**
823
-     * Callback for the WordPress after_delete_post hook.
824
-     * Execute some basic checks before calling the delete_cpt_item method in the child class.
825
-     *
826
-     * @param $post_id
827
-     * @throws \EE_Error
828
-     */
829
-    public function before_delete_cpt_item($post_id)
830
-    {
831
-        $this->_set_model_object($post_id, true, 'delete');
832
-        //if our cpt object isn't existent then get out immediately.
833
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
834
-            return;
835
-        }
836
-        $this->delete_cpt_item($post_id);
837
-    }
838
-
839
-
840
-
841
-    /**
842
-     * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
843
-     * accordingly.
844
-     *
845
-     * @access public
846
-     * @throws EE_Error
847
-     * @return void
848
-     */
849
-    public function verify_cpt_object()
850
-    {
851
-        $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
852
-        // verify event object
853
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
854
-            throw new EE_Error(sprintf(__('Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
855
-                    'event_espresso'), $label));
856
-        }
857
-        //if auto-draft then throw an error
858
-        if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
859
-            EE_Error::overwrite_errors();
860
-            EE_Error::add_error(sprintf(__('This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.'),
861
-                    $label), __FILE__, __FUNCTION__, __LINE__);
862
-        }
863
-    }
864
-
865
-
866
-
867
-    /**
868
-     * admin_footer_scripts_global
869
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
870
-     * will apply on ALL EE_Admin pages.
871
-     *
872
-     * @access public
873
-     * @return void
874
-     */
875
-    public function admin_footer_scripts_global()
876
-    {
877
-        $this->_add_admin_page_ajax_loading_img();
878
-        $this->_add_admin_page_overlay();
879
-    }
880
-
881
-
882
-
883
-    /**
884
-     * add in any global scripts for cpt routes
885
-     *
886
-     * @return void
887
-     */
888
-    public function load_global_scripts_styles()
889
-    {
890
-        parent::load_global_scripts_styles();
891
-        if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
892
-            //setup custom post status object for localize script but only if we've got a cpt object
893
-            $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
894
-            if ( ! empty($statuses)) {
895
-                //get ALL statuses!
896
-                $statuses = $this->_cpt_model_obj->get_all_post_statuses();
897
-                //setup object
898
-                $ee_cpt_statuses = array();
899
-                foreach ($statuses as $status => $label) {
900
-                    $ee_cpt_statuses[$status] = array(
901
-                        'label'      => $label,
902
-                        'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
903
-                    );
904
-                }
905
-                wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
906
-            }
907
-        }
908
-    }
909
-
910
-
911
-
912
-    /**
913
-     * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
914
-     * insert/updates
915
-     *
916
-     * @param  int     $post_id ID of post being updated
917
-     * @param  WP_Post $post    Post object from WP
918
-     * @param  bool    $update  Whether this is an update or a new save.
919
-     * @return void
920
-     * @throws \EE_Error
921
-     */
922
-    public function insert_update($post_id, $post, $update)
923
-    {
924
-        //make sure that if this is a revision OR trash action that we don't do any updates!
925
-        if (
926
-            isset($this->_req_data['action'])
927
-            && (
928
-                $this->_req_data['action'] === 'restore'
929
-                || $this->_req_data['action'] === 'trash'
930
-            )
931
-        ) {
932
-            return;
933
-        }
934
-        $this->_set_model_object($post_id, true, 'insert_update');
935
-        //if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
936
-        if ($update
937
-            && (
938
-                ! $this->_cpt_model_obj instanceof EE_CPT_Base
939
-                || $this->_cpt_model_obj->ID() !== $post_id
940
-            )
941
-        ) {
942
-            return;
943
-        }
944
-        //check for autosave and update our req_data property accordingly.
945
-        /*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
502
+	}
503
+
504
+
505
+
506
+	/**
507
+	 * if this post is a draft or scheduled post then we provide a preview button for user to click
508
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
509
+	 *
510
+	 * @param  string $return    the current html
511
+	 * @param  int    $id        the post id for the page
512
+	 * @param  string $new_title What the title is
513
+	 * @param  string $new_slug  what the slug is
514
+	 * @return string            The new html string for the permalink area
515
+	 */
516
+	public function preview_button_html($return, $id, $new_title, $new_slug)
517
+	{
518
+		$post = get_post($id);
519
+		if ('publish' !== get_post_status($post)) {
520
+			//include shims for the `get_preview_post_link` function
521
+			require_once( EE_CORE . 'wordpress-shims.php' );
522
+			$return .= '<span_id="view-post-btn"><a target="_blank" href="'
523
+					   . get_preview_post_link($id)
524
+					   . '" class="button button-small">'
525
+					   . __('Preview', 'event_espresso')
526
+					   . '</a></span>'
527
+					   . "\n";
528
+		}
529
+		return $return;
530
+	}
531
+
532
+
533
+
534
+	/**
535
+	 * add our custom post stati dropdown on the wp post page for this cpt
536
+	 *
537
+	 * @return void
538
+	 */
539
+	public function custom_post_stati_dropdown()
540
+	{
541
+
542
+		$statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
543
+		$cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
544
+			? $statuses[$this->_cpt_model_obj->status()]
545
+			: '';
546
+		$template_args    = array(
547
+			'cur_status'            => $this->_cpt_model_obj->status(),
548
+			'statuses'              => $statuses,
549
+			'cur_status_label'      => $cur_status_label,
550
+			'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
551
+		);
552
+		//we'll add a trash post status (WP doesn't add one for some reason)
553
+		if ($this->_cpt_model_obj->status() === 'trash') {
554
+			$template_args['cur_status_label'] = __('Trashed', 'event_espresso');
555
+			$statuses['trash']                 = __('Trashed', 'event_espresso');
556
+			$template_args['statuses']         = $statuses;
557
+		}
558
+
559
+		$template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
560
+		EEH_Template::display_template($template, $template_args);
561
+	}
562
+
563
+
564
+
565
+	public function setup_autosave_hooks()
566
+	{
567
+		$this->_set_autosave_containers();
568
+		$this->_load_autosave_scripts_styles();
569
+	}
570
+
571
+
572
+
573
+	/**
574
+	 * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
575
+	 * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
576
+	 * for the nonce in here, but then this method looks for two things:
577
+	 * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
578
+	 * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
579
+	 * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
580
+	 * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
581
+	 * template args.
582
+	 *    1. $template_args['error'] = IF there is an error you can add the message in here.
583
+	 *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
584
+	 *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
585
+	 *    $this->_template_args['data']['items'] = array(
586
+	 *        'event-datetime-ids' => '1,2,3';
587
+	 *    );
588
+	 *    Keep in mind the following things:
589
+	 *    - "where" index is for the input with the id as that string.
590
+	 *    - "what" index is what will be used for the value of that input.
591
+	 *
592
+	 * @return void
593
+	 */
594
+	public function do_extra_autosave_stuff()
595
+	{
596
+		//next let's check for the autosave nonce (we'll use _verify_nonce )
597
+		$nonce = isset($this->_req_data['autosavenonce'])
598
+				? $this->_req_data['autosavenonce']
599
+				: null;
600
+		$this->_verify_nonce($nonce, 'autosave');
601
+		//make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
602
+		if ( ! defined('DOING_AUTOSAVE')) {
603
+			define('DOING_AUTOSAVE', true);
604
+		}
605
+		//if we made it here then the nonce checked out.  Let's run our methods and actions
606
+		$autosave = "_ee_autosave_{$this->_current_view}";
607
+		if (method_exists($this, $autosave)) {
608
+			$this->$autosave();
609
+		} else {
610
+			$this->_template_args['success'] = true;
611
+		}
612
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
613
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
614
+		//now let's return json
615
+		$this->_return_json();
616
+	}
617
+
618
+
619
+
620
+	/**
621
+	 * This takes care of setting up default routes and pages that utilize the core WP admin pages.
622
+	 * Child classes can override the defaults (in cases for adding metaboxes etc.)
623
+	 * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
624
+	 *
625
+	 * @access protected
626
+	 * @throws EE_Error
627
+	 * @return void
628
+	 */
629
+	protected function _extend_page_config_for_cpt()
630
+	{
631
+		//before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
632
+		if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
633
+			return;
634
+		}
635
+		//set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
636
+		if ( ! empty($this->_cpt_object)) {
637
+			$this->_page_routes = array_merge(array(
638
+				'create_new' => '_create_new_cpt_item',
639
+				'edit'       => '_edit_cpt_item',
640
+			), $this->_page_routes);
641
+			$this->_page_config = array_merge(array(
642
+				'create_new' => array(
643
+					'nav'           => array(
644
+						'label' => $this->_cpt_object->labels->add_new_item,
645
+						'order' => 5,
646
+					),
647
+					'require_nonce' => false,
648
+				),
649
+				'edit'       => array(
650
+					'nav'           => array(
651
+						'label'      => $this->_cpt_object->labels->edit_item,
652
+						'order'      => 5,
653
+						'persistent' => false,
654
+						'url'        => '',
655
+					),
656
+					'require_nonce' => false,
657
+				),
658
+			),
659
+				$this->_page_config
660
+			);
661
+		}
662
+		//load the next section only if this is a matching cpt route as set in the cpt routes array.
663
+		if ( ! isset($this->_cpt_routes[$this->_req_action])) {
664
+			return;
665
+		}
666
+		$this->_cpt_route = isset($this->_cpt_routes[$this->_req_action]) ? true : false;
667
+		//add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
668
+		if (empty($this->_cpt_object)) {
669
+			$msg = sprintf(__('This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).'),
670
+				$this->page_slug, $this->_req_action, get_class($this));
671
+			throw new EE_Error($msg);
672
+		}
673
+		if ($this->_cpt_route) {
674
+			$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
675
+			$this->_set_model_object($id);
676
+		}
677
+	}
678
+
679
+
680
+
681
+	/**
682
+	 * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
683
+	 *
684
+	 * @access protected
685
+	 * @param int  $id The id to retrieve the model object for. If empty we set a default object.
686
+	 * @param bool $ignore_route_check
687
+	 * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
688
+	 * @throws EE_Error
689
+	 */
690
+	protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
691
+	{
692
+		$model = null;
693
+		if (
694
+			empty($this->_cpt_model_names)
695
+			|| (
696
+				! $ignore_route_check
697
+				&& ! isset($this->_cpt_routes[$this->_req_action])
698
+			) || (
699
+				$this->_cpt_model_obj instanceof EE_CPT_Base
700
+				&& $this->_cpt_model_obj->ID() === $id
701
+			)
702
+		) {
703
+			//get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
704
+			return;
705
+		}
706
+		//if ignore_route_check is true, then get the model name via EE_Register_CPTs
707
+		if ($ignore_route_check) {
708
+			$model_names = EE_Register_CPTs::get_cpt_model_names();
709
+			$post_type   = get_post_type($id);
710
+			if (isset($model_names[$post_type])) {
711
+				$model = EE_Registry::instance()->load_model($model_names[$post_type]);
712
+			}
713
+		} else {
714
+			$model = EE_Registry::instance()->load_model($this->_cpt_model_names[$this->_req_action]);
715
+		}
716
+		if ($model instanceof EEM_Base) {
717
+			$this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
718
+		}
719
+		do_action(
720
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
721
+			$this->_cpt_model_obj,
722
+			$req_type
723
+		);
724
+	}
725
+
726
+
727
+
728
+	/**
729
+	 * admin_init_global
730
+	 * This runs all the code that we want executed within the WP admin_init hook.
731
+	 * This method executes for ALL EE Admin pages.
732
+	 *
733
+	 * @access public
734
+	 * @return void
735
+	 */
736
+	public function admin_init_global()
737
+	{
738
+		$post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
739
+		//its possible this is a new save so let's catch that instead
740
+		$post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
741
+		$post_type = $post ? $post->post_type : false;
742
+		$current_route = isset($this->_req_data['current_route'])
743
+			? $this->_req_data['current_route']
744
+			: 'shouldneverwork';
745
+		$route_to_check = $post_type && isset($this->_cpt_routes[$current_route])
746
+			? $this->_cpt_routes[$current_route]
747
+			: '';
748
+		add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
749
+		add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
750
+		if ($post_type === $route_to_check) {
751
+			add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
752
+		}
753
+		//now let's filter redirect if we're on a revision page and the revision is for an event CPT.
754
+		$revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
755
+		if ( ! empty($revision)) {
756
+			$action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
757
+			//doing a restore?
758
+			if ( ! empty($action) && $action === 'restore') {
759
+				//get post for revision
760
+				$rev_post = get_post($revision);
761
+				$rev_parent = get_post($rev_post->post_parent);
762
+				//only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
763
+				if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
764
+					add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
765
+					//restores of revisions
766
+					add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
767
+				}
768
+			}
769
+		}
770
+		//NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
771
+		if ($post_type && $post_type === $route_to_check) {
772
+			//$post_id, $post
773
+			add_action('save_post', array($this, 'insert_update'), 10, 3);
774
+			//$post_id
775
+			add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
776
+			add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
777
+			add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
778
+			add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
779
+		}
780
+	}
781
+
782
+
783
+
784
+	/**
785
+	 * Callback for the WordPress trashed_post hook.
786
+	 * Execute some basic checks before calling the trash_cpt_item declared in the child class.
787
+	 *
788
+	 * @param int $post_id
789
+	 * @throws \EE_Error
790
+	 */
791
+	public function before_trash_cpt_item($post_id)
792
+	{
793
+		$this->_set_model_object($post_id, true, 'trash');
794
+		//if our cpt object isn't existent then get out immediately.
795
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
796
+			return;
797
+		}
798
+		$this->trash_cpt_item($post_id);
799
+	}
800
+
801
+
802
+
803
+	/**
804
+	 * Callback for the WordPress untrashed_post hook.
805
+	 * Execute some basic checks before calling the restore_cpt_method in the child class.
806
+	 *
807
+	 * @param $post_id
808
+	 * @throws \EE_Error
809
+	 */
810
+	public function before_restore_cpt_item($post_id)
811
+	{
812
+		$this->_set_model_object($post_id, true, 'restore');
813
+		//if our cpt object isn't existent then get out immediately.
814
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
815
+			return;
816
+		}
817
+		$this->restore_cpt_item($post_id);
818
+	}
819
+
820
+
821
+
822
+	/**
823
+	 * Callback for the WordPress after_delete_post hook.
824
+	 * Execute some basic checks before calling the delete_cpt_item method in the child class.
825
+	 *
826
+	 * @param $post_id
827
+	 * @throws \EE_Error
828
+	 */
829
+	public function before_delete_cpt_item($post_id)
830
+	{
831
+		$this->_set_model_object($post_id, true, 'delete');
832
+		//if our cpt object isn't existent then get out immediately.
833
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
834
+			return;
835
+		}
836
+		$this->delete_cpt_item($post_id);
837
+	}
838
+
839
+
840
+
841
+	/**
842
+	 * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
843
+	 * accordingly.
844
+	 *
845
+	 * @access public
846
+	 * @throws EE_Error
847
+	 * @return void
848
+	 */
849
+	public function verify_cpt_object()
850
+	{
851
+		$label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
852
+		// verify event object
853
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
854
+			throw new EE_Error(sprintf(__('Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
855
+					'event_espresso'), $label));
856
+		}
857
+		//if auto-draft then throw an error
858
+		if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
859
+			EE_Error::overwrite_errors();
860
+			EE_Error::add_error(sprintf(__('This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.'),
861
+					$label), __FILE__, __FUNCTION__, __LINE__);
862
+		}
863
+	}
864
+
865
+
866
+
867
+	/**
868
+	 * admin_footer_scripts_global
869
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
870
+	 * will apply on ALL EE_Admin pages.
871
+	 *
872
+	 * @access public
873
+	 * @return void
874
+	 */
875
+	public function admin_footer_scripts_global()
876
+	{
877
+		$this->_add_admin_page_ajax_loading_img();
878
+		$this->_add_admin_page_overlay();
879
+	}
880
+
881
+
882
+
883
+	/**
884
+	 * add in any global scripts for cpt routes
885
+	 *
886
+	 * @return void
887
+	 */
888
+	public function load_global_scripts_styles()
889
+	{
890
+		parent::load_global_scripts_styles();
891
+		if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
892
+			//setup custom post status object for localize script but only if we've got a cpt object
893
+			$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
894
+			if ( ! empty($statuses)) {
895
+				//get ALL statuses!
896
+				$statuses = $this->_cpt_model_obj->get_all_post_statuses();
897
+				//setup object
898
+				$ee_cpt_statuses = array();
899
+				foreach ($statuses as $status => $label) {
900
+					$ee_cpt_statuses[$status] = array(
901
+						'label'      => $label,
902
+						'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
903
+					);
904
+				}
905
+				wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
906
+			}
907
+		}
908
+	}
909
+
910
+
911
+
912
+	/**
913
+	 * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
914
+	 * insert/updates
915
+	 *
916
+	 * @param  int     $post_id ID of post being updated
917
+	 * @param  WP_Post $post    Post object from WP
918
+	 * @param  bool    $update  Whether this is an update or a new save.
919
+	 * @return void
920
+	 * @throws \EE_Error
921
+	 */
922
+	public function insert_update($post_id, $post, $update)
923
+	{
924
+		//make sure that if this is a revision OR trash action that we don't do any updates!
925
+		if (
926
+			isset($this->_req_data['action'])
927
+			&& (
928
+				$this->_req_data['action'] === 'restore'
929
+				|| $this->_req_data['action'] === 'trash'
930
+			)
931
+		) {
932
+			return;
933
+		}
934
+		$this->_set_model_object($post_id, true, 'insert_update');
935
+		//if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
936
+		if ($update
937
+			&& (
938
+				! $this->_cpt_model_obj instanceof EE_CPT_Base
939
+				|| $this->_cpt_model_obj->ID() !== $post_id
940
+			)
941
+		) {
942
+			return;
943
+		}
944
+		//check for autosave and update our req_data property accordingly.
945
+		/*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
946 946
             foreach( (array) $this->_req_data['ee_autosave_data'] as $id => $values ) {
947 947
 
948 948
                 foreach ( (array) $values as $key => $value ) {
@@ -952,542 +952,542 @@  discard block
 block discarded – undo
952 952
 
953 953
         }/**/ //TODO reactivate after autosave is implemented in 4.2
954 954
 
955
-        //take care of updating any selected page_template IF this cpt supports it.
956
-        if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
957
-            //wp version aware.
958
-            if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
959
-                $page_templates = wp_get_theme()->get_page_templates();
960
-            } else {
961
-                $post->page_template = $this->_req_data['page_template'];
962
-                $page_templates      = wp_get_theme()->get_page_templates($post);
963
-            }
964
-            if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[$this->_req_data['page_template']])) {
965
-                EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
966
-            } else {
967
-                update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
968
-            }
969
-        }
970
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
971
-            return;
972
-        } //TODO we'll remove this after reimplementing autosave in 4.2
973
-        $this->_insert_update_cpt_item($post_id, $post);
974
-    }
975
-
976
-
977
-
978
-    /**
979
-     * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
980
-     * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
981
-     * so we don't have to check for our CPT.
982
-     *
983
-     * @param  int $post_id ID of the post
984
-     * @return void
985
-     */
986
-    public function dont_permanently_delete_ee_cpts($post_id)
987
-    {
988
-        //only do this if we're actually processing one of our CPTs
989
-        //if our cpt object isn't existent then get out immediately.
990
-        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
991
-            return;
992
-        }
993
-        delete_post_meta($post_id, '_wp_trash_meta_status');
994
-        delete_post_meta($post_id, '_wp_trash_meta_time');
995
-        //our cpts may have comments so let's take care of that too
996
-        delete_post_meta($post_id, '_wp_trash_meta_comments_status');
997
-    }
998
-
999
-
1000
-
1001
-    /**
1002
-     * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1003
-     * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1004
-     * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1005
-     *
1006
-     * @param  int $post_id     ID of cpt item
1007
-     * @param  int $revision_id ID of revision being restored
1008
-     * @return void
1009
-     */
1010
-    public function restore_revision($post_id, $revision_id)
1011
-    {
1012
-        $this->_restore_cpt_item($post_id, $revision_id);
1013
-        //global action
1014
-        do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1015
-        //class specific action so you can limit hooking into a specific page.
1016
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1017
-    }
1018
-
1019
-
1020
-
1021
-    /**
1022
-     * @see restore_revision() for details
1023
-     * @param  int $post_id     ID of cpt item
1024
-     * @param  int $revision_id ID of revision for item
1025
-     * @return void
1026
-     */
1027
-    abstract protected function _restore_cpt_item($post_id, $revision_id);
1028
-
1029
-
1030
-
1031
-    /**
1032
-     * Execution of this method is added to the end of the load_page_dependencies method in the parent
1033
-     * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1034
-     * To fix we have to reset the current_screen using the page_slug
1035
-     * (which is identical - or should be - to our registered_post_type id.)
1036
-     * Also, since the core WP file loads the admin_header.php for WP
1037
-     * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1038
-     * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1039
-     *
1040
-     * @return void
1041
-     */
1042
-    public function modify_current_screen()
1043
-    {
1044
-        //ONLY do this if the current page_route IS a cpt route
1045
-        if ( ! $this->_cpt_route) {
1046
-            return;
1047
-        }
1048
-        //routing things REALLY early b/c this is a cpt admin page
1049
-        set_current_screen($this->_cpt_routes[$this->_req_action]);
1050
-        $this->_current_screen       = get_current_screen();
1051
-        $this->_current_screen->base = 'event-espresso';
1052
-        $this->_add_help_tabs(); //we make sure we add any help tabs back in!
1053
-        /*try {
955
+		//take care of updating any selected page_template IF this cpt supports it.
956
+		if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
957
+			//wp version aware.
958
+			if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
959
+				$page_templates = wp_get_theme()->get_page_templates();
960
+			} else {
961
+				$post->page_template = $this->_req_data['page_template'];
962
+				$page_templates      = wp_get_theme()->get_page_templates($post);
963
+			}
964
+			if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[$this->_req_data['page_template']])) {
965
+				EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
966
+			} else {
967
+				update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
968
+			}
969
+		}
970
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
971
+			return;
972
+		} //TODO we'll remove this after reimplementing autosave in 4.2
973
+		$this->_insert_update_cpt_item($post_id, $post);
974
+	}
975
+
976
+
977
+
978
+	/**
979
+	 * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
980
+	 * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
981
+	 * so we don't have to check for our CPT.
982
+	 *
983
+	 * @param  int $post_id ID of the post
984
+	 * @return void
985
+	 */
986
+	public function dont_permanently_delete_ee_cpts($post_id)
987
+	{
988
+		//only do this if we're actually processing one of our CPTs
989
+		//if our cpt object isn't existent then get out immediately.
990
+		if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
991
+			return;
992
+		}
993
+		delete_post_meta($post_id, '_wp_trash_meta_status');
994
+		delete_post_meta($post_id, '_wp_trash_meta_time');
995
+		//our cpts may have comments so let's take care of that too
996
+		delete_post_meta($post_id, '_wp_trash_meta_comments_status');
997
+	}
998
+
999
+
1000
+
1001
+	/**
1002
+	 * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1003
+	 * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1004
+	 * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1005
+	 *
1006
+	 * @param  int $post_id     ID of cpt item
1007
+	 * @param  int $revision_id ID of revision being restored
1008
+	 * @return void
1009
+	 */
1010
+	public function restore_revision($post_id, $revision_id)
1011
+	{
1012
+		$this->_restore_cpt_item($post_id, $revision_id);
1013
+		//global action
1014
+		do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1015
+		//class specific action so you can limit hooking into a specific page.
1016
+		do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1017
+	}
1018
+
1019
+
1020
+
1021
+	/**
1022
+	 * @see restore_revision() for details
1023
+	 * @param  int $post_id     ID of cpt item
1024
+	 * @param  int $revision_id ID of revision for item
1025
+	 * @return void
1026
+	 */
1027
+	abstract protected function _restore_cpt_item($post_id, $revision_id);
1028
+
1029
+
1030
+
1031
+	/**
1032
+	 * Execution of this method is added to the end of the load_page_dependencies method in the parent
1033
+	 * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1034
+	 * To fix we have to reset the current_screen using the page_slug
1035
+	 * (which is identical - or should be - to our registered_post_type id.)
1036
+	 * Also, since the core WP file loads the admin_header.php for WP
1037
+	 * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1038
+	 * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1039
+	 *
1040
+	 * @return void
1041
+	 */
1042
+	public function modify_current_screen()
1043
+	{
1044
+		//ONLY do this if the current page_route IS a cpt route
1045
+		if ( ! $this->_cpt_route) {
1046
+			return;
1047
+		}
1048
+		//routing things REALLY early b/c this is a cpt admin page
1049
+		set_current_screen($this->_cpt_routes[$this->_req_action]);
1050
+		$this->_current_screen       = get_current_screen();
1051
+		$this->_current_screen->base = 'event-espresso';
1052
+		$this->_add_help_tabs(); //we make sure we add any help tabs back in!
1053
+		/*try {
1054 1054
             $this->_route_admin_request();
1055 1055
         } catch ( EE_Error $e ) {
1056 1056
             $e->get_error();
1057 1057
         }/**/
1058
-    }
1059
-
1060
-
1061
-
1062
-    /**
1063
-     * This allows child classes to modify the default editor title that appears when people add a new or edit an
1064
-     * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1065
-     * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1066
-     * default to be.
1067
-     *
1068
-     * @param string $title The new title (or existing if there is no editor_title defined)
1069
-     * @return string
1070
-     */
1071
-    public function add_custom_editor_default_title($title)
1072
-    {
1073
-        return isset($this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]])
1074
-            ? $this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]]
1075
-            : $title;
1076
-    }
1077
-
1078
-
1079
-
1080
-    /**
1081
-     * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1082
-     *
1083
-     * @param string $shortlink   The already generated shortlink
1084
-     * @param int    $id          Post ID for this item
1085
-     * @param string $context     The context for the link
1086
-     * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1087
-     * @return string
1088
-     */
1089
-    public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1090
-    {
1091
-        if ( ! empty($id) && get_option('permalink_structure') !== '') {
1092
-            $post = get_post($id);
1093
-            if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1094
-                $shortlink = home_url('?p=' . $post->ID);
1095
-            }
1096
-        }
1097
-        return $shortlink;
1098
-    }
1099
-
1100
-
1101
-
1102
-    /**
1103
-     * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1104
-     * already run in modify_current_screen())
1105
-     *
1106
-     * @return void
1107
-     */
1108
-    public function route_admin_request()
1109
-    {
1110
-        if ($this->_cpt_route) {
1111
-            return;
1112
-        }
1113
-        try {
1114
-            $this->_route_admin_request();
1115
-        } catch (EE_Error $e) {
1116
-            $e->get_error();
1117
-        }
1118
-    }
1119
-
1120
-
1121
-
1122
-    /**
1123
-     * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1124
-     *
1125
-     * @return void
1126
-     */
1127
-    public function cpt_post_form_hidden_input()
1128
-    {
1129
-        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1130
-        //we're also going to add the route value and the current page so we can direct autosave parsing correctly
1131
-        echo '<div id="ee-cpt-hidden-inputs">';
1132
-        echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1133
-        echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1134
-        echo '</div>';
1135
-    }
1136
-
1137
-
1138
-
1139
-    /**
1140
-     * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1141
-     *
1142
-     * @param  string $location Original location url
1143
-     * @param  int    $status   Status for http header
1144
-     * @return string           new (or original) url to redirect to.
1145
-     */
1146
-    public function revision_redirect($location, $status)
1147
-    {
1148
-        //get revision
1149
-        $rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1150
-        //can't do anything without revision so let's get out if not present
1151
-        if (empty($rev_id)) {
1152
-            return $location;
1153
-        }
1154
-        //get rev_post_data
1155
-        $rev = get_post($rev_id);
1156
-        $admin_url = $this->_admin_base_url;
1157
-        $query_args = array(
1158
-            'action'   => 'edit',
1159
-            'post'     => $rev->post_parent,
1160
-            'revision' => $rev_id,
1161
-            'message'  => 5,
1162
-        );
1163
-        $this->_process_notices($query_args, true);
1164
-        return self::add_query_args_and_nonce($query_args, $admin_url);
1165
-    }
1166
-
1167
-
1168
-
1169
-    /**
1170
-     * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1171
-     *
1172
-     * @param  string $link    the original generated link
1173
-     * @param  int    $id      post id
1174
-     * @param  string $context optional, defaults to display.  How to write the '&'
1175
-     * @return string          the link
1176
-     */
1177
-    public function modify_edit_post_link($link, $id, $context)
1178
-    {
1179
-        $post = get_post($id);
1180
-        if ( ! isset($this->_req_data['action'])
1181
-             || ! isset($this->_cpt_routes[$this->_req_data['action']])
1182
-             || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1183
-        ) {
1184
-            return $link;
1185
-        }
1186
-        $query_args = array(
1187
-            'action' => isset($this->_cpt_edit_routes[$post->post_type])
1188
-                ? $this->_cpt_edit_routes[$post->post_type]
1189
-                : 'edit',
1190
-            'post'   => $id,
1191
-        );
1192
-        return self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1193
-    }
1194
-
1195
-
1196
-    /**
1197
-     * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1198
-     * our routes.
1199
-     *
1200
-     * @param  string $delete_link  original delete link
1201
-     * @param  int    $post_id      id of cpt object
1202
-     * @param  bool   $force_delete whether this is forcing a hard delete instead of trash
1203
-     * @return string new delete link
1204
-     * @throws EE_Error
1205
-     */
1206
-    public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1207
-    {
1208
-        $post = get_post($post_id);
1209
-
1210
-        if (empty($this->_req_data['action'])
1211
-            || ! isset($this->_cpt_routes[$this->_req_data['action']])
1212
-            || ! $post instanceof WP_Post
1213
-            || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1214
-        ) {
1215
-            return $delete_link;
1216
-        }
1217
-        $this->_set_model_object($post->ID, true);
1218
-
1219
-        //returns something like `trash_event` or `trash_attendee` or `trash_venue`
1220
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1221
-
1222
-        return EE_Admin_Page::add_query_args_and_nonce(
1223
-            array(
1224
-                'page' => $this->_req_data['page'],
1225
-                'action' => $action,
1226
-                $this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1227
-                    => $post->ID
1228
-            ),
1229
-            admin_url()
1230
-        );
1231
-    }
1232
-
1233
-
1234
-
1235
-    /**
1236
-     * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1237
-     * so that we can hijack the default redirect locations for wp custom post types
1238
-     * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1239
-     *
1240
-     * @param  string $location This is the incoming currently set redirect location
1241
-     * @param  string $post_id  This is the 'ID' value of the wp_posts table
1242
-     * @return string           the new location to redirect to
1243
-     */
1244
-    public function cpt_post_location_redirect($location, $post_id)
1245
-    {
1246
-        //we DO have a match so let's setup the url
1247
-        //we have to get the post to determine our route
1248
-        $post       = get_post($post_id);
1249
-        $edit_route = $this->_cpt_edit_routes[$post->post_type];
1250
-        //shared query_args
1251
-        $query_args = array('action' => $edit_route, 'post' => $post_id);
1252
-        $admin_url  = $this->_admin_base_url;
1253
-        if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1254
-            $status = get_post_status($post_id);
1255
-            if (isset($this->_req_data['publish'])) {
1256
-                switch ($status) {
1257
-                    case 'pending':
1258
-                        $message = 8;
1259
-                        break;
1260
-                    case 'future':
1261
-                        $message = 9;
1262
-                        break;
1263
-                    default:
1264
-                        $message = 6;
1265
-                }
1266
-            } else {
1267
-                $message = 'draft' === $status ? 10 : 1;
1268
-            }
1269
-        } else if (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1270
-            $message = 2;
1271
-            //			$append = '#postcustom';
1272
-        } else if (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1273
-            $message = 3;
1274
-            //			$append = '#postcustom';
1275
-        } elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1276
-            $message = 7;
1277
-        } else {
1278
-            $message = 4;
1279
-        }
1280
-        //change the message if the post type is not viewable on the frontend
1281
-        $this->_cpt_object = get_post_type_object($post->post_type);
1282
-        $message           = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1283
-        $query_args = array_merge(array('message' => $message), $query_args);
1284
-        $this->_process_notices($query_args, true);
1285
-        return self::add_query_args_and_nonce($query_args, $admin_url);
1286
-    }
1287
-
1288
-
1289
-
1290
-    /**
1291
-     * This method is called to inject nav tabs on core WP cpt pages
1292
-     *
1293
-     * @access public
1294
-     * @return void
1295
-     */
1296
-    public function inject_nav_tabs()
1297
-    {
1298
-        //can we hijack and insert the nav_tabs?
1299
-        $nav_tabs = $this->_get_main_nav_tabs();
1300
-        //first close off existing form tag
1301
-        $html = '>';
1302
-        $html .= $nav_tabs;
1303
-        //now let's handle the remaining tag ( missing ">" is CORRECT )
1304
-        $html .= '<span></span';
1305
-        echo $html;
1306
-    }
1307
-
1308
-
1309
-
1310
-    /**
1311
-     * This just sets up the post update messages when an update form is loaded
1312
-     *
1313
-     * @access public
1314
-     * @param  array $messages the original messages array
1315
-     * @return array           the new messages array
1316
-     */
1317
-    public function post_update_messages($messages)
1318
-    {
1319
-        global $post;
1320
-        $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1321
-        $id = empty($id) && is_object($post) ? $post->ID : null;
1322
-        //		$post_type = $post ? $post->post_type : false;
1323
-        /*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1058
+	}
1059
+
1060
+
1061
+
1062
+	/**
1063
+	 * This allows child classes to modify the default editor title that appears when people add a new or edit an
1064
+	 * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1065
+	 * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1066
+	 * default to be.
1067
+	 *
1068
+	 * @param string $title The new title (or existing if there is no editor_title defined)
1069
+	 * @return string
1070
+	 */
1071
+	public function add_custom_editor_default_title($title)
1072
+	{
1073
+		return isset($this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]])
1074
+			? $this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]]
1075
+			: $title;
1076
+	}
1077
+
1078
+
1079
+
1080
+	/**
1081
+	 * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1082
+	 *
1083
+	 * @param string $shortlink   The already generated shortlink
1084
+	 * @param int    $id          Post ID for this item
1085
+	 * @param string $context     The context for the link
1086
+	 * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1087
+	 * @return string
1088
+	 */
1089
+	public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1090
+	{
1091
+		if ( ! empty($id) && get_option('permalink_structure') !== '') {
1092
+			$post = get_post($id);
1093
+			if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1094
+				$shortlink = home_url('?p=' . $post->ID);
1095
+			}
1096
+		}
1097
+		return $shortlink;
1098
+	}
1099
+
1100
+
1101
+
1102
+	/**
1103
+	 * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1104
+	 * already run in modify_current_screen())
1105
+	 *
1106
+	 * @return void
1107
+	 */
1108
+	public function route_admin_request()
1109
+	{
1110
+		if ($this->_cpt_route) {
1111
+			return;
1112
+		}
1113
+		try {
1114
+			$this->_route_admin_request();
1115
+		} catch (EE_Error $e) {
1116
+			$e->get_error();
1117
+		}
1118
+	}
1119
+
1120
+
1121
+
1122
+	/**
1123
+	 * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1124
+	 *
1125
+	 * @return void
1126
+	 */
1127
+	public function cpt_post_form_hidden_input()
1128
+	{
1129
+		echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1130
+		//we're also going to add the route value and the current page so we can direct autosave parsing correctly
1131
+		echo '<div id="ee-cpt-hidden-inputs">';
1132
+		echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1133
+		echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1134
+		echo '</div>';
1135
+	}
1136
+
1137
+
1138
+
1139
+	/**
1140
+	 * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1141
+	 *
1142
+	 * @param  string $location Original location url
1143
+	 * @param  int    $status   Status for http header
1144
+	 * @return string           new (or original) url to redirect to.
1145
+	 */
1146
+	public function revision_redirect($location, $status)
1147
+	{
1148
+		//get revision
1149
+		$rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1150
+		//can't do anything without revision so let's get out if not present
1151
+		if (empty($rev_id)) {
1152
+			return $location;
1153
+		}
1154
+		//get rev_post_data
1155
+		$rev = get_post($rev_id);
1156
+		$admin_url = $this->_admin_base_url;
1157
+		$query_args = array(
1158
+			'action'   => 'edit',
1159
+			'post'     => $rev->post_parent,
1160
+			'revision' => $rev_id,
1161
+			'message'  => 5,
1162
+		);
1163
+		$this->_process_notices($query_args, true);
1164
+		return self::add_query_args_and_nonce($query_args, $admin_url);
1165
+	}
1166
+
1167
+
1168
+
1169
+	/**
1170
+	 * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1171
+	 *
1172
+	 * @param  string $link    the original generated link
1173
+	 * @param  int    $id      post id
1174
+	 * @param  string $context optional, defaults to display.  How to write the '&'
1175
+	 * @return string          the link
1176
+	 */
1177
+	public function modify_edit_post_link($link, $id, $context)
1178
+	{
1179
+		$post = get_post($id);
1180
+		if ( ! isset($this->_req_data['action'])
1181
+			 || ! isset($this->_cpt_routes[$this->_req_data['action']])
1182
+			 || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1183
+		) {
1184
+			return $link;
1185
+		}
1186
+		$query_args = array(
1187
+			'action' => isset($this->_cpt_edit_routes[$post->post_type])
1188
+				? $this->_cpt_edit_routes[$post->post_type]
1189
+				: 'edit',
1190
+			'post'   => $id,
1191
+		);
1192
+		return self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1193
+	}
1194
+
1195
+
1196
+	/**
1197
+	 * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1198
+	 * our routes.
1199
+	 *
1200
+	 * @param  string $delete_link  original delete link
1201
+	 * @param  int    $post_id      id of cpt object
1202
+	 * @param  bool   $force_delete whether this is forcing a hard delete instead of trash
1203
+	 * @return string new delete link
1204
+	 * @throws EE_Error
1205
+	 */
1206
+	public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1207
+	{
1208
+		$post = get_post($post_id);
1209
+
1210
+		if (empty($this->_req_data['action'])
1211
+			|| ! isset($this->_cpt_routes[$this->_req_data['action']])
1212
+			|| ! $post instanceof WP_Post
1213
+			|| $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1214
+		) {
1215
+			return $delete_link;
1216
+		}
1217
+		$this->_set_model_object($post->ID, true);
1218
+
1219
+		//returns something like `trash_event` or `trash_attendee` or `trash_venue`
1220
+		$action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1221
+
1222
+		return EE_Admin_Page::add_query_args_and_nonce(
1223
+			array(
1224
+				'page' => $this->_req_data['page'],
1225
+				'action' => $action,
1226
+				$this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1227
+					=> $post->ID
1228
+			),
1229
+			admin_url()
1230
+		);
1231
+	}
1232
+
1233
+
1234
+
1235
+	/**
1236
+	 * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1237
+	 * so that we can hijack the default redirect locations for wp custom post types
1238
+	 * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1239
+	 *
1240
+	 * @param  string $location This is the incoming currently set redirect location
1241
+	 * @param  string $post_id  This is the 'ID' value of the wp_posts table
1242
+	 * @return string           the new location to redirect to
1243
+	 */
1244
+	public function cpt_post_location_redirect($location, $post_id)
1245
+	{
1246
+		//we DO have a match so let's setup the url
1247
+		//we have to get the post to determine our route
1248
+		$post       = get_post($post_id);
1249
+		$edit_route = $this->_cpt_edit_routes[$post->post_type];
1250
+		//shared query_args
1251
+		$query_args = array('action' => $edit_route, 'post' => $post_id);
1252
+		$admin_url  = $this->_admin_base_url;
1253
+		if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1254
+			$status = get_post_status($post_id);
1255
+			if (isset($this->_req_data['publish'])) {
1256
+				switch ($status) {
1257
+					case 'pending':
1258
+						$message = 8;
1259
+						break;
1260
+					case 'future':
1261
+						$message = 9;
1262
+						break;
1263
+					default:
1264
+						$message = 6;
1265
+				}
1266
+			} else {
1267
+				$message = 'draft' === $status ? 10 : 1;
1268
+			}
1269
+		} else if (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1270
+			$message = 2;
1271
+			//			$append = '#postcustom';
1272
+		} else if (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1273
+			$message = 3;
1274
+			//			$append = '#postcustom';
1275
+		} elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1276
+			$message = 7;
1277
+		} else {
1278
+			$message = 4;
1279
+		}
1280
+		//change the message if the post type is not viewable on the frontend
1281
+		$this->_cpt_object = get_post_type_object($post->post_type);
1282
+		$message           = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1283
+		$query_args = array_merge(array('message' => $message), $query_args);
1284
+		$this->_process_notices($query_args, true);
1285
+		return self::add_query_args_and_nonce($query_args, $admin_url);
1286
+	}
1287
+
1288
+
1289
+
1290
+	/**
1291
+	 * This method is called to inject nav tabs on core WP cpt pages
1292
+	 *
1293
+	 * @access public
1294
+	 * @return void
1295
+	 */
1296
+	public function inject_nav_tabs()
1297
+	{
1298
+		//can we hijack and insert the nav_tabs?
1299
+		$nav_tabs = $this->_get_main_nav_tabs();
1300
+		//first close off existing form tag
1301
+		$html = '>';
1302
+		$html .= $nav_tabs;
1303
+		//now let's handle the remaining tag ( missing ">" is CORRECT )
1304
+		$html .= '<span></span';
1305
+		echo $html;
1306
+	}
1307
+
1308
+
1309
+
1310
+	/**
1311
+	 * This just sets up the post update messages when an update form is loaded
1312
+	 *
1313
+	 * @access public
1314
+	 * @param  array $messages the original messages array
1315
+	 * @return array           the new messages array
1316
+	 */
1317
+	public function post_update_messages($messages)
1318
+	{
1319
+		global $post;
1320
+		$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1321
+		$id = empty($id) && is_object($post) ? $post->ID : null;
1322
+		//		$post_type = $post ? $post->post_type : false;
1323
+		/*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1324 1324
 
1325 1325
         $route_to_check = $post_type && isset( $this->_cpt_routes[$current_route]) ? $this->_cpt_routes[$current_route] : '';/**/
1326
-        $messages[$post->post_type] = array(
1327
-            0 => '', //Unused. Messages start at index 1.
1328
-            1 => sprintf(
1329
-                __('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1330
-                $this->_cpt_object->labels->singular_name,
1331
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1332
-                '</a>'
1333
-            ),
1334
-            2 => __('Custom field updated'),
1335
-            3 => __('Custom field deleted.'),
1336
-            4 => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1337
-            5 => isset($_GET['revision']) ? sprintf(__('%s restored to revision from %s', 'event_espresso'),
1338
-                $this->_cpt_object->labels->singular_name, wp_post_revision_title((int)$_GET['revision'], false))
1339
-                : false,
1340
-            6 => sprintf(
1341
-                __('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1342
-                $this->_cpt_object->labels->singular_name,
1343
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1344
-                '</a>'
1345
-            ),
1346
-            7 => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1347
-            8 => sprintf(
1348
-                __('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1349
-                $this->_cpt_object->labels->singular_name,
1350
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1351
-                '</a>'
1352
-            ),
1353
-            9 => sprintf(
1354
-                __('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1355
-                $this->_cpt_object->labels->singular_name,
1356
-                '<strong>' . date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)) . '</strong>',
1357
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1358
-                '</a>'
1359
-            ),
1360
-            10 => sprintf(
1361
-                __('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1362
-                $this->_cpt_object->labels->singular_name,
1363
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1364
-                '</a>'
1365
-            ),
1366
-        );
1367
-        return $messages;
1368
-    }
1369
-
1370
-
1371
-
1372
-    /**
1373
-     * default method for the 'create_new' route for cpt admin pages.
1374
-     * For reference what to include in here, see wp-admin/post-new.php
1375
-     *
1376
-     * @access  protected
1377
-     * @return void
1378
-     */
1379
-    protected function _create_new_cpt_item()
1380
-    {
1381
-        // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1382
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1383
-        $post_type        = $this->_cpt_routes[$this->_req_action];
1384
-        $post_type_object = $this->_cpt_object;
1385
-        $title            = $post_type_object->labels->add_new_item;
1386
-        $post    = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1387
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1388
-        //modify the default editor title field with default title.
1389
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1390
-        $this->loadEditorTemplate(true);
1391
-    }
1392
-
1393
-
1394
-    /**
1395
-     * Enqueues auto-save and loads the editor template
1396
-     *
1397
-     * @param bool $creating
1398
-     */
1399
-    private function loadEditorTemplate($creating = true) {
1400
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1401
-        //these vars are used by the template
1402
-        $editing = true;
1403
-        $post_ID = $post->ID;
1404
-        if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1405
-            //only enqueue autosave when creating event (necessary to get permalink/url generated)
1406
-            //otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1407
-            if ($creating) {
1408
-                wp_enqueue_script('autosave');
1409
-            } else {
1410
-                if (isset($this->_cpt_routes[$this->_req_data['action']])
1411
-                    && ! isset($this->_labels['hide_add_button_on_cpt_route'][$this->_req_data['action']])
1412
-                ) {
1413
-                    $create_new_action = apply_filters('FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1414
-                        'create_new', $this);
1415
-                    $post_new_file = EE_Admin_Page::add_query_args_and_nonce(array(
1416
-                        'action' => $create_new_action,
1417
-                        'page'   => $this->page_slug,
1418
-                    ), 'admin.php');
1419
-                }
1420
-            }
1421
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1422
-        }
1423
-    }
1424
-
1425
-
1426
-
1427
-    public function add_new_admin_page_global()
1428
-    {
1429
-        $admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1430
-        ?>
1326
+		$messages[$post->post_type] = array(
1327
+			0 => '', //Unused. Messages start at index 1.
1328
+			1 => sprintf(
1329
+				__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1330
+				$this->_cpt_object->labels->singular_name,
1331
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1332
+				'</a>'
1333
+			),
1334
+			2 => __('Custom field updated'),
1335
+			3 => __('Custom field deleted.'),
1336
+			4 => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1337
+			5 => isset($_GET['revision']) ? sprintf(__('%s restored to revision from %s', 'event_espresso'),
1338
+				$this->_cpt_object->labels->singular_name, wp_post_revision_title((int)$_GET['revision'], false))
1339
+				: false,
1340
+			6 => sprintf(
1341
+				__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1342
+				$this->_cpt_object->labels->singular_name,
1343
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1344
+				'</a>'
1345
+			),
1346
+			7 => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1347
+			8 => sprintf(
1348
+				__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1349
+				$this->_cpt_object->labels->singular_name,
1350
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1351
+				'</a>'
1352
+			),
1353
+			9 => sprintf(
1354
+				__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1355
+				$this->_cpt_object->labels->singular_name,
1356
+				'<strong>' . date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)) . '</strong>',
1357
+				'<a target="_blank" href="' . esc_url(get_permalink($id)),
1358
+				'</a>'
1359
+			),
1360
+			10 => sprintf(
1361
+				__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1362
+				$this->_cpt_object->labels->singular_name,
1363
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1364
+				'</a>'
1365
+			),
1366
+		);
1367
+		return $messages;
1368
+	}
1369
+
1370
+
1371
+
1372
+	/**
1373
+	 * default method for the 'create_new' route for cpt admin pages.
1374
+	 * For reference what to include in here, see wp-admin/post-new.php
1375
+	 *
1376
+	 * @access  protected
1377
+	 * @return void
1378
+	 */
1379
+	protected function _create_new_cpt_item()
1380
+	{
1381
+		// gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1382
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1383
+		$post_type        = $this->_cpt_routes[$this->_req_action];
1384
+		$post_type_object = $this->_cpt_object;
1385
+		$title            = $post_type_object->labels->add_new_item;
1386
+		$post    = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1387
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1388
+		//modify the default editor title field with default title.
1389
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1390
+		$this->loadEditorTemplate(true);
1391
+	}
1392
+
1393
+
1394
+	/**
1395
+	 * Enqueues auto-save and loads the editor template
1396
+	 *
1397
+	 * @param bool $creating
1398
+	 */
1399
+	private function loadEditorTemplate($creating = true) {
1400
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1401
+		//these vars are used by the template
1402
+		$editing = true;
1403
+		$post_ID = $post->ID;
1404
+		if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1405
+			//only enqueue autosave when creating event (necessary to get permalink/url generated)
1406
+			//otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1407
+			if ($creating) {
1408
+				wp_enqueue_script('autosave');
1409
+			} else {
1410
+				if (isset($this->_cpt_routes[$this->_req_data['action']])
1411
+					&& ! isset($this->_labels['hide_add_button_on_cpt_route'][$this->_req_data['action']])
1412
+				) {
1413
+					$create_new_action = apply_filters('FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1414
+						'create_new', $this);
1415
+					$post_new_file = EE_Admin_Page::add_query_args_and_nonce(array(
1416
+						'action' => $create_new_action,
1417
+						'page'   => $this->page_slug,
1418
+					), 'admin.php');
1419
+				}
1420
+			}
1421
+			include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1422
+		}
1423
+	}
1424
+
1425
+
1426
+
1427
+	public function add_new_admin_page_global()
1428
+	{
1429
+		$admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1430
+		?>
1431 1431
         <script type="text/javascript">
1432 1432
             adminpage = '<?php echo $admin_page; ?>';
1433 1433
         </script>
1434 1434
         <?php
1435
-    }
1436
-
1437
-
1438
-
1439
-    /**
1440
-     * default method for the 'edit' route for cpt admin pages
1441
-     * For reference on what to put in here, refer to wp-admin/post.php
1442
-     *
1443
-     * @access protected
1444
-     * @return string   template for edit cpt form
1445
-     */
1446
-    protected function _edit_cpt_item()
1447
-    {
1448
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1449
-        $post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1450
-        $post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1451
-        if (empty ($post)) {
1452
-            wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?'));
1453
-        }
1454
-        if ( ! empty($_GET['get-post-lock'])) {
1455
-            wp_set_post_lock($post_id);
1456
-            wp_redirect(get_edit_post_link($post_id, 'url'));
1457
-            exit();
1458
-        }
1459
-
1460
-        // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1461
-        $post_type        = $this->_cpt_routes[$this->_req_action];
1462
-        $post_type_object = $this->_cpt_object;
1463
-
1464
-        if ( ! wp_check_post_lock($post->ID)) {
1465
-            wp_set_post_lock($post->ID);
1466
-        }
1467
-        add_action('admin_footer', '_admin_notice_post_locked');
1468
-        if (post_type_supports($this->_cpt_routes[$this->_req_action], 'comments')) {
1469
-            wp_enqueue_script('admin-comments');
1470
-            enqueue_comment_hotkeys_js();
1471
-        }
1472
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1473
-        //modify the default editor title field with default title.
1474
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1475
-        $this->loadEditorTemplate(false);
1476
-    }
1477
-
1478
-
1479
-
1480
-    /**
1481
-     * some getters
1482
-     */
1483
-    /**
1484
-     * This returns the protected _cpt_model_obj property
1485
-     *
1486
-     * @return EE_CPT_Base
1487
-     */
1488
-    public function get_cpt_model_obj()
1489
-    {
1490
-        return $this->_cpt_model_obj;
1491
-    }
1435
+	}
1436
+
1437
+
1438
+
1439
+	/**
1440
+	 * default method for the 'edit' route for cpt admin pages
1441
+	 * For reference on what to put in here, refer to wp-admin/post.php
1442
+	 *
1443
+	 * @access protected
1444
+	 * @return string   template for edit cpt form
1445
+	 */
1446
+	protected function _edit_cpt_item()
1447
+	{
1448
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1449
+		$post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1450
+		$post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1451
+		if (empty ($post)) {
1452
+			wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?'));
1453
+		}
1454
+		if ( ! empty($_GET['get-post-lock'])) {
1455
+			wp_set_post_lock($post_id);
1456
+			wp_redirect(get_edit_post_link($post_id, 'url'));
1457
+			exit();
1458
+		}
1459
+
1460
+		// template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1461
+		$post_type        = $this->_cpt_routes[$this->_req_action];
1462
+		$post_type_object = $this->_cpt_object;
1463
+
1464
+		if ( ! wp_check_post_lock($post->ID)) {
1465
+			wp_set_post_lock($post->ID);
1466
+		}
1467
+		add_action('admin_footer', '_admin_notice_post_locked');
1468
+		if (post_type_supports($this->_cpt_routes[$this->_req_action], 'comments')) {
1469
+			wp_enqueue_script('admin-comments');
1470
+			enqueue_comment_hotkeys_js();
1471
+		}
1472
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1473
+		//modify the default editor title field with default title.
1474
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1475
+		$this->loadEditorTemplate(false);
1476
+	}
1477
+
1478
+
1479
+
1480
+	/**
1481
+	 * some getters
1482
+	 */
1483
+	/**
1484
+	 * This returns the protected _cpt_model_obj property
1485
+	 *
1486
+	 * @return EE_CPT_Base
1487
+	 */
1488
+	public function get_cpt_model_obj()
1489
+	{
1490
+		return $this->_cpt_model_obj;
1491
+	}
1492 1492
 
1493 1493
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
      */
240 240
     protected function _register_autosave_containers($ids)
241 241
     {
242
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array)$ids);
242
+        $this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
243 243
     }
244 244
 
245 245
 
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
         //filter _autosave_containers
287 287
         $containers = apply_filters('FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
288 288
             $this->_autosave_containers, $this);
289
-        $containers = apply_filters('FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
289
+        $containers = apply_filters('FHEE__EE_Admin_Page_CPT__'.get_class($this).'___load_autosave_scripts_styles__containers',
290 290
             $containers, $this);
291 291
 
292 292
         wp_localize_script('event_editor_js', 'EE_AUTOSAVE_IDS',
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
         // This is for any plugins that are doing things properly
399 399
         // and hooking into the load page hook for core wp cpt routes.
400 400
         global $pagenow;
401
-        do_action('load-' . $pagenow);
401
+        do_action('load-'.$pagenow);
402 402
         $this->modify_current_screen();
403 403
         add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
404 404
         //we route REALLY early.
@@ -429,8 +429,8 @@  discard block
 block discarded – undo
429 429
                 'admin.php?page=espresso_registrations&action=contact_list',
430 430
             ),
431 431
             1 => array(
432
-                'edit.php?post_type=' . $this->_cpt_object->name,
433
-                'admin.php?page=' . $this->_cpt_object->name,
432
+                'edit.php?post_type='.$this->_cpt_object->name,
433
+                'admin.php?page='.$this->_cpt_object->name,
434 434
             ),
435 435
         );
436 436
         foreach ($routes_to_match as $route_matches) {
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
         $cpt_has_support = ! empty($cpt_args['page_templates']);
459 459
 
460 460
         //if the installed version of WP is > 4.7 we do some additional checks.
461
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
461
+        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
462 462
             $post_templates = wp_get_theme()->get_post_templates();
463 463
             //if there are $post_templates for this cpt, then we return false for this method because
464 464
             //that means we aren't going to load our page template manager and leave that up to the native
@@ -481,7 +481,7 @@  discard block
 block discarded – undo
481 481
         global $post;
482 482
         $template = '';
483 483
 
484
-        if (RecommendedVersions::compareWordPressVersion('4.7','>=')) {
484
+        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
485 485
             $page_template_count = count(get_page_templates());
486 486
         } else {
487 487
             $page_template_count = count(get_page_templates($post));
@@ -518,7 +518,7 @@  discard block
 block discarded – undo
518 518
         $post = get_post($id);
519 519
         if ('publish' !== get_post_status($post)) {
520 520
             //include shims for the `get_preview_post_link` function
521
-            require_once( EE_CORE . 'wordpress-shims.php' );
521
+            require_once(EE_CORE.'wordpress-shims.php');
522 522
             $return .= '<span_id="view-post-btn"><a target="_blank" href="'
523 523
                        . get_preview_post_link($id)
524 524
                        . '" class="button button-small">'
@@ -556,7 +556,7 @@  discard block
 block discarded – undo
556 556
             $template_args['statuses']         = $statuses;
557 557
         }
558 558
 
559
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
559
+        $template = EE_ADMIN_TEMPLATE.'status_dropdown.template.php';
560 560
         EEH_Template::display_template($template, $template_args);
561 561
     }
562 562
 
@@ -610,7 +610,7 @@  discard block
 block discarded – undo
610 610
             $this->_template_args['success'] = true;
611 611
         }
612 612
         do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
613
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
613
+        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_'.get_class($this), $this);
614 614
         //now let's return json
615 615
         $this->_return_json();
616 616
     }
@@ -1013,7 +1013,7 @@  discard block
 block discarded – undo
1013 1013
         //global action
1014 1014
         do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1015 1015
         //class specific action so you can limit hooking into a specific page.
1016
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1016
+        do_action('AHEE_EE_Admin_Page_CPT_'.get_class($this).'__restore_revision', $post_id, $revision_id);
1017 1017
     }
1018 1018
 
1019 1019
 
@@ -1091,7 +1091,7 @@  discard block
 block discarded – undo
1091 1091
         if ( ! empty($id) && get_option('permalink_structure') !== '') {
1092 1092
             $post = get_post($id);
1093 1093
             if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1094
-                $shortlink = home_url('?p=' . $post->ID);
1094
+                $shortlink = home_url('?p='.$post->ID);
1095 1095
             }
1096 1096
         }
1097 1097
         return $shortlink;
@@ -1126,11 +1126,11 @@  discard block
 block discarded – undo
1126 1126
      */
1127 1127
     public function cpt_post_form_hidden_input()
1128 1128
     {
1129
-        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1129
+        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="'.$this->_admin_base_url.'" />';
1130 1130
         //we're also going to add the route value and the current page so we can direct autosave parsing correctly
1131 1131
         echo '<div id="ee-cpt-hidden-inputs">';
1132
-        echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1133
-        echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1132
+        echo '<input type="hidden" id="current_route" name="current_route" value="'.$this->_current_view.'" />';
1133
+        echo '<input type="hidden" id="current_page" name="current_page" value="'.$this->page_slug.'" />';
1134 1134
         echo '</div>';
1135 1135
     }
1136 1136
 
@@ -1217,7 +1217,7 @@  discard block
 block discarded – undo
1217 1217
         $this->_set_model_object($post->ID, true);
1218 1218
 
1219 1219
         //returns something like `trash_event` or `trash_attendee` or `trash_venue`
1220
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1220
+        $action = 'trash_'.str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1221 1221
 
1222 1222
         return EE_Admin_Page::add_query_args_and_nonce(
1223 1223
             array(
@@ -1328,39 +1328,39 @@  discard block
 block discarded – undo
1328 1328
             1 => sprintf(
1329 1329
                 __('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1330 1330
                 $this->_cpt_object->labels->singular_name,
1331
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1331
+                '<a href="'.esc_url(get_permalink($id)).'">',
1332 1332
                 '</a>'
1333 1333
             ),
1334 1334
             2 => __('Custom field updated'),
1335 1335
             3 => __('Custom field deleted.'),
1336 1336
             4 => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1337 1337
             5 => isset($_GET['revision']) ? sprintf(__('%s restored to revision from %s', 'event_espresso'),
1338
-                $this->_cpt_object->labels->singular_name, wp_post_revision_title((int)$_GET['revision'], false))
1338
+                $this->_cpt_object->labels->singular_name, wp_post_revision_title((int) $_GET['revision'], false))
1339 1339
                 : false,
1340 1340
             6 => sprintf(
1341 1341
                 __('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1342 1342
                 $this->_cpt_object->labels->singular_name,
1343
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1343
+                '<a href="'.esc_url(get_permalink($id)).'">',
1344 1344
                 '</a>'
1345 1345
             ),
1346 1346
             7 => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1347 1347
             8 => sprintf(
1348 1348
                 __('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1349 1349
                 $this->_cpt_object->labels->singular_name,
1350
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1350
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))).'">',
1351 1351
                 '</a>'
1352 1352
             ),
1353 1353
             9 => sprintf(
1354 1354
                 __('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1355 1355
                 $this->_cpt_object->labels->singular_name,
1356
-                '<strong>' . date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)) . '</strong>',
1357
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1356
+                '<strong>'.date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date)).'</strong>',
1357
+                '<a target="_blank" href="'.esc_url(get_permalink($id)),
1358 1358
                 '</a>'
1359 1359
             ),
1360 1360
             10 => sprintf(
1361 1361
                 __('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1362 1362
                 $this->_cpt_object->labels->singular_name,
1363
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1363
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1364 1364
                 '</a>'
1365 1365
             ),
1366 1366
         );
@@ -1383,7 +1383,7 @@  discard block
 block discarded – undo
1383 1383
         $post_type        = $this->_cpt_routes[$this->_req_action];
1384 1384
         $post_type_object = $this->_cpt_object;
1385 1385
         $title            = $post_type_object->labels->add_new_item;
1386
-        $post    = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1386
+        $post = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1387 1387
         add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1388 1388
         //modify the default editor title field with default title.
1389 1389
         add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
@@ -1418,7 +1418,7 @@  discard block
 block discarded – undo
1418 1418
                     ), 'admin.php');
1419 1419
                 }
1420 1420
             }
1421
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1421
+            include_once WP_ADMIN_PATH.'edit-form-advanced.php';
1422 1422
         }
1423 1423
     }
1424 1424
 
Please login to merge, or discard this patch.
core/libraries/form_sections/form_handlers/FormHandler.php 1 patch
Indentation   +643 added lines, -643 removed lines patch added patch discarded remove patch
@@ -15,7 +15,7 @@  discard block
 block discarded – undo
15 15
 use EventEspresso\core\exceptions\InvalidFormSubmissionException;
16 16
 
17 17
 if (! defined('EVENT_ESPRESSO_VERSION')) {
18
-    exit('No direct script access allowed');
18
+	exit('No direct script access allowed');
19 19
 }
20 20
 
21 21
 
@@ -34,648 +34,648 @@  discard block
 block discarded – undo
34 34
 abstract class FormHandler implements FormHandlerInterface
35 35
 {
36 36
 
37
-    /**
38
-     * will add opening and closing HTML form tags as well as a submit button
39
-     */
40
-    const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
41
-
42
-    /**
43
-     * will add opening and closing HTML form tags but NOT a submit button
44
-     */
45
-    const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
46
-
47
-    /**
48
-     * will NOT add opening and closing HTML form tags but will add a submit button
49
-     */
50
-    const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
51
-
52
-    /**
53
-     * will NOT add opening and closing HTML form tags NOR a submit button
54
-     */
55
-    const DO_NOT_SETUP_FORM = 'do_not_setup_form';
56
-
57
-    /**
58
-     * if set to false, then this form has no displayable content,
59
-     * and will only be used for processing data sent passed via GET or POST
60
-     * defaults to true ( ie: form has displayable content )
61
-     *
62
-     * @var boolean $displayable
63
-     */
64
-    private $displayable = true;
65
-
66
-    /**
67
-     * @var string $form_name
68
-     */
69
-    private $form_name;
70
-
71
-    /**
72
-     * @var string $admin_name
73
-     */
74
-    private $admin_name;
75
-
76
-    /**
77
-     * @var string $slug
78
-     */
79
-    private $slug;
80
-
81
-    /**
82
-     * @var string $submit_btn_text
83
-     */
84
-    private $submit_btn_text;
85
-
86
-    /**
87
-     * @var string $form_action
88
-     */
89
-    private $form_action;
90
-
91
-    /**
92
-     * form params in key value pairs
93
-     * can be added to form action URL or as hidden inputs
94
-     *
95
-     * @var array $form_args
96
-     */
97
-    private $form_args = array();
98
-
99
-    /**
100
-     * value of one of the string constant above
101
-     *
102
-     * @var string $form_config
103
-     */
104
-    private $form_config;
105
-
106
-    /**
107
-     * whether or not the form was determined to be invalid
108
-     *
109
-     * @var boolean $form_has_errors
110
-     */
111
-    private $form_has_errors;
112
-
113
-    /**
114
-     * the absolute top level form section being used on the page
115
-     *
116
-     * @var EE_Form_Section_Proper $form
117
-     */
118
-    private $form;
119
-
120
-    /**
121
-     * @var EE_Registry $registry
122
-     */
123
-    protected $registry;
124
-
125
-
126
-
127
-    /**
128
-     * Form constructor.
129
-     *
130
-     * @param string      $form_name
131
-     * @param string      $admin_name
132
-     * @param string      $slug
133
-     * @param string      $form_action
134
-     * @param string      $form_config
135
-     * @param EE_Registry $registry
136
-     * @throws InvalidDataTypeException
137
-     * @throws DomainException
138
-     * @throws InvalidArgumentException
139
-     */
140
-    public function __construct(
141
-        $form_name,
142
-        $admin_name,
143
-        $slug,
144
-        $form_action = '',
145
-        $form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
146
-        EE_Registry $registry
147
-    ) {
148
-        $this->setFormName($form_name);
149
-        $this->setAdminName($admin_name);
150
-        $this->setSlug($slug);
151
-        $this->setFormAction($form_action);
152
-        $this->setFormConfig($form_config);
153
-        $this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
154
-        $this->registry = $registry;
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * @return array
161
-     */
162
-    public static function getFormConfigConstants()
163
-    {
164
-        return array(
165
-            FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
166
-            FormHandler::ADD_FORM_TAGS_ONLY,
167
-            FormHandler::ADD_FORM_SUBMIT_ONLY,
168
-            FormHandler::DO_NOT_SETUP_FORM,
169
-        );
170
-    }
171
-
172
-
173
-
174
-    /**
175
-     * @param bool $for_display
176
-     * @return EE_Form_Section_Proper
177
-     * @throws EE_Error
178
-     * @throws LogicException
179
-     */
180
-    public function form($for_display = false)
181
-    {
182
-        if (! $this->formIsValid()) {
183
-            return null;
184
-        }
185
-        if ($for_display) {
186
-            $form_config = $this->formConfig();
187
-            if (
188
-                $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
189
-                || $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
190
-            ) {
191
-                $this->appendSubmitButton();
192
-                $this->clearFormButtonFloats();
193
-            }
194
-        }
195
-        return $this->form;
196
-    }
197
-
198
-
199
-
200
-    /**
201
-     * @return boolean
202
-     * @throws LogicException
203
-     */
204
-    public function formIsValid()
205
-    {
206
-        if ($this->form instanceof EE_Form_Section_Proper) {
207
-            return true;
208
-        }
209
-        $form = apply_filters(
210
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
211
-            $this->generate(),
212
-            $this
213
-        );
214
-        if ($this->verifyForm($form)) {
215
-            $this->setForm($form);
216
-        }
217
-        return true;
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * @param EE_Form_Section_Proper|null $form
224
-     * @return bool
225
-     * @throws LogicException
226
-     */
227
-    public function verifyForm(EE_Form_Section_Proper $form = null)
228
-    {
229
-        $form = $form !== null ? $form : $this->form;
230
-        if ($form instanceof EE_Form_Section_Proper) {
231
-            return true;
232
-        }
233
-        throw new LogicException(
234
-            sprintf(
235
-                esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
236
-                $this->form_name,
237
-                var_export($form, true)
238
-            )
239
-        );
240
-    }
241
-
242
-
243
-
244
-    /**
245
-     * @param EE_Form_Section_Proper $form
246
-     */
247
-    public function setForm(EE_Form_Section_Proper $form)
248
-    {
249
-        $this->form = $form;
250
-    }
251
-
252
-
253
-
254
-    /**
255
-     * @return boolean
256
-     */
257
-    public function displayable()
258
-    {
259
-        return $this->displayable;
260
-    }
261
-
262
-
263
-
264
-    /**
265
-     * @param boolean $displayable
266
-     */
267
-    public function setDisplayable($displayable = false)
268
-    {
269
-        $this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
270
-    }
271
-
272
-
273
-
274
-    /**
275
-     * a public name for the form that can be displayed on the frontend of a site
276
-     *
277
-     * @return string
278
-     */
279
-    public function formName()
280
-    {
281
-        return $this->form_name;
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @param string $form_name
288
-     * @throws InvalidDataTypeException
289
-     */
290
-    public function setFormName($form_name)
291
-    {
292
-        if (! is_string($form_name)) {
293
-            throw new InvalidDataTypeException('$form_name', $form_name, 'string');
294
-        }
295
-        $this->form_name = $form_name;
296
-    }
297
-
298
-
299
-
300
-    /**
301
-     * a public name for the form that can be displayed, but only in the admin
302
-     *
303
-     * @return string
304
-     */
305
-    public function adminName()
306
-    {
307
-        return $this->admin_name;
308
-    }
309
-
310
-
311
-
312
-    /**
313
-     * @param string $admin_name
314
-     * @throws InvalidDataTypeException
315
-     */
316
-    public function setAdminName($admin_name)
317
-    {
318
-        if (! is_string($admin_name)) {
319
-            throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
320
-        }
321
-        $this->admin_name = $admin_name;
322
-    }
323
-
324
-
325
-
326
-    /**
327
-     * a URL friendly string that can be used for identifying the form
328
-     *
329
-     * @return string
330
-     */
331
-    public function slug()
332
-    {
333
-        return $this->slug;
334
-    }
335
-
336
-
337
-
338
-    /**
339
-     * @param string $slug
340
-     * @throws InvalidDataTypeException
341
-     */
342
-    public function setSlug($slug)
343
-    {
344
-        if (! is_string($slug)) {
345
-            throw new InvalidDataTypeException('$slug', $slug, 'string');
346
-        }
347
-        $this->slug = $slug;
348
-    }
349
-
350
-
351
-
352
-    /**
353
-     * @return string
354
-     */
355
-    public function submitBtnText()
356
-    {
357
-        return $this->submit_btn_text;
358
-    }
359
-
360
-
361
-
362
-    /**
363
-     * @param string $submit_btn_text
364
-     * @throws InvalidDataTypeException
365
-     * @throws InvalidArgumentException
366
-     */
367
-    public function setSubmitBtnText($submit_btn_text)
368
-    {
369
-        if (! is_string($submit_btn_text)) {
370
-            throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
371
-        }
372
-        if (empty($submit_btn_text)) {
373
-            throw new InvalidArgumentException(
374
-                esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
375
-            );
376
-        }
377
-        $this->submit_btn_text = $submit_btn_text;
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     * @return string
384
-     */
385
-    public function formAction()
386
-    {
387
-        return ! empty($this->form_args)
388
-            ? add_query_arg($this->form_args, $this->form_action)
389
-            : $this->form_action;
390
-    }
391
-
392
-
393
-
394
-    /**
395
-     * @param string $form_action
396
-     * @throws InvalidDataTypeException
397
-     */
398
-    public function setFormAction($form_action)
399
-    {
400
-        if (! is_string($form_action)) {
401
-            throw new InvalidDataTypeException('$form_action', $form_action, 'string');
402
-        }
403
-        $this->form_action = $form_action;
404
-    }
405
-
406
-
407
-
408
-    /**
409
-     * @param array $form_args
410
-     * @throws InvalidDataTypeException
411
-     * @throws InvalidArgumentException
412
-     */
413
-    public function addFormActionArgs($form_args = array())
414
-    {
415
-        if (is_object($form_args)) {
416
-            throw new InvalidDataTypeException(
417
-                '$form_args',
418
-                $form_args,
419
-                'anything other than an object was expected.'
420
-            );
421
-        }
422
-        if (empty($form_args)) {
423
-            throw new InvalidArgumentException(
424
-                esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
425
-            );
426
-        }
427
-        $this->form_args = array_merge($this->form_args, $form_args);
428
-    }
429
-
430
-
431
-
432
-    /**
433
-     * @return string
434
-     */
435
-    public function formConfig()
436
-    {
437
-        return $this->form_config;
438
-    }
439
-
440
-
441
-
442
-    /**
443
-     * @param string $form_config
444
-     * @throws DomainException
445
-     */
446
-    public function setFormConfig($form_config)
447
-    {
448
-        if (
449
-        ! in_array(
450
-            $form_config,
451
-            array(
452
-                FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
453
-                FormHandler::ADD_FORM_TAGS_ONLY,
454
-                FormHandler::ADD_FORM_SUBMIT_ONLY,
455
-                FormHandler::DO_NOT_SETUP_FORM,
456
-            ),
457
-            true
458
-        )
459
-        ) {
460
-            throw new DomainException(
461
-                sprintf(
462
-                    esc_html__('"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
463
-                        'event_espresso'),
464
-                    $form_config
465
-                )
466
-            );
467
-        }
468
-        $this->form_config = $form_config;
469
-    }
470
-
471
-
472
-
473
-    /**
474
-     * called after the form is instantiated
475
-     * and used for performing any logic that needs to occur early
476
-     * before any of the other methods are called.
477
-     * returns true if everything is ok to proceed,
478
-     * and false if no further form logic should be implemented
479
-     *
480
-     * @return boolean
481
-     */
482
-    public function initialize()
483
-    {
484
-        $this->form_has_errors = EE_Error::has_error(true);
485
-        return true;
486
-    }
487
-
488
-
489
-
490
-    /**
491
-     * used for setting up css and js
492
-     *
493
-     * @return void
494
-     * @throws LogicException
495
-     * @throws EE_Error
496
-     */
497
-    public function enqueueStylesAndScripts()
498
-    {
499
-        $this->form()->enqueue_js();
500
-    }
501
-
502
-
503
-
504
-    /**
505
-     * creates and returns the actual form
506
-     *
507
-     * @return EE_Form_Section_Proper
508
-     */
509
-    abstract public function generate();
510
-
511
-
512
-
513
-    /**
514
-     * creates and returns an EE_Submit_Input labeled "Submit"
515
-     *
516
-     * @param string $text
517
-     * @return EE_Submit_Input
518
-     */
519
-    public function generateSubmitButton($text = '')
520
-    {
521
-        $text = ! empty($text) ? $text : $this->submitBtnText();
522
-        return new EE_Submit_Input(
523
-            array(
524
-                'html_name'             => 'ee-form-submit-' . $this->slug(),
525
-                'html_id'               => 'ee-form-submit-' . $this->slug(),
526
-                'html_class'            => 'ee-form-submit',
527
-                'html_label'            => '&nbsp;',
528
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
529
-                'default'               => $text,
530
-            )
531
-        );
532
-    }
533
-
534
-
535
-
536
-    /**
537
-     * calls generateSubmitButton() and appends it onto the form along with a float clearing div
538
-     *
539
-     * @param string $text
540
-     * @return void
541
-     * @throws EE_Error
542
-     */
543
-    public function appendSubmitButton($text = '')
544
-    {
545
-        if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
546
-            return;
547
-        }
548
-        $this->form->add_subsections(
549
-            array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
550
-            null,
551
-            false
552
-        );
553
-    }
554
-
555
-
556
-
557
-    /**
558
-     * creates and returns an EE_Submit_Input labeled "Cancel"
559
-     *
560
-     * @param string $text
561
-     * @return EE_Submit_Input
562
-     */
563
-    public function generateCancelButton($text = '')
564
-    {
565
-        $cancel_button = new EE_Submit_Input(
566
-            array(
567
-                'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
568
-                'html_id'               => 'ee-cancel-form-' . $this->slug(),
569
-                'html_class'            => 'ee-cancel-form',
570
-                'html_label'            => '&nbsp;',
571
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
572
-                'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
573
-            )
574
-        );
575
-        $cancel_button->set_button_css_attributes(false);
576
-        return $cancel_button;
577
-    }
578
-
579
-
580
-
581
-    /**
582
-     * appends a float clearing div onto end of form
583
-     *
584
-     * @return void
585
-     * @throws EE_Error
586
-     */
587
-    public function clearFormButtonFloats()
588
-    {
589
-        $this->form->add_subsections(
590
-            array(
591
-                'clear-submit-btn-float' => new EE_Form_Section_HTML(
592
-                    EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
593
-                ),
594
-            ),
595
-            null,
596
-            false
597
-        );
598
-    }
599
-
600
-
601
-    /**
602
-     * takes the generated form and displays it along with ony other non-form HTML that may be required
603
-     * returns a string of HTML that can be directly echoed in a template
604
-     *
605
-     * @return string
606
-     * @throws \InvalidArgumentException
607
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
608
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
609
-     * @throws LogicException
610
-     * @throws EE_Error
611
-     */
612
-    public function display()
613
-    {
614
-        $form_html = apply_filters(
615
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
616
-            ''
617
-        );
618
-        $form_config = $this->formConfig();
619
-        if (
620
-            $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
621
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
622
-        ) {
623
-            $form_html .= $this->form()->form_open($this->formAction());
624
-        }
625
-        $form_html .= $this->form(true)->get_html($this->form_has_errors);
626
-        if (
627
-            $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
628
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
629
-        ) {
630
-            $form_html .= $this->form()->form_close();
631
-        }
632
-        $form_html .= apply_filters(
633
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
634
-            ''
635
-        );
636
-        return $form_html;
637
-    }
638
-
639
-
640
-    /**
641
-     * handles processing the form submission
642
-     * returns true or false depending on whether the form was processed successfully or not
643
-     *
644
-     * @param array $submitted_form_data
645
-     * @return array
646
-     * @throws \InvalidArgumentException
647
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
648
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
649
-     * @throws EE_Error
650
-     * @throws LogicException
651
-     * @throws InvalidFormSubmissionException
652
-     */
653
-    public function process($submitted_form_data = array())
654
-    {
655
-        if (! $this->form()->was_submitted($submitted_form_data)) {
656
-            throw new InvalidFormSubmissionException($this->form_name);
657
-        }
658
-        $this->form(true)->receive_form_submission($submitted_form_data);
659
-        if (! $this->form()->is_valid()) {
660
-            throw new InvalidFormSubmissionException(
661
-                $this->form_name,
662
-                sprintf(
663
-                    esc_html__(
664
-                        'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
665
-                        'event_espresso'
666
-                    ),
667
-                    $this->form_name,
668
-                    '<br />',
669
-                    implode('<br />', $this->form()->get_validation_errors_accumulated())
670
-                )
671
-            );
672
-        }
673
-        return apply_filters(
674
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
675
-            $this->form()->valid_data(),
676
-            $this
677
-        );
678
-    }
37
+	/**
38
+	 * will add opening and closing HTML form tags as well as a submit button
39
+	 */
40
+	const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
41
+
42
+	/**
43
+	 * will add opening and closing HTML form tags but NOT a submit button
44
+	 */
45
+	const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
46
+
47
+	/**
48
+	 * will NOT add opening and closing HTML form tags but will add a submit button
49
+	 */
50
+	const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
51
+
52
+	/**
53
+	 * will NOT add opening and closing HTML form tags NOR a submit button
54
+	 */
55
+	const DO_NOT_SETUP_FORM = 'do_not_setup_form';
56
+
57
+	/**
58
+	 * if set to false, then this form has no displayable content,
59
+	 * and will only be used for processing data sent passed via GET or POST
60
+	 * defaults to true ( ie: form has displayable content )
61
+	 *
62
+	 * @var boolean $displayable
63
+	 */
64
+	private $displayable = true;
65
+
66
+	/**
67
+	 * @var string $form_name
68
+	 */
69
+	private $form_name;
70
+
71
+	/**
72
+	 * @var string $admin_name
73
+	 */
74
+	private $admin_name;
75
+
76
+	/**
77
+	 * @var string $slug
78
+	 */
79
+	private $slug;
80
+
81
+	/**
82
+	 * @var string $submit_btn_text
83
+	 */
84
+	private $submit_btn_text;
85
+
86
+	/**
87
+	 * @var string $form_action
88
+	 */
89
+	private $form_action;
90
+
91
+	/**
92
+	 * form params in key value pairs
93
+	 * can be added to form action URL or as hidden inputs
94
+	 *
95
+	 * @var array $form_args
96
+	 */
97
+	private $form_args = array();
98
+
99
+	/**
100
+	 * value of one of the string constant above
101
+	 *
102
+	 * @var string $form_config
103
+	 */
104
+	private $form_config;
105
+
106
+	/**
107
+	 * whether or not the form was determined to be invalid
108
+	 *
109
+	 * @var boolean $form_has_errors
110
+	 */
111
+	private $form_has_errors;
112
+
113
+	/**
114
+	 * the absolute top level form section being used on the page
115
+	 *
116
+	 * @var EE_Form_Section_Proper $form
117
+	 */
118
+	private $form;
119
+
120
+	/**
121
+	 * @var EE_Registry $registry
122
+	 */
123
+	protected $registry;
124
+
125
+
126
+
127
+	/**
128
+	 * Form constructor.
129
+	 *
130
+	 * @param string      $form_name
131
+	 * @param string      $admin_name
132
+	 * @param string      $slug
133
+	 * @param string      $form_action
134
+	 * @param string      $form_config
135
+	 * @param EE_Registry $registry
136
+	 * @throws InvalidDataTypeException
137
+	 * @throws DomainException
138
+	 * @throws InvalidArgumentException
139
+	 */
140
+	public function __construct(
141
+		$form_name,
142
+		$admin_name,
143
+		$slug,
144
+		$form_action = '',
145
+		$form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
146
+		EE_Registry $registry
147
+	) {
148
+		$this->setFormName($form_name);
149
+		$this->setAdminName($admin_name);
150
+		$this->setSlug($slug);
151
+		$this->setFormAction($form_action);
152
+		$this->setFormConfig($form_config);
153
+		$this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
154
+		$this->registry = $registry;
155
+	}
156
+
157
+
158
+
159
+	/**
160
+	 * @return array
161
+	 */
162
+	public static function getFormConfigConstants()
163
+	{
164
+		return array(
165
+			FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
166
+			FormHandler::ADD_FORM_TAGS_ONLY,
167
+			FormHandler::ADD_FORM_SUBMIT_ONLY,
168
+			FormHandler::DO_NOT_SETUP_FORM,
169
+		);
170
+	}
171
+
172
+
173
+
174
+	/**
175
+	 * @param bool $for_display
176
+	 * @return EE_Form_Section_Proper
177
+	 * @throws EE_Error
178
+	 * @throws LogicException
179
+	 */
180
+	public function form($for_display = false)
181
+	{
182
+		if (! $this->formIsValid()) {
183
+			return null;
184
+		}
185
+		if ($for_display) {
186
+			$form_config = $this->formConfig();
187
+			if (
188
+				$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
189
+				|| $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
190
+			) {
191
+				$this->appendSubmitButton();
192
+				$this->clearFormButtonFloats();
193
+			}
194
+		}
195
+		return $this->form;
196
+	}
197
+
198
+
199
+
200
+	/**
201
+	 * @return boolean
202
+	 * @throws LogicException
203
+	 */
204
+	public function formIsValid()
205
+	{
206
+		if ($this->form instanceof EE_Form_Section_Proper) {
207
+			return true;
208
+		}
209
+		$form = apply_filters(
210
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
211
+			$this->generate(),
212
+			$this
213
+		);
214
+		if ($this->verifyForm($form)) {
215
+			$this->setForm($form);
216
+		}
217
+		return true;
218
+	}
219
+
220
+
221
+
222
+	/**
223
+	 * @param EE_Form_Section_Proper|null $form
224
+	 * @return bool
225
+	 * @throws LogicException
226
+	 */
227
+	public function verifyForm(EE_Form_Section_Proper $form = null)
228
+	{
229
+		$form = $form !== null ? $form : $this->form;
230
+		if ($form instanceof EE_Form_Section_Proper) {
231
+			return true;
232
+		}
233
+		throw new LogicException(
234
+			sprintf(
235
+				esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
236
+				$this->form_name,
237
+				var_export($form, true)
238
+			)
239
+		);
240
+	}
241
+
242
+
243
+
244
+	/**
245
+	 * @param EE_Form_Section_Proper $form
246
+	 */
247
+	public function setForm(EE_Form_Section_Proper $form)
248
+	{
249
+		$this->form = $form;
250
+	}
251
+
252
+
253
+
254
+	/**
255
+	 * @return boolean
256
+	 */
257
+	public function displayable()
258
+	{
259
+		return $this->displayable;
260
+	}
261
+
262
+
263
+
264
+	/**
265
+	 * @param boolean $displayable
266
+	 */
267
+	public function setDisplayable($displayable = false)
268
+	{
269
+		$this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
270
+	}
271
+
272
+
273
+
274
+	/**
275
+	 * a public name for the form that can be displayed on the frontend of a site
276
+	 *
277
+	 * @return string
278
+	 */
279
+	public function formName()
280
+	{
281
+		return $this->form_name;
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @param string $form_name
288
+	 * @throws InvalidDataTypeException
289
+	 */
290
+	public function setFormName($form_name)
291
+	{
292
+		if (! is_string($form_name)) {
293
+			throw new InvalidDataTypeException('$form_name', $form_name, 'string');
294
+		}
295
+		$this->form_name = $form_name;
296
+	}
297
+
298
+
299
+
300
+	/**
301
+	 * a public name for the form that can be displayed, but only in the admin
302
+	 *
303
+	 * @return string
304
+	 */
305
+	public function adminName()
306
+	{
307
+		return $this->admin_name;
308
+	}
309
+
310
+
311
+
312
+	/**
313
+	 * @param string $admin_name
314
+	 * @throws InvalidDataTypeException
315
+	 */
316
+	public function setAdminName($admin_name)
317
+	{
318
+		if (! is_string($admin_name)) {
319
+			throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
320
+		}
321
+		$this->admin_name = $admin_name;
322
+	}
323
+
324
+
325
+
326
+	/**
327
+	 * a URL friendly string that can be used for identifying the form
328
+	 *
329
+	 * @return string
330
+	 */
331
+	public function slug()
332
+	{
333
+		return $this->slug;
334
+	}
335
+
336
+
337
+
338
+	/**
339
+	 * @param string $slug
340
+	 * @throws InvalidDataTypeException
341
+	 */
342
+	public function setSlug($slug)
343
+	{
344
+		if (! is_string($slug)) {
345
+			throw new InvalidDataTypeException('$slug', $slug, 'string');
346
+		}
347
+		$this->slug = $slug;
348
+	}
349
+
350
+
351
+
352
+	/**
353
+	 * @return string
354
+	 */
355
+	public function submitBtnText()
356
+	{
357
+		return $this->submit_btn_text;
358
+	}
359
+
360
+
361
+
362
+	/**
363
+	 * @param string $submit_btn_text
364
+	 * @throws InvalidDataTypeException
365
+	 * @throws InvalidArgumentException
366
+	 */
367
+	public function setSubmitBtnText($submit_btn_text)
368
+	{
369
+		if (! is_string($submit_btn_text)) {
370
+			throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
371
+		}
372
+		if (empty($submit_btn_text)) {
373
+			throw new InvalidArgumentException(
374
+				esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
375
+			);
376
+		}
377
+		$this->submit_btn_text = $submit_btn_text;
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * @return string
384
+	 */
385
+	public function formAction()
386
+	{
387
+		return ! empty($this->form_args)
388
+			? add_query_arg($this->form_args, $this->form_action)
389
+			: $this->form_action;
390
+	}
391
+
392
+
393
+
394
+	/**
395
+	 * @param string $form_action
396
+	 * @throws InvalidDataTypeException
397
+	 */
398
+	public function setFormAction($form_action)
399
+	{
400
+		if (! is_string($form_action)) {
401
+			throw new InvalidDataTypeException('$form_action', $form_action, 'string');
402
+		}
403
+		$this->form_action = $form_action;
404
+	}
405
+
406
+
407
+
408
+	/**
409
+	 * @param array $form_args
410
+	 * @throws InvalidDataTypeException
411
+	 * @throws InvalidArgumentException
412
+	 */
413
+	public function addFormActionArgs($form_args = array())
414
+	{
415
+		if (is_object($form_args)) {
416
+			throw new InvalidDataTypeException(
417
+				'$form_args',
418
+				$form_args,
419
+				'anything other than an object was expected.'
420
+			);
421
+		}
422
+		if (empty($form_args)) {
423
+			throw new InvalidArgumentException(
424
+				esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
425
+			);
426
+		}
427
+		$this->form_args = array_merge($this->form_args, $form_args);
428
+	}
429
+
430
+
431
+
432
+	/**
433
+	 * @return string
434
+	 */
435
+	public function formConfig()
436
+	{
437
+		return $this->form_config;
438
+	}
439
+
440
+
441
+
442
+	/**
443
+	 * @param string $form_config
444
+	 * @throws DomainException
445
+	 */
446
+	public function setFormConfig($form_config)
447
+	{
448
+		if (
449
+		! in_array(
450
+			$form_config,
451
+			array(
452
+				FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
453
+				FormHandler::ADD_FORM_TAGS_ONLY,
454
+				FormHandler::ADD_FORM_SUBMIT_ONLY,
455
+				FormHandler::DO_NOT_SETUP_FORM,
456
+			),
457
+			true
458
+		)
459
+		) {
460
+			throw new DomainException(
461
+				sprintf(
462
+					esc_html__('"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
463
+						'event_espresso'),
464
+					$form_config
465
+				)
466
+			);
467
+		}
468
+		$this->form_config = $form_config;
469
+	}
470
+
471
+
472
+
473
+	/**
474
+	 * called after the form is instantiated
475
+	 * and used for performing any logic that needs to occur early
476
+	 * before any of the other methods are called.
477
+	 * returns true if everything is ok to proceed,
478
+	 * and false if no further form logic should be implemented
479
+	 *
480
+	 * @return boolean
481
+	 */
482
+	public function initialize()
483
+	{
484
+		$this->form_has_errors = EE_Error::has_error(true);
485
+		return true;
486
+	}
487
+
488
+
489
+
490
+	/**
491
+	 * used for setting up css and js
492
+	 *
493
+	 * @return void
494
+	 * @throws LogicException
495
+	 * @throws EE_Error
496
+	 */
497
+	public function enqueueStylesAndScripts()
498
+	{
499
+		$this->form()->enqueue_js();
500
+	}
501
+
502
+
503
+
504
+	/**
505
+	 * creates and returns the actual form
506
+	 *
507
+	 * @return EE_Form_Section_Proper
508
+	 */
509
+	abstract public function generate();
510
+
511
+
512
+
513
+	/**
514
+	 * creates and returns an EE_Submit_Input labeled "Submit"
515
+	 *
516
+	 * @param string $text
517
+	 * @return EE_Submit_Input
518
+	 */
519
+	public function generateSubmitButton($text = '')
520
+	{
521
+		$text = ! empty($text) ? $text : $this->submitBtnText();
522
+		return new EE_Submit_Input(
523
+			array(
524
+				'html_name'             => 'ee-form-submit-' . $this->slug(),
525
+				'html_id'               => 'ee-form-submit-' . $this->slug(),
526
+				'html_class'            => 'ee-form-submit',
527
+				'html_label'            => '&nbsp;',
528
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
529
+				'default'               => $text,
530
+			)
531
+		);
532
+	}
533
+
534
+
535
+
536
+	/**
537
+	 * calls generateSubmitButton() and appends it onto the form along with a float clearing div
538
+	 *
539
+	 * @param string $text
540
+	 * @return void
541
+	 * @throws EE_Error
542
+	 */
543
+	public function appendSubmitButton($text = '')
544
+	{
545
+		if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
546
+			return;
547
+		}
548
+		$this->form->add_subsections(
549
+			array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
550
+			null,
551
+			false
552
+		);
553
+	}
554
+
555
+
556
+
557
+	/**
558
+	 * creates and returns an EE_Submit_Input labeled "Cancel"
559
+	 *
560
+	 * @param string $text
561
+	 * @return EE_Submit_Input
562
+	 */
563
+	public function generateCancelButton($text = '')
564
+	{
565
+		$cancel_button = new EE_Submit_Input(
566
+			array(
567
+				'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
568
+				'html_id'               => 'ee-cancel-form-' . $this->slug(),
569
+				'html_class'            => 'ee-cancel-form',
570
+				'html_label'            => '&nbsp;',
571
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
572
+				'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
573
+			)
574
+		);
575
+		$cancel_button->set_button_css_attributes(false);
576
+		return $cancel_button;
577
+	}
578
+
579
+
580
+
581
+	/**
582
+	 * appends a float clearing div onto end of form
583
+	 *
584
+	 * @return void
585
+	 * @throws EE_Error
586
+	 */
587
+	public function clearFormButtonFloats()
588
+	{
589
+		$this->form->add_subsections(
590
+			array(
591
+				'clear-submit-btn-float' => new EE_Form_Section_HTML(
592
+					EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
593
+				),
594
+			),
595
+			null,
596
+			false
597
+		);
598
+	}
599
+
600
+
601
+	/**
602
+	 * takes the generated form and displays it along with ony other non-form HTML that may be required
603
+	 * returns a string of HTML that can be directly echoed in a template
604
+	 *
605
+	 * @return string
606
+	 * @throws \InvalidArgumentException
607
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
608
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
609
+	 * @throws LogicException
610
+	 * @throws EE_Error
611
+	 */
612
+	public function display()
613
+	{
614
+		$form_html = apply_filters(
615
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
616
+			''
617
+		);
618
+		$form_config = $this->formConfig();
619
+		if (
620
+			$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
621
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
622
+		) {
623
+			$form_html .= $this->form()->form_open($this->formAction());
624
+		}
625
+		$form_html .= $this->form(true)->get_html($this->form_has_errors);
626
+		if (
627
+			$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
628
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
629
+		) {
630
+			$form_html .= $this->form()->form_close();
631
+		}
632
+		$form_html .= apply_filters(
633
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
634
+			''
635
+		);
636
+		return $form_html;
637
+	}
638
+
639
+
640
+	/**
641
+	 * handles processing the form submission
642
+	 * returns true or false depending on whether the form was processed successfully or not
643
+	 *
644
+	 * @param array $submitted_form_data
645
+	 * @return array
646
+	 * @throws \InvalidArgumentException
647
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
648
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
649
+	 * @throws EE_Error
650
+	 * @throws LogicException
651
+	 * @throws InvalidFormSubmissionException
652
+	 */
653
+	public function process($submitted_form_data = array())
654
+	{
655
+		if (! $this->form()->was_submitted($submitted_form_data)) {
656
+			throw new InvalidFormSubmissionException($this->form_name);
657
+		}
658
+		$this->form(true)->receive_form_submission($submitted_form_data);
659
+		if (! $this->form()->is_valid()) {
660
+			throw new InvalidFormSubmissionException(
661
+				$this->form_name,
662
+				sprintf(
663
+					esc_html__(
664
+						'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
665
+						'event_espresso'
666
+					),
667
+					$this->form_name,
668
+					'<br />',
669
+					implode('<br />', $this->form()->get_validation_errors_accumulated())
670
+				)
671
+			);
672
+		}
673
+		return apply_filters(
674
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
675
+			$this->form()->valid_data(),
676
+			$this
677
+		);
678
+	}
679 679
 
680 680
 
681 681
 
Please login to merge, or discard this patch.
form_sections/strategies/normalization/EE_Null_Normalization.strategy.php 2 patches
Indentation   +22 added lines, -22 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
 
@@ -15,26 +15,26 @@  discard block
 block discarded – undo
15 15
 class EE_Null_Normalization extends EE_Normalization_Strategy_Base
16 16
 {
17 17
 
18
-    /**
19
-     * @param string $value_to_normalize
20
-     * @return null
21
-     */
22
-    public function normalize($value_to_normalize)
23
-    {
24
-        return null;
25
-    }
26
-
27
-
28
-
29
-    /**
30
-     * In the form input we need some string, so use a blank one.
31
-     *
32
-     * @param string $normalized_value
33
-     * @return string
34
-     */
35
-    public function unnormalize($normalized_value)
36
-    {
37
-        return '';
38
-    }
18
+	/**
19
+	 * @param string $value_to_normalize
20
+	 * @return null
21
+	 */
22
+	public function normalize($value_to_normalize)
23
+	{
24
+		return null;
25
+	}
26
+
27
+
28
+
29
+	/**
30
+	 * In the form input we need some string, so use a blank one.
31
+	 *
32
+	 * @param string $normalized_value
33
+	 * @return string
34
+	 */
35
+	public function unnormalize($normalized_value)
36
+	{
37
+		return '';
38
+	}
39 39
 
40 40
 }
41 41
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@
 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
 
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Form_Input_Base.input.php 2 patches
Indentation   +1171 added lines, -1171 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
 
@@ -16,1174 +16,1174 @@  discard block
 block discarded – undo
16 16
 abstract class EE_Form_Input_Base extends EE_Form_Section_Validatable
17 17
 {
18 18
 
19
-    /**
20
-     * the input's name attribute
21
-     *
22
-     * @var string
23
-     */
24
-    protected $_html_name;
25
-
26
-    /**
27
-     * id for the html label tag
28
-     *
29
-     * @var string
30
-     */
31
-    protected $_html_label_id;
32
-
33
-    /**
34
-     * class for teh html label tag
35
-     *
36
-     * @var string
37
-     */
38
-    protected $_html_label_class;
39
-
40
-    /**
41
-     * any additional html attributes that you may want to add
42
-     *
43
-     * @var string
44
-     */
45
-    protected $_html_other_attributes;
46
-
47
-    /**
48
-     * style for teh html label tag
49
-     *
50
-     * @var string
51
-     */
52
-    protected $_html_label_style;
53
-
54
-    /**
55
-     * text to be placed in the html label
56
-     *
57
-     * @var string
58
-     */
59
-    protected $_html_label_text;
60
-
61
-    /**
62
-     * the full html label. If used, all other html_label_* properties are invalid
63
-     *
64
-     * @var string
65
-     */
66
-    protected $_html_label;
67
-
68
-    /**
69
-     * HTML to use for help text (normally placed below form input), in a span which normally
70
-     * has a class of 'description'
71
-     *
72
-     * @var string
73
-     */
74
-    protected $_html_help_text;
75
-
76
-    /**
77
-     * CSS classes for displaying the help span
78
-     *
79
-     * @var string
80
-     */
81
-    protected $_html_help_class = 'description';
82
-
83
-    /**
84
-     * CSS to put in the style attribute on the help span
85
-     *
86
-     * @var string
87
-     */
88
-    protected $_html_help_style;
89
-
90
-    /**
91
-     * Stores whether or not this input's response is required.
92
-     * Because certain styling elements may also want to know that this
93
-     * input is required etc.
94
-     *
95
-     * @var boolean
96
-     */
97
-    protected $_required;
98
-
99
-    /**
100
-     * css class added to required inputs
101
-     *
102
-     * @var string
103
-     */
104
-    protected $_required_css_class = 'ee-required';
105
-
106
-    /**
107
-     * css styles applied to button type inputs
108
-     *
109
-     * @var string
110
-     */
111
-    protected $_button_css_attributes;
112
-
113
-    /**
114
-     * The raw data submitted for this, like in the $_POST super global.
115
-     * Generally unsafe for usage in client code
116
-     *
117
-     * @var mixed string or array
118
-     */
119
-    protected $_raw_value;
120
-
121
-    /**
122
-     * Value normalized according to the input's normalization strategy.
123
-     * The normalization strategy dictates whether this is a string, int, float,
124
-     * boolean, or array of any of those.
125
-     *
126
-     * @var mixed
127
-     */
128
-    protected $_normalized_value;
129
-
130
-
131
-    /**
132
-     * Normalized default value either initially set on the input, or provided by calling
133
-     * set_default().
134
-     * @var mixed
135
-     */
136
-    protected $_default;
137
-
138
-    /**
139
-     * Strategy used for displaying this field.
140
-     * Child classes must use _get_display_strategy to access it.
141
-     *
142
-     * @var EE_Display_Strategy_Base
143
-     */
144
-    private $_display_strategy;
145
-
146
-    /**
147
-     * Gets all the validation strategies used on this field
148
-     *
149
-     * @var EE_Validation_Strategy_Base[]
150
-     */
151
-    private $_validation_strategies = array();
152
-
153
-    /**
154
-     * The normalization strategy for this field
155
-     *
156
-     * @var EE_Normalization_Strategy_Base
157
-     */
158
-    private $_normalization_strategy;
159
-
160
-    /**
161
-     * Strategy for removing sensitive data after we're done with the form input
162
-     *
163
-     * @var EE_Sensitive_Data_Removal_Base
164
-     */
165
-    protected $_sensitive_data_removal_strategy;
166
-
167
-
168
-
169
-    /**
170
-     * @param array                         $input_args       {
171
-     * @type string                         $html_name        the html name for the input
172
-     * @type string                         $html_label_id    the id attribute to give to the html label tag
173
-     * @type string                         $html_label_class the class attribute to give to the html label tag
174
-     * @type string                         $html_label_style the style attribute to give ot teh label tag
175
-     * @type string                         $html_label_text  the text to put in the label tag
176
-     * @type string                         $html_label       the full html label. If used,
177
-     *                                                        all other html_label_* args are invalid
178
-     * @type string                         $html_help_text   text to put in help element
179
-     * @type string                         $html_help_style  style attribute to give to teh help element
180
-     * @type string                         $html_help_class  class attribute to give to the help element
181
-     * @type string                         $default          default value NORMALIZED (eg, if providing the default
182
-     *       for a Yes_No_Input, you should provide TRUE or FALSE, not '1' or '0')
183
-     * @type EE_Display_Strategy_Base       $display          strategy
184
-     * @type EE_Normalization_Strategy_Base $normalization_strategy
185
-     * @type EE_Validation_Strategy_Base[]  $validation_strategies
186
-     * @type boolean                        $ignore_input special argument which can be used to avoid adding any validation strategies,
187
-     *                                                    and sets the normalization strategy to the Null normalization. This is good
188
-     *                                                    when you want the input to be totally ignored server-side (like when using
189
-     *                                                    React.js form inputs)
190
-     *                                                        }
191
-     */
192
-    public function __construct($input_args = array())
193
-    {
194
-        $input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
195
-        // the following properties must be cast as arrays
196
-        if (isset($input_args['validation_strategies'])) {
197
-            foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
198
-                if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
199
-                    $this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
200
-                }
201
-            }
202
-            unset($input_args['validation_strategies']);
203
-        }
204
-        if(isset($input_args['ignore_input'])) {
205
-            $this->_validation_strategies = array();
206
-        }
207
-        // loop thru incoming options
208
-        foreach ($input_args as $key => $value) {
209
-            // add underscore to $key to match property names
210
-            $_key = '_' . $key;
211
-            if (property_exists($this, $_key)) {
212
-                $this->{$_key} = $value;
213
-            }
214
-        }
215
-        // ensure that "required" is set correctly
216
-        $this->set_required(
217
-            $this->_required, isset($input_args['required_validation_error_message'])
218
-            ? $input_args['required_validation_error_message']
219
-            : null
220
-        );
221
-        //$this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
222
-        $this->_display_strategy->_construct_finalize($this);
223
-        foreach ($this->_validation_strategies as $validation_strategy) {
224
-            $validation_strategy->_construct_finalize($this);
225
-        }
226
-        if (isset($input_args['ignore_input'])) {
227
-            $this->_normalization_strategy = new EE_Null_Normalization();
228
-        }
229
-        if (! $this->_normalization_strategy) {
230
-                $this->_normalization_strategy = new EE_Text_Normalization();
231
-        }
232
-        $this->_normalization_strategy->_construct_finalize($this);
233
-        //at least we can use the normalization strategy to populate the default
234
-        if (isset($input_args['default'])) {
235
-            $this->set_default($input_args['default']);
236
-            unset($input_args['default']);
237
-        }
238
-        if (! $this->_sensitive_data_removal_strategy) {
239
-            $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
240
-        }
241
-        $this->_sensitive_data_removal_strategy->_construct_finalize($this);
242
-        parent::__construct($input_args);
243
-    }
244
-
245
-
246
-
247
-    /**
248
-     * Sets the html_name to its default value, if none was specified in teh constructor.
249
-     * Calculation involves using the name and the parent's html_name
250
-     *
251
-     * @throws \EE_Error
252
-     */
253
-    protected function _set_default_html_name_if_empty()
254
-    {
255
-        if (! $this->_html_name) {
256
-            $this->_html_name = $this->name();
257
-            if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
258
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
259
-            }
260
-        }
261
-    }
262
-
263
-
264
-
265
-    /**
266
-     * @param $parent_form_section
267
-     * @param $name
268
-     * @throws \EE_Error
269
-     */
270
-    public function _construct_finalize($parent_form_section, $name)
271
-    {
272
-        parent::_construct_finalize($parent_form_section, $name);
273
-        if ($this->_html_label === null && $this->_html_label_text === null) {
274
-            $this->_html_label_text = ucwords(str_replace("_", " ", $name));
275
-        }
276
-        do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * Returns the strategy for displaying this form input. If none is set, throws an exception.
283
-     *
284
-     * @return EE_Display_Strategy_Base
285
-     * @throws EE_Error
286
-     */
287
-    protected function _get_display_strategy()
288
-    {
289
-        $this->ensure_construct_finalized_called();
290
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
291
-            throw new EE_Error(
292
-                sprintf(
293
-                    __(
294
-                        "Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
295
-                        "event_espresso"
296
-                    ),
297
-                    $this->html_name(),
298
-                    $this->html_id()
299
-                )
300
-            );
301
-        } else {
302
-            return $this->_display_strategy;
303
-        }
304
-    }
305
-
306
-
307
-
308
-    /**
309
-     * Sets the display strategy.
310
-     *
311
-     * @param EE_Display_Strategy_Base $strategy
312
-     */
313
-    protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
314
-    {
315
-        $this->_display_strategy = $strategy;
316
-    }
317
-
318
-
319
-
320
-    /**
321
-     * Sets the sanitization strategy
322
-     *
323
-     * @param EE_Normalization_Strategy_Base $strategy
324
-     */
325
-    protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
326
-    {
327
-        $this->_normalization_strategy = $strategy;
328
-    }
329
-
330
-
331
-
332
-    /**
333
-     * Gets sensitive_data_removal_strategy
334
-     *
335
-     * @return EE_Sensitive_Data_Removal_Base
336
-     */
337
-    public function get_sensitive_data_removal_strategy()
338
-    {
339
-        return $this->_sensitive_data_removal_strategy;
340
-    }
341
-
342
-
343
-
344
-    /**
345
-     * Sets sensitive_data_removal_strategy
346
-     *
347
-     * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
348
-     * @return boolean
349
-     */
350
-    public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
351
-    {
352
-        $this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
353
-    }
354
-
355
-
356
-
357
-    /**
358
-     * Gets the display strategy for this input
359
-     *
360
-     * @return EE_Display_Strategy_Base
361
-     */
362
-    public function get_display_strategy()
363
-    {
364
-        return $this->_display_strategy;
365
-    }
366
-
367
-
368
-
369
-    /**
370
-     * Overwrites the display strategy
371
-     *
372
-     * @param EE_Display_Strategy_Base $display_strategy
373
-     */
374
-    public function set_display_strategy($display_strategy)
375
-    {
376
-        $this->_display_strategy = $display_strategy;
377
-        $this->_display_strategy->_construct_finalize($this);
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     * Gets the normalization strategy set on this input
384
-     *
385
-     * @return EE_Normalization_Strategy_Base
386
-     */
387
-    public function get_normalization_strategy()
388
-    {
389
-        return $this->_normalization_strategy;
390
-    }
391
-
392
-
393
-
394
-    /**
395
-     * Overwrites the normalization strategy
396
-     *
397
-     * @param EE_Normalization_Strategy_Base $normalization_strategy
398
-     */
399
-    public function set_normalization_strategy($normalization_strategy)
400
-    {
401
-        $this->_normalization_strategy = $normalization_strategy;
402
-        $this->_normalization_strategy->_construct_finalize($this);
403
-    }
404
-
405
-
406
-
407
-    /**
408
-     * Returns all teh validation strategies which apply to this field, numerically indexed
409
-     *
410
-     * @return EE_Validation_Strategy_Base[]
411
-     */
412
-    public function get_validation_strategies()
413
-    {
414
-        return $this->_validation_strategies;
415
-    }
416
-
417
-
418
-
419
-    /**
420
-     * Adds this strategy to the field so it will be used in both JS validation and server-side validation
421
-     *
422
-     * @param EE_Validation_Strategy_Base $validation_strategy
423
-     * @return void
424
-     */
425
-    protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
426
-    {
427
-        $validation_strategy->_construct_finalize($this);
428
-        $this->_validation_strategies[] = $validation_strategy;
429
-    }
430
-
431
-
432
-
433
-    /**
434
-     * Adds a new validation strategy onto the form input
435
-     *
436
-     * @param EE_Validation_Strategy_Base $validation_strategy
437
-     * @return void
438
-     */
439
-    public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
440
-    {
441
-        $this->_add_validation_strategy($validation_strategy);
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     * The classname of the validation strategy to remove
448
-     *
449
-     * @param string $validation_strategy_classname
450
-     */
451
-    public function remove_validation_strategy($validation_strategy_classname)
452
-    {
453
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
454
-            if (
455
-                $validation_strategy instanceof $validation_strategy_classname
456
-                || is_subclass_of($validation_strategy, $validation_strategy_classname)
457
-            ) {
458
-                unset($this->_validation_strategies[$key]);
459
-            }
460
-        }
461
-    }
462
-
463
-
464
-
465
-    /**
466
-     * returns true if input employs any of the validation strategy defined by the supplied array of classnames
467
-     *
468
-     * @param array $validation_strategy_classnames
469
-     * @return bool
470
-     */
471
-    public function has_validation_strategy($validation_strategy_classnames)
472
-    {
473
-        $validation_strategy_classnames = is_array($validation_strategy_classnames)
474
-            ? $validation_strategy_classnames
475
-            : array($validation_strategy_classnames);
476
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
477
-            if (in_array($key, $validation_strategy_classnames)) {
478
-                return true;
479
-            }
480
-        }
481
-        return false;
482
-    }
483
-
484
-
485
-
486
-    /**
487
-     * Gets the HTML
488
-     *
489
-     * @return string
490
-     */
491
-    public function get_html()
492
-    {
493
-        return $this->_parent_section->get_html_for_input($this);
494
-    }
495
-
496
-
497
-
498
-    /**
499
-     * Gets the HTML for the input itself (no label or errors) according to the
500
-     * input's display strategy
501
-     * Makes sure the JS and CSS are enqueued for it
502
-     *
503
-     * @return string
504
-     * @throws \EE_Error
505
-     */
506
-    public function get_html_for_input()
507
-    {
508
-        return $this->_form_html_filter
509
-            ? $this->_form_html_filter->filterHtml(
510
-                $this->_get_display_strategy()->display(),
511
-                $this
512
-            )
513
-            : $this->_get_display_strategy()->display();
514
-    }
515
-
516
-
517
-
518
-    /**
519
-     * @return string
520
-     */
521
-    public function html_other_attributes()
522
-    {
523
-        return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * @param string $html_other_attributes
530
-     */
531
-    public function set_html_other_attributes($html_other_attributes)
532
-    {
533
-        $this->_html_other_attributes = $html_other_attributes;
534
-    }
535
-
536
-
537
-
538
-    /**
539
-     * Gets the HTML for displaying the label for this form input
540
-     * according to the form section's layout strategy
541
-     *
542
-     * @return string
543
-     */
544
-    public function get_html_for_label()
545
-    {
546
-        return $this->_parent_section->get_layout_strategy()->display_label($this);
547
-    }
548
-
549
-
550
-
551
-    /**
552
-     * Gets the HTML for displaying the errors section for this form input
553
-     * according to the form section's layout strategy
554
-     *
555
-     * @return string
556
-     */
557
-    public function get_html_for_errors()
558
-    {
559
-        return $this->_parent_section->get_layout_strategy()->display_errors($this);
560
-    }
561
-
562
-
563
-
564
-    /**
565
-     * Gets the HTML for displaying the help text for this form input
566
-     * according to the form section's layout strategy
567
-     *
568
-     * @return string
569
-     */
570
-    public function get_html_for_help()
571
-    {
572
-        return $this->_parent_section->get_layout_strategy()->display_help_text($this);
573
-    }
574
-
575
-
576
-
577
-    /**
578
-     * Validates the input's sanitized value (assumes _sanitize() has already been called)
579
-     * and returns whether or not the form input's submitted value is value
580
-     *
581
-     * @return boolean
582
-     */
583
-    protected function _validate()
584
-    {
585
-        foreach ($this->_validation_strategies as $validation_strategy) {
586
-            if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
587
-                try {
588
-                    $validation_strategy->validate($this->normalized_value());
589
-                } catch (EE_Validation_Error $e) {
590
-                    $this->add_validation_error($e);
591
-                }
592
-            }
593
-        }
594
-        if ($this->get_validation_errors()) {
595
-            return false;
596
-        } else {
597
-            return true;
598
-        }
599
-    }
600
-
601
-
602
-
603
-    /**
604
-     * Performs basic sanitization on this value. But what sanitization can be performed anyways?
605
-     * This value MIGHT be allowed to have tags, so we can't really remove them.
606
-     *
607
-     * @param string $value
608
-     * @return null|string
609
-     */
610
-    private function _sanitize($value)
611
-    {
612
-        return $value !== null ? stripslashes(html_entity_decode(trim($value))) : null;
613
-    }
614
-
615
-
616
-
617
-    /**
618
-     * Picks out the form value that relates to this form input,
619
-     * and stores it as the sanitized value on the form input, and sets the normalized value.
620
-     * Returns whether or not any validation errors occurred
621
-     *
622
-     * @param array $req_data like $_POST
623
-     * @return boolean whether or not there was an error
624
-     * @throws \EE_Error
625
-     */
626
-    protected function _normalize($req_data)
627
-    {
628
-        //any existing validation errors don't apply so clear them
629
-        $this->_validation_errors = array();
630
-        try {
631
-            $raw_input = $this->find_form_data_for_this_section($req_data);
632
-            //super simple sanitization for now
633
-            if (is_array($raw_input)) {
634
-                $raw_value = array();
635
-                foreach ($raw_input as $key => $value) {
636
-                    $raw_value[$key] = $this->_sanitize($value);
637
-                }
638
-                $this->_set_raw_value($raw_value);
639
-            } else {
640
-                $this->_set_raw_value($this->_sanitize($raw_input));
641
-            }
642
-            //we want to mostly leave the input alone in case we need to re-display it to the user
643
-            $this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
644
-        } catch (EE_Validation_Error $e) {
645
-            $this->add_validation_error($e);
646
-        }
647
-    }
648
-
649
-
650
-
651
-    /**
652
-     * @return string
653
-     */
654
-    public function html_name()
655
-    {
656
-        $this->_set_default_html_name_if_empty();
657
-        return $this->_html_name;
658
-    }
659
-
660
-
661
-
662
-    /**
663
-     * @return string
664
-     */
665
-    public function html_label_id()
666
-    {
667
-        return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id() . '-lbl';
668
-    }
669
-
670
-
671
-
672
-    /**
673
-     * @return string
674
-     */
675
-    public function html_label_class()
676
-    {
677
-        return $this->_html_label_class;
678
-    }
679
-
680
-
681
-
682
-    /**
683
-     * @return string
684
-     */
685
-    public function html_label_style()
686
-    {
687
-        return $this->_html_label_style;
688
-    }
689
-
690
-
691
-
692
-    /**
693
-     * @return string
694
-     */
695
-    public function html_label_text()
696
-    {
697
-        return $this->_html_label_text;
698
-    }
699
-
700
-
701
-
702
-    /**
703
-     * @return string
704
-     */
705
-    public function html_help_text()
706
-    {
707
-        return $this->_html_help_text;
708
-    }
709
-
710
-
711
-
712
-    /**
713
-     * @return string
714
-     */
715
-    public function html_help_class()
716
-    {
717
-        return $this->_html_help_class;
718
-    }
719
-
720
-
721
-
722
-    /**
723
-     * @return string
724
-     */
725
-    public function html_help_style()
726
-    {
727
-        return $this->_html_style;
728
-    }
729
-
730
-
731
-
732
-    /**
733
-     * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
734
-     * Please note that almost all client code should instead use the normalized_value;
735
-     * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
736
-     * mostly by escaping quotes)
737
-     * Note, we do not store the exact original value sent in the user's request because
738
-     * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
739
-     * in which case, we would have stored the malicious content to our database.
740
-     *
741
-     * @return string
742
-     */
743
-    public function raw_value()
744
-    {
745
-        return $this->_raw_value;
746
-    }
747
-
748
-
749
-
750
-    /**
751
-     * Returns a string safe to usage in form inputs when displaying, because
752
-     * it escapes all html entities
753
-     *
754
-     * @return string
755
-     */
756
-    public function raw_value_in_form()
757
-    {
758
-        return htmlentities($this->raw_value(), ENT_QUOTES, 'UTF-8');
759
-    }
760
-
761
-
762
-
763
-    /**
764
-     * returns the value after it's been sanitized, and then converted into it's proper type
765
-     * in PHP. Eg, a string, an int, an array,
766
-     *
767
-     * @return mixed
768
-     */
769
-    public function normalized_value()
770
-    {
771
-        return $this->_normalized_value;
772
-    }
773
-
774
-
775
-
776
-    /**
777
-     * Returns the normalized value is a presentable way. By default this is just
778
-     * the normalized value by itself, but it can be overridden for when that's not
779
-     * the best thing to display
780
-     *
781
-     * @return string
782
-     */
783
-    public function pretty_value()
784
-    {
785
-        return $this->_normalized_value;
786
-    }
787
-
788
-
789
-
790
-    /**
791
-     * When generating the JS for the jquery validation rules like<br>
792
-     * <code>$( "#myform" ).validate({
793
-     * rules: {
794
-     * password: "required",
795
-     * password_again: {
796
-     * equalTo: "#password"
797
-     * }
798
-     * }
799
-     * });</code>
800
-     * if this field had the name 'password_again', it should return
801
-     * <br><code>password_again: {
802
-     * equalTo: "#password"
803
-     * }</code>
804
-     *
805
-     * @return array
806
-     */
807
-    public function get_jquery_validation_rules()
808
-    {
809
-        $jquery_validation_js = array();
810
-        $jquery_validation_rules = array();
811
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
812
-            $jquery_validation_rules = array_replace_recursive(
813
-                $jquery_validation_rules,
814
-                $validation_strategy->get_jquery_validation_rule_array()
815
-            );
816
-        }
817
-        if (! empty($jquery_validation_rules)) {
818
-            foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
819
-                $jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
820
-            }
821
-        }
822
-        return $jquery_validation_js;
823
-    }
824
-
825
-
826
-
827
-    /**
828
-     * Sets the input's default value for use in displaying in the form. Note: value should be
829
-     * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
830
-     *
831
-     * @param mixed $value
832
-     * @return void
833
-     */
834
-    public function set_default($value)
835
-    {
836
-        $this->_default = $value;
837
-        $this->_set_normalized_value($value);
838
-        $this->_set_raw_value($value);
839
-    }
840
-
841
-
842
-
843
-    /**
844
-     * Sets the normalized value on this input
845
-     *
846
-     * @param mixed $value
847
-     */
848
-    protected function _set_normalized_value($value)
849
-    {
850
-        $this->_normalized_value = $value;
851
-    }
852
-
853
-
854
-
855
-    /**
856
-     * Sets the raw value on this input (ie, exactly as the user submitted it)
857
-     *
858
-     * @param mixed $value
859
-     */
860
-    protected function _set_raw_value($value)
861
-    {
862
-        $this->_raw_value = $this->_normalization_strategy->unnormalize($value);
863
-    }
864
-
865
-
866
-
867
-    /**
868
-     * Sets the HTML label text after it has already been defined
869
-     *
870
-     * @param string $label
871
-     * @return void
872
-     */
873
-    public function set_html_label_text($label)
874
-    {
875
-        $this->_html_label_text = $label;
876
-    }
877
-
878
-
879
-
880
-    /**
881
-     * Sets whether or not this field is required, and adjusts the validation strategy.
882
-     * If you want to use the EE_Conditionally_Required_Validation_Strategy,
883
-     * please add it as a validation strategy using add_validation_strategy as normal
884
-     *
885
-     * @param boolean $required boolean
886
-     * @param null    $required_text
887
-     */
888
-    public function set_required($required = true, $required_text = null)
889
-    {
890
-        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
891
-        //whether $required is a string or a boolean, we want to add a required validation strategy
892
-        if ($required) {
893
-            $this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
894
-        } else {
895
-            $this->remove_validation_strategy('EE_Required_Validation_Strategy');
896
-        }
897
-        $this->_required = $required;
898
-    }
899
-
900
-
901
-
902
-    /**
903
-     * Returns whether or not this field is required
904
-     *
905
-     * @return boolean
906
-     */
907
-    public function required()
908
-    {
909
-        return $this->_required;
910
-    }
911
-
912
-
913
-
914
-    /**
915
-     * @param string $required_css_class
916
-     */
917
-    public function set_required_css_class($required_css_class)
918
-    {
919
-        $this->_required_css_class = $required_css_class;
920
-    }
921
-
922
-
923
-
924
-    /**
925
-     * @return string
926
-     */
927
-    public function required_css_class()
928
-    {
929
-        return $this->_required_css_class;
930
-    }
931
-
932
-
933
-
934
-    /**
935
-     * @param bool $add_required
936
-     * @return string
937
-     */
938
-    public function html_class($add_required = false)
939
-    {
940
-        return $add_required && $this->required()
941
-            ? $this->required_css_class() . ' ' . $this->_html_class
942
-            : $this->_html_class;
943
-    }
944
-
945
-
946
-    /**
947
-     * Sets the help text, in case
948
-     *
949
-     * @param string $text
950
-     */
951
-    public function set_html_help_text($text)
952
-    {
953
-        $this->_html_help_text = $text;
954
-    }
955
-
956
-
957
-
958
-    /**
959
-     * Uses the sensitive data removal strategy to remove the sensitive data from this
960
-     * input. If there is any kind of sensitive data removal on this input, we clear
961
-     * out the raw value completely
962
-     *
963
-     * @return void
964
-     */
965
-    public function clean_sensitive_data()
966
-    {
967
-        //if we do ANY kind of sensitive data removal on this, then just clear out the raw value
968
-        //if we need more logic than this we'll make a strategy for it
969
-        if ($this->_sensitive_data_removal_strategy
970
-            && ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
971
-        ) {
972
-            $this->_set_raw_value(null);
973
-        }
974
-        //and clean the normalized value according to the appropriate strategy
975
-        $this->_set_normalized_value(
976
-            $this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
977
-                $this->_normalized_value
978
-            )
979
-        );
980
-    }
981
-
982
-
983
-
984
-    /**
985
-     * @param bool   $primary
986
-     * @param string $button_size
987
-     * @param string $other_attributes
988
-     */
989
-    public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
990
-    {
991
-        $button_css_attributes = 'button';
992
-        $button_css_attributes .= $primary === true ? ' button-primary' : ' button-secondary';
993
-        switch ($button_size) {
994
-            case 'xs' :
995
-            case 'extra-small' :
996
-                $button_css_attributes .= ' button-xs';
997
-                break;
998
-            case 'sm' :
999
-            case 'small' :
1000
-                $button_css_attributes .= ' button-sm';
1001
-                break;
1002
-            case 'lg' :
1003
-            case 'large' :
1004
-                $button_css_attributes .= ' button-lg';
1005
-                break;
1006
-            case 'block' :
1007
-                $button_css_attributes .= ' button-block';
1008
-                break;
1009
-            case 'md' :
1010
-            case 'medium' :
1011
-            default :
1012
-                $button_css_attributes .= '';
1013
-        }
1014
-        $this->_button_css_attributes .= ! empty($other_attributes)
1015
-            ? $button_css_attributes . ' ' . $other_attributes
1016
-            : $button_css_attributes;
1017
-    }
1018
-
1019
-
1020
-
1021
-    /**
1022
-     * @return string
1023
-     */
1024
-    public function button_css_attributes()
1025
-    {
1026
-        if (empty($this->_button_css_attributes)) {
1027
-            $this->set_button_css_attributes();
1028
-        }
1029
-        return $this->_button_css_attributes;
1030
-    }
1031
-
1032
-
1033
-
1034
-    /**
1035
-     * find_form_data_for_this_section
1036
-     * using this section's name and its parents, finds the value of the form data that corresponds to it.
1037
-     * For example, if this form section's HTML name is my_form[subform][form_input_1],
1038
-     * then it's value should be in $_REQUEST at $_REQUEST['my_form']['subform']['form_input_1'].
1039
-     * (If that doesn't exist, we also check for this subsection's name
1040
-     * at the TOP LEVEL of the request data. Eg $_REQUEST['form_input_1'].)
1041
-     * This function finds its value in the form.
1042
-     *
1043
-     * @param array $req_data
1044
-     * @return mixed whatever the raw value of this form section is in the request data
1045
-     * @throws \EE_Error
1046
-     */
1047
-    public function find_form_data_for_this_section($req_data)
1048
-    {
1049
-        // break up the html name by "[]"
1050
-        if (strpos($this->html_name(), '[') !== false) {
1051
-            $before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1052
-        } else {
1053
-            $before_any_brackets = $this->html_name();
1054
-        }
1055
-        // grab all of the segments
1056
-        preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1057
-        if (isset($matches[1]) && is_array($matches[1])) {
1058
-            $name_parts = $matches[1];
1059
-            array_unshift($name_parts, $before_any_brackets);
1060
-        } else {
1061
-            $name_parts = array($before_any_brackets);
1062
-        }
1063
-        // now get the value for the input
1064
-        $value = $this->_find_form_data_for_this_section_using_name_parts($name_parts, $req_data);
1065
-        // check if this thing's name is at the TOP level of the request data
1066
-        if ($value === null && isset($req_data[$this->name()])) {
1067
-            $value = $req_data[$this->name()];
1068
-        }
1069
-        return $value;
1070
-    }
1071
-
1072
-
1073
-
1074
-    /**
1075
-     * @param array $html_name_parts
1076
-     * @param array $req_data
1077
-     * @return array | NULL
1078
-     */
1079
-    public function _find_form_data_for_this_section_using_name_parts($html_name_parts, $req_data)
1080
-    {
1081
-        $first_part_to_consider = array_shift($html_name_parts);
1082
-        if (isset($req_data[$first_part_to_consider])) {
1083
-            if (empty($html_name_parts)) {
1084
-                return $req_data[$first_part_to_consider];
1085
-            } else {
1086
-                return $this->_find_form_data_for_this_section_using_name_parts(
1087
-                    $html_name_parts,
1088
-                    $req_data[$first_part_to_consider]
1089
-                );
1090
-            }
1091
-        } else {
1092
-            return null;
1093
-        }
1094
-    }
1095
-
1096
-
1097
-
1098
-    /**
1099
-     * Checks if this form input's data is in the request data
1100
-     *
1101
-     * @param array $req_data like $_POST
1102
-     * @return boolean
1103
-     * @throws \EE_Error
1104
-     */
1105
-    public function form_data_present_in($req_data = null)
1106
-    {
1107
-        if ($req_data === null) {
1108
-            $req_data = $_POST;
1109
-        }
1110
-        $checked_value = $this->find_form_data_for_this_section($req_data);
1111
-        if ($checked_value !== null) {
1112
-            return true;
1113
-        } else {
1114
-            return false;
1115
-        }
1116
-    }
1117
-
1118
-
1119
-
1120
-    /**
1121
-     * Overrides parent to add js data from validation and display strategies
1122
-     *
1123
-     * @param array $form_other_js_data
1124
-     * @return array
1125
-     */
1126
-    public function get_other_js_data($form_other_js_data = array())
1127
-    {
1128
-        $form_other_js_data = $this->get_other_js_data_from_strategies($form_other_js_data);
1129
-        return $form_other_js_data;
1130
-    }
1131
-
1132
-
1133
-
1134
-    /**
1135
-     * Gets other JS data for localization from this input's strategies, like
1136
-     * the validation strategies and the display strategy
1137
-     *
1138
-     * @param array $form_other_js_data
1139
-     * @return array
1140
-     */
1141
-    public function get_other_js_data_from_strategies($form_other_js_data = array())
1142
-    {
1143
-        $form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1144
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1145
-            $form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1146
-        }
1147
-        return $form_other_js_data;
1148
-    }
1149
-
1150
-
1151
-
1152
-    /**
1153
-     * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1154
-     *
1155
-     * @return void
1156
-     */
1157
-    public function enqueue_js()
1158
-    {
1159
-        //ask our display strategy and validation strategies if they have js to enqueue
1160
-        $this->enqueue_js_from_strategies();
1161
-    }
1162
-
1163
-
1164
-
1165
-    /**
1166
-     * Tells strategies when its ok to enqueue their js and css
1167
-     *
1168
-     * @return void
1169
-     */
1170
-    public function enqueue_js_from_strategies()
1171
-    {
1172
-        $this->get_display_strategy()->enqueue_js();
1173
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1174
-            $validation_strategy->enqueue_js();
1175
-        }
1176
-    }
1177
-
1178
-
1179
-
1180
-    /**
1181
-     * Gets the default value set on the input (not the current value, which may have been
1182
-     * changed because of a form submission). If no default was set, this us null.
1183
-     * @return mixed
1184
-     */
1185
-    public function get_default()
1186
-    {
1187
-        return $this->_default;
1188
-    }
19
+	/**
20
+	 * the input's name attribute
21
+	 *
22
+	 * @var string
23
+	 */
24
+	protected $_html_name;
25
+
26
+	/**
27
+	 * id for the html label tag
28
+	 *
29
+	 * @var string
30
+	 */
31
+	protected $_html_label_id;
32
+
33
+	/**
34
+	 * class for teh html label tag
35
+	 *
36
+	 * @var string
37
+	 */
38
+	protected $_html_label_class;
39
+
40
+	/**
41
+	 * any additional html attributes that you may want to add
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $_html_other_attributes;
46
+
47
+	/**
48
+	 * style for teh html label tag
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $_html_label_style;
53
+
54
+	/**
55
+	 * text to be placed in the html label
56
+	 *
57
+	 * @var string
58
+	 */
59
+	protected $_html_label_text;
60
+
61
+	/**
62
+	 * the full html label. If used, all other html_label_* properties are invalid
63
+	 *
64
+	 * @var string
65
+	 */
66
+	protected $_html_label;
67
+
68
+	/**
69
+	 * HTML to use for help text (normally placed below form input), in a span which normally
70
+	 * has a class of 'description'
71
+	 *
72
+	 * @var string
73
+	 */
74
+	protected $_html_help_text;
75
+
76
+	/**
77
+	 * CSS classes for displaying the help span
78
+	 *
79
+	 * @var string
80
+	 */
81
+	protected $_html_help_class = 'description';
82
+
83
+	/**
84
+	 * CSS to put in the style attribute on the help span
85
+	 *
86
+	 * @var string
87
+	 */
88
+	protected $_html_help_style;
89
+
90
+	/**
91
+	 * Stores whether or not this input's response is required.
92
+	 * Because certain styling elements may also want to know that this
93
+	 * input is required etc.
94
+	 *
95
+	 * @var boolean
96
+	 */
97
+	protected $_required;
98
+
99
+	/**
100
+	 * css class added to required inputs
101
+	 *
102
+	 * @var string
103
+	 */
104
+	protected $_required_css_class = 'ee-required';
105
+
106
+	/**
107
+	 * css styles applied to button type inputs
108
+	 *
109
+	 * @var string
110
+	 */
111
+	protected $_button_css_attributes;
112
+
113
+	/**
114
+	 * The raw data submitted for this, like in the $_POST super global.
115
+	 * Generally unsafe for usage in client code
116
+	 *
117
+	 * @var mixed string or array
118
+	 */
119
+	protected $_raw_value;
120
+
121
+	/**
122
+	 * Value normalized according to the input's normalization strategy.
123
+	 * The normalization strategy dictates whether this is a string, int, float,
124
+	 * boolean, or array of any of those.
125
+	 *
126
+	 * @var mixed
127
+	 */
128
+	protected $_normalized_value;
129
+
130
+
131
+	/**
132
+	 * Normalized default value either initially set on the input, or provided by calling
133
+	 * set_default().
134
+	 * @var mixed
135
+	 */
136
+	protected $_default;
137
+
138
+	/**
139
+	 * Strategy used for displaying this field.
140
+	 * Child classes must use _get_display_strategy to access it.
141
+	 *
142
+	 * @var EE_Display_Strategy_Base
143
+	 */
144
+	private $_display_strategy;
145
+
146
+	/**
147
+	 * Gets all the validation strategies used on this field
148
+	 *
149
+	 * @var EE_Validation_Strategy_Base[]
150
+	 */
151
+	private $_validation_strategies = array();
152
+
153
+	/**
154
+	 * The normalization strategy for this field
155
+	 *
156
+	 * @var EE_Normalization_Strategy_Base
157
+	 */
158
+	private $_normalization_strategy;
159
+
160
+	/**
161
+	 * Strategy for removing sensitive data after we're done with the form input
162
+	 *
163
+	 * @var EE_Sensitive_Data_Removal_Base
164
+	 */
165
+	protected $_sensitive_data_removal_strategy;
166
+
167
+
168
+
169
+	/**
170
+	 * @param array                         $input_args       {
171
+	 * @type string                         $html_name        the html name for the input
172
+	 * @type string                         $html_label_id    the id attribute to give to the html label tag
173
+	 * @type string                         $html_label_class the class attribute to give to the html label tag
174
+	 * @type string                         $html_label_style the style attribute to give ot teh label tag
175
+	 * @type string                         $html_label_text  the text to put in the label tag
176
+	 * @type string                         $html_label       the full html label. If used,
177
+	 *                                                        all other html_label_* args are invalid
178
+	 * @type string                         $html_help_text   text to put in help element
179
+	 * @type string                         $html_help_style  style attribute to give to teh help element
180
+	 * @type string                         $html_help_class  class attribute to give to the help element
181
+	 * @type string                         $default          default value NORMALIZED (eg, if providing the default
182
+	 *       for a Yes_No_Input, you should provide TRUE or FALSE, not '1' or '0')
183
+	 * @type EE_Display_Strategy_Base       $display          strategy
184
+	 * @type EE_Normalization_Strategy_Base $normalization_strategy
185
+	 * @type EE_Validation_Strategy_Base[]  $validation_strategies
186
+	 * @type boolean                        $ignore_input special argument which can be used to avoid adding any validation strategies,
187
+	 *                                                    and sets the normalization strategy to the Null normalization. This is good
188
+	 *                                                    when you want the input to be totally ignored server-side (like when using
189
+	 *                                                    React.js form inputs)
190
+	 *                                                        }
191
+	 */
192
+	public function __construct($input_args = array())
193
+	{
194
+		$input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
195
+		// the following properties must be cast as arrays
196
+		if (isset($input_args['validation_strategies'])) {
197
+			foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
198
+				if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
199
+					$this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
200
+				}
201
+			}
202
+			unset($input_args['validation_strategies']);
203
+		}
204
+		if(isset($input_args['ignore_input'])) {
205
+			$this->_validation_strategies = array();
206
+		}
207
+		// loop thru incoming options
208
+		foreach ($input_args as $key => $value) {
209
+			// add underscore to $key to match property names
210
+			$_key = '_' . $key;
211
+			if (property_exists($this, $_key)) {
212
+				$this->{$_key} = $value;
213
+			}
214
+		}
215
+		// ensure that "required" is set correctly
216
+		$this->set_required(
217
+			$this->_required, isset($input_args['required_validation_error_message'])
218
+			? $input_args['required_validation_error_message']
219
+			: null
220
+		);
221
+		//$this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
222
+		$this->_display_strategy->_construct_finalize($this);
223
+		foreach ($this->_validation_strategies as $validation_strategy) {
224
+			$validation_strategy->_construct_finalize($this);
225
+		}
226
+		if (isset($input_args['ignore_input'])) {
227
+			$this->_normalization_strategy = new EE_Null_Normalization();
228
+		}
229
+		if (! $this->_normalization_strategy) {
230
+				$this->_normalization_strategy = new EE_Text_Normalization();
231
+		}
232
+		$this->_normalization_strategy->_construct_finalize($this);
233
+		//at least we can use the normalization strategy to populate the default
234
+		if (isset($input_args['default'])) {
235
+			$this->set_default($input_args['default']);
236
+			unset($input_args['default']);
237
+		}
238
+		if (! $this->_sensitive_data_removal_strategy) {
239
+			$this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
240
+		}
241
+		$this->_sensitive_data_removal_strategy->_construct_finalize($this);
242
+		parent::__construct($input_args);
243
+	}
244
+
245
+
246
+
247
+	/**
248
+	 * Sets the html_name to its default value, if none was specified in teh constructor.
249
+	 * Calculation involves using the name and the parent's html_name
250
+	 *
251
+	 * @throws \EE_Error
252
+	 */
253
+	protected function _set_default_html_name_if_empty()
254
+	{
255
+		if (! $this->_html_name) {
256
+			$this->_html_name = $this->name();
257
+			if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
258
+				$this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
259
+			}
260
+		}
261
+	}
262
+
263
+
264
+
265
+	/**
266
+	 * @param $parent_form_section
267
+	 * @param $name
268
+	 * @throws \EE_Error
269
+	 */
270
+	public function _construct_finalize($parent_form_section, $name)
271
+	{
272
+		parent::_construct_finalize($parent_form_section, $name);
273
+		if ($this->_html_label === null && $this->_html_label_text === null) {
274
+			$this->_html_label_text = ucwords(str_replace("_", " ", $name));
275
+		}
276
+		do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * Returns the strategy for displaying this form input. If none is set, throws an exception.
283
+	 *
284
+	 * @return EE_Display_Strategy_Base
285
+	 * @throws EE_Error
286
+	 */
287
+	protected function _get_display_strategy()
288
+	{
289
+		$this->ensure_construct_finalized_called();
290
+		if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
291
+			throw new EE_Error(
292
+				sprintf(
293
+					__(
294
+						"Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
295
+						"event_espresso"
296
+					),
297
+					$this->html_name(),
298
+					$this->html_id()
299
+				)
300
+			);
301
+		} else {
302
+			return $this->_display_strategy;
303
+		}
304
+	}
305
+
306
+
307
+
308
+	/**
309
+	 * Sets the display strategy.
310
+	 *
311
+	 * @param EE_Display_Strategy_Base $strategy
312
+	 */
313
+	protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
314
+	{
315
+		$this->_display_strategy = $strategy;
316
+	}
317
+
318
+
319
+
320
+	/**
321
+	 * Sets the sanitization strategy
322
+	 *
323
+	 * @param EE_Normalization_Strategy_Base $strategy
324
+	 */
325
+	protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
326
+	{
327
+		$this->_normalization_strategy = $strategy;
328
+	}
329
+
330
+
331
+
332
+	/**
333
+	 * Gets sensitive_data_removal_strategy
334
+	 *
335
+	 * @return EE_Sensitive_Data_Removal_Base
336
+	 */
337
+	public function get_sensitive_data_removal_strategy()
338
+	{
339
+		return $this->_sensitive_data_removal_strategy;
340
+	}
341
+
342
+
343
+
344
+	/**
345
+	 * Sets sensitive_data_removal_strategy
346
+	 *
347
+	 * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
348
+	 * @return boolean
349
+	 */
350
+	public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
351
+	{
352
+		$this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
353
+	}
354
+
355
+
356
+
357
+	/**
358
+	 * Gets the display strategy for this input
359
+	 *
360
+	 * @return EE_Display_Strategy_Base
361
+	 */
362
+	public function get_display_strategy()
363
+	{
364
+		return $this->_display_strategy;
365
+	}
366
+
367
+
368
+
369
+	/**
370
+	 * Overwrites the display strategy
371
+	 *
372
+	 * @param EE_Display_Strategy_Base $display_strategy
373
+	 */
374
+	public function set_display_strategy($display_strategy)
375
+	{
376
+		$this->_display_strategy = $display_strategy;
377
+		$this->_display_strategy->_construct_finalize($this);
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * Gets the normalization strategy set on this input
384
+	 *
385
+	 * @return EE_Normalization_Strategy_Base
386
+	 */
387
+	public function get_normalization_strategy()
388
+	{
389
+		return $this->_normalization_strategy;
390
+	}
391
+
392
+
393
+
394
+	/**
395
+	 * Overwrites the normalization strategy
396
+	 *
397
+	 * @param EE_Normalization_Strategy_Base $normalization_strategy
398
+	 */
399
+	public function set_normalization_strategy($normalization_strategy)
400
+	{
401
+		$this->_normalization_strategy = $normalization_strategy;
402
+		$this->_normalization_strategy->_construct_finalize($this);
403
+	}
404
+
405
+
406
+
407
+	/**
408
+	 * Returns all teh validation strategies which apply to this field, numerically indexed
409
+	 *
410
+	 * @return EE_Validation_Strategy_Base[]
411
+	 */
412
+	public function get_validation_strategies()
413
+	{
414
+		return $this->_validation_strategies;
415
+	}
416
+
417
+
418
+
419
+	/**
420
+	 * Adds this strategy to the field so it will be used in both JS validation and server-side validation
421
+	 *
422
+	 * @param EE_Validation_Strategy_Base $validation_strategy
423
+	 * @return void
424
+	 */
425
+	protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
426
+	{
427
+		$validation_strategy->_construct_finalize($this);
428
+		$this->_validation_strategies[] = $validation_strategy;
429
+	}
430
+
431
+
432
+
433
+	/**
434
+	 * Adds a new validation strategy onto the form input
435
+	 *
436
+	 * @param EE_Validation_Strategy_Base $validation_strategy
437
+	 * @return void
438
+	 */
439
+	public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
440
+	{
441
+		$this->_add_validation_strategy($validation_strategy);
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 * The classname of the validation strategy to remove
448
+	 *
449
+	 * @param string $validation_strategy_classname
450
+	 */
451
+	public function remove_validation_strategy($validation_strategy_classname)
452
+	{
453
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
454
+			if (
455
+				$validation_strategy instanceof $validation_strategy_classname
456
+				|| is_subclass_of($validation_strategy, $validation_strategy_classname)
457
+			) {
458
+				unset($this->_validation_strategies[$key]);
459
+			}
460
+		}
461
+	}
462
+
463
+
464
+
465
+	/**
466
+	 * returns true if input employs any of the validation strategy defined by the supplied array of classnames
467
+	 *
468
+	 * @param array $validation_strategy_classnames
469
+	 * @return bool
470
+	 */
471
+	public function has_validation_strategy($validation_strategy_classnames)
472
+	{
473
+		$validation_strategy_classnames = is_array($validation_strategy_classnames)
474
+			? $validation_strategy_classnames
475
+			: array($validation_strategy_classnames);
476
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
477
+			if (in_array($key, $validation_strategy_classnames)) {
478
+				return true;
479
+			}
480
+		}
481
+		return false;
482
+	}
483
+
484
+
485
+
486
+	/**
487
+	 * Gets the HTML
488
+	 *
489
+	 * @return string
490
+	 */
491
+	public function get_html()
492
+	{
493
+		return $this->_parent_section->get_html_for_input($this);
494
+	}
495
+
496
+
497
+
498
+	/**
499
+	 * Gets the HTML for the input itself (no label or errors) according to the
500
+	 * input's display strategy
501
+	 * Makes sure the JS and CSS are enqueued for it
502
+	 *
503
+	 * @return string
504
+	 * @throws \EE_Error
505
+	 */
506
+	public function get_html_for_input()
507
+	{
508
+		return $this->_form_html_filter
509
+			? $this->_form_html_filter->filterHtml(
510
+				$this->_get_display_strategy()->display(),
511
+				$this
512
+			)
513
+			: $this->_get_display_strategy()->display();
514
+	}
515
+
516
+
517
+
518
+	/**
519
+	 * @return string
520
+	 */
521
+	public function html_other_attributes()
522
+	{
523
+		return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * @param string $html_other_attributes
530
+	 */
531
+	public function set_html_other_attributes($html_other_attributes)
532
+	{
533
+		$this->_html_other_attributes = $html_other_attributes;
534
+	}
535
+
536
+
537
+
538
+	/**
539
+	 * Gets the HTML for displaying the label for this form input
540
+	 * according to the form section's layout strategy
541
+	 *
542
+	 * @return string
543
+	 */
544
+	public function get_html_for_label()
545
+	{
546
+		return $this->_parent_section->get_layout_strategy()->display_label($this);
547
+	}
548
+
549
+
550
+
551
+	/**
552
+	 * Gets the HTML for displaying the errors section for this form input
553
+	 * according to the form section's layout strategy
554
+	 *
555
+	 * @return string
556
+	 */
557
+	public function get_html_for_errors()
558
+	{
559
+		return $this->_parent_section->get_layout_strategy()->display_errors($this);
560
+	}
561
+
562
+
563
+
564
+	/**
565
+	 * Gets the HTML for displaying the help text for this form input
566
+	 * according to the form section's layout strategy
567
+	 *
568
+	 * @return string
569
+	 */
570
+	public function get_html_for_help()
571
+	{
572
+		return $this->_parent_section->get_layout_strategy()->display_help_text($this);
573
+	}
574
+
575
+
576
+
577
+	/**
578
+	 * Validates the input's sanitized value (assumes _sanitize() has already been called)
579
+	 * and returns whether or not the form input's submitted value is value
580
+	 *
581
+	 * @return boolean
582
+	 */
583
+	protected function _validate()
584
+	{
585
+		foreach ($this->_validation_strategies as $validation_strategy) {
586
+			if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
587
+				try {
588
+					$validation_strategy->validate($this->normalized_value());
589
+				} catch (EE_Validation_Error $e) {
590
+					$this->add_validation_error($e);
591
+				}
592
+			}
593
+		}
594
+		if ($this->get_validation_errors()) {
595
+			return false;
596
+		} else {
597
+			return true;
598
+		}
599
+	}
600
+
601
+
602
+
603
+	/**
604
+	 * Performs basic sanitization on this value. But what sanitization can be performed anyways?
605
+	 * This value MIGHT be allowed to have tags, so we can't really remove them.
606
+	 *
607
+	 * @param string $value
608
+	 * @return null|string
609
+	 */
610
+	private function _sanitize($value)
611
+	{
612
+		return $value !== null ? stripslashes(html_entity_decode(trim($value))) : null;
613
+	}
614
+
615
+
616
+
617
+	/**
618
+	 * Picks out the form value that relates to this form input,
619
+	 * and stores it as the sanitized value on the form input, and sets the normalized value.
620
+	 * Returns whether or not any validation errors occurred
621
+	 *
622
+	 * @param array $req_data like $_POST
623
+	 * @return boolean whether or not there was an error
624
+	 * @throws \EE_Error
625
+	 */
626
+	protected function _normalize($req_data)
627
+	{
628
+		//any existing validation errors don't apply so clear them
629
+		$this->_validation_errors = array();
630
+		try {
631
+			$raw_input = $this->find_form_data_for_this_section($req_data);
632
+			//super simple sanitization for now
633
+			if (is_array($raw_input)) {
634
+				$raw_value = array();
635
+				foreach ($raw_input as $key => $value) {
636
+					$raw_value[$key] = $this->_sanitize($value);
637
+				}
638
+				$this->_set_raw_value($raw_value);
639
+			} else {
640
+				$this->_set_raw_value($this->_sanitize($raw_input));
641
+			}
642
+			//we want to mostly leave the input alone in case we need to re-display it to the user
643
+			$this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
644
+		} catch (EE_Validation_Error $e) {
645
+			$this->add_validation_error($e);
646
+		}
647
+	}
648
+
649
+
650
+
651
+	/**
652
+	 * @return string
653
+	 */
654
+	public function html_name()
655
+	{
656
+		$this->_set_default_html_name_if_empty();
657
+		return $this->_html_name;
658
+	}
659
+
660
+
661
+
662
+	/**
663
+	 * @return string
664
+	 */
665
+	public function html_label_id()
666
+	{
667
+		return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id() . '-lbl';
668
+	}
669
+
670
+
671
+
672
+	/**
673
+	 * @return string
674
+	 */
675
+	public function html_label_class()
676
+	{
677
+		return $this->_html_label_class;
678
+	}
679
+
680
+
681
+
682
+	/**
683
+	 * @return string
684
+	 */
685
+	public function html_label_style()
686
+	{
687
+		return $this->_html_label_style;
688
+	}
689
+
690
+
691
+
692
+	/**
693
+	 * @return string
694
+	 */
695
+	public function html_label_text()
696
+	{
697
+		return $this->_html_label_text;
698
+	}
699
+
700
+
701
+
702
+	/**
703
+	 * @return string
704
+	 */
705
+	public function html_help_text()
706
+	{
707
+		return $this->_html_help_text;
708
+	}
709
+
710
+
711
+
712
+	/**
713
+	 * @return string
714
+	 */
715
+	public function html_help_class()
716
+	{
717
+		return $this->_html_help_class;
718
+	}
719
+
720
+
721
+
722
+	/**
723
+	 * @return string
724
+	 */
725
+	public function html_help_style()
726
+	{
727
+		return $this->_html_style;
728
+	}
729
+
730
+
731
+
732
+	/**
733
+	 * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
734
+	 * Please note that almost all client code should instead use the normalized_value;
735
+	 * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
736
+	 * mostly by escaping quotes)
737
+	 * Note, we do not store the exact original value sent in the user's request because
738
+	 * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
739
+	 * in which case, we would have stored the malicious content to our database.
740
+	 *
741
+	 * @return string
742
+	 */
743
+	public function raw_value()
744
+	{
745
+		return $this->_raw_value;
746
+	}
747
+
748
+
749
+
750
+	/**
751
+	 * Returns a string safe to usage in form inputs when displaying, because
752
+	 * it escapes all html entities
753
+	 *
754
+	 * @return string
755
+	 */
756
+	public function raw_value_in_form()
757
+	{
758
+		return htmlentities($this->raw_value(), ENT_QUOTES, 'UTF-8');
759
+	}
760
+
761
+
762
+
763
+	/**
764
+	 * returns the value after it's been sanitized, and then converted into it's proper type
765
+	 * in PHP. Eg, a string, an int, an array,
766
+	 *
767
+	 * @return mixed
768
+	 */
769
+	public function normalized_value()
770
+	{
771
+		return $this->_normalized_value;
772
+	}
773
+
774
+
775
+
776
+	/**
777
+	 * Returns the normalized value is a presentable way. By default this is just
778
+	 * the normalized value by itself, but it can be overridden for when that's not
779
+	 * the best thing to display
780
+	 *
781
+	 * @return string
782
+	 */
783
+	public function pretty_value()
784
+	{
785
+		return $this->_normalized_value;
786
+	}
787
+
788
+
789
+
790
+	/**
791
+	 * When generating the JS for the jquery validation rules like<br>
792
+	 * <code>$( "#myform" ).validate({
793
+	 * rules: {
794
+	 * password: "required",
795
+	 * password_again: {
796
+	 * equalTo: "#password"
797
+	 * }
798
+	 * }
799
+	 * });</code>
800
+	 * if this field had the name 'password_again', it should return
801
+	 * <br><code>password_again: {
802
+	 * equalTo: "#password"
803
+	 * }</code>
804
+	 *
805
+	 * @return array
806
+	 */
807
+	public function get_jquery_validation_rules()
808
+	{
809
+		$jquery_validation_js = array();
810
+		$jquery_validation_rules = array();
811
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
812
+			$jquery_validation_rules = array_replace_recursive(
813
+				$jquery_validation_rules,
814
+				$validation_strategy->get_jquery_validation_rule_array()
815
+			);
816
+		}
817
+		if (! empty($jquery_validation_rules)) {
818
+			foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
819
+				$jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
820
+			}
821
+		}
822
+		return $jquery_validation_js;
823
+	}
824
+
825
+
826
+
827
+	/**
828
+	 * Sets the input's default value for use in displaying in the form. Note: value should be
829
+	 * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
830
+	 *
831
+	 * @param mixed $value
832
+	 * @return void
833
+	 */
834
+	public function set_default($value)
835
+	{
836
+		$this->_default = $value;
837
+		$this->_set_normalized_value($value);
838
+		$this->_set_raw_value($value);
839
+	}
840
+
841
+
842
+
843
+	/**
844
+	 * Sets the normalized value on this input
845
+	 *
846
+	 * @param mixed $value
847
+	 */
848
+	protected function _set_normalized_value($value)
849
+	{
850
+		$this->_normalized_value = $value;
851
+	}
852
+
853
+
854
+
855
+	/**
856
+	 * Sets the raw value on this input (ie, exactly as the user submitted it)
857
+	 *
858
+	 * @param mixed $value
859
+	 */
860
+	protected function _set_raw_value($value)
861
+	{
862
+		$this->_raw_value = $this->_normalization_strategy->unnormalize($value);
863
+	}
864
+
865
+
866
+
867
+	/**
868
+	 * Sets the HTML label text after it has already been defined
869
+	 *
870
+	 * @param string $label
871
+	 * @return void
872
+	 */
873
+	public function set_html_label_text($label)
874
+	{
875
+		$this->_html_label_text = $label;
876
+	}
877
+
878
+
879
+
880
+	/**
881
+	 * Sets whether or not this field is required, and adjusts the validation strategy.
882
+	 * If you want to use the EE_Conditionally_Required_Validation_Strategy,
883
+	 * please add it as a validation strategy using add_validation_strategy as normal
884
+	 *
885
+	 * @param boolean $required boolean
886
+	 * @param null    $required_text
887
+	 */
888
+	public function set_required($required = true, $required_text = null)
889
+	{
890
+		$required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
891
+		//whether $required is a string or a boolean, we want to add a required validation strategy
892
+		if ($required) {
893
+			$this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
894
+		} else {
895
+			$this->remove_validation_strategy('EE_Required_Validation_Strategy');
896
+		}
897
+		$this->_required = $required;
898
+	}
899
+
900
+
901
+
902
+	/**
903
+	 * Returns whether or not this field is required
904
+	 *
905
+	 * @return boolean
906
+	 */
907
+	public function required()
908
+	{
909
+		return $this->_required;
910
+	}
911
+
912
+
913
+
914
+	/**
915
+	 * @param string $required_css_class
916
+	 */
917
+	public function set_required_css_class($required_css_class)
918
+	{
919
+		$this->_required_css_class = $required_css_class;
920
+	}
921
+
922
+
923
+
924
+	/**
925
+	 * @return string
926
+	 */
927
+	public function required_css_class()
928
+	{
929
+		return $this->_required_css_class;
930
+	}
931
+
932
+
933
+
934
+	/**
935
+	 * @param bool $add_required
936
+	 * @return string
937
+	 */
938
+	public function html_class($add_required = false)
939
+	{
940
+		return $add_required && $this->required()
941
+			? $this->required_css_class() . ' ' . $this->_html_class
942
+			: $this->_html_class;
943
+	}
944
+
945
+
946
+	/**
947
+	 * Sets the help text, in case
948
+	 *
949
+	 * @param string $text
950
+	 */
951
+	public function set_html_help_text($text)
952
+	{
953
+		$this->_html_help_text = $text;
954
+	}
955
+
956
+
957
+
958
+	/**
959
+	 * Uses the sensitive data removal strategy to remove the sensitive data from this
960
+	 * input. If there is any kind of sensitive data removal on this input, we clear
961
+	 * out the raw value completely
962
+	 *
963
+	 * @return void
964
+	 */
965
+	public function clean_sensitive_data()
966
+	{
967
+		//if we do ANY kind of sensitive data removal on this, then just clear out the raw value
968
+		//if we need more logic than this we'll make a strategy for it
969
+		if ($this->_sensitive_data_removal_strategy
970
+			&& ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
971
+		) {
972
+			$this->_set_raw_value(null);
973
+		}
974
+		//and clean the normalized value according to the appropriate strategy
975
+		$this->_set_normalized_value(
976
+			$this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
977
+				$this->_normalized_value
978
+			)
979
+		);
980
+	}
981
+
982
+
983
+
984
+	/**
985
+	 * @param bool   $primary
986
+	 * @param string $button_size
987
+	 * @param string $other_attributes
988
+	 */
989
+	public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
990
+	{
991
+		$button_css_attributes = 'button';
992
+		$button_css_attributes .= $primary === true ? ' button-primary' : ' button-secondary';
993
+		switch ($button_size) {
994
+			case 'xs' :
995
+			case 'extra-small' :
996
+				$button_css_attributes .= ' button-xs';
997
+				break;
998
+			case 'sm' :
999
+			case 'small' :
1000
+				$button_css_attributes .= ' button-sm';
1001
+				break;
1002
+			case 'lg' :
1003
+			case 'large' :
1004
+				$button_css_attributes .= ' button-lg';
1005
+				break;
1006
+			case 'block' :
1007
+				$button_css_attributes .= ' button-block';
1008
+				break;
1009
+			case 'md' :
1010
+			case 'medium' :
1011
+			default :
1012
+				$button_css_attributes .= '';
1013
+		}
1014
+		$this->_button_css_attributes .= ! empty($other_attributes)
1015
+			? $button_css_attributes . ' ' . $other_attributes
1016
+			: $button_css_attributes;
1017
+	}
1018
+
1019
+
1020
+
1021
+	/**
1022
+	 * @return string
1023
+	 */
1024
+	public function button_css_attributes()
1025
+	{
1026
+		if (empty($this->_button_css_attributes)) {
1027
+			$this->set_button_css_attributes();
1028
+		}
1029
+		return $this->_button_css_attributes;
1030
+	}
1031
+
1032
+
1033
+
1034
+	/**
1035
+	 * find_form_data_for_this_section
1036
+	 * using this section's name and its parents, finds the value of the form data that corresponds to it.
1037
+	 * For example, if this form section's HTML name is my_form[subform][form_input_1],
1038
+	 * then it's value should be in $_REQUEST at $_REQUEST['my_form']['subform']['form_input_1'].
1039
+	 * (If that doesn't exist, we also check for this subsection's name
1040
+	 * at the TOP LEVEL of the request data. Eg $_REQUEST['form_input_1'].)
1041
+	 * This function finds its value in the form.
1042
+	 *
1043
+	 * @param array $req_data
1044
+	 * @return mixed whatever the raw value of this form section is in the request data
1045
+	 * @throws \EE_Error
1046
+	 */
1047
+	public function find_form_data_for_this_section($req_data)
1048
+	{
1049
+		// break up the html name by "[]"
1050
+		if (strpos($this->html_name(), '[') !== false) {
1051
+			$before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1052
+		} else {
1053
+			$before_any_brackets = $this->html_name();
1054
+		}
1055
+		// grab all of the segments
1056
+		preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1057
+		if (isset($matches[1]) && is_array($matches[1])) {
1058
+			$name_parts = $matches[1];
1059
+			array_unshift($name_parts, $before_any_brackets);
1060
+		} else {
1061
+			$name_parts = array($before_any_brackets);
1062
+		}
1063
+		// now get the value for the input
1064
+		$value = $this->_find_form_data_for_this_section_using_name_parts($name_parts, $req_data);
1065
+		// check if this thing's name is at the TOP level of the request data
1066
+		if ($value === null && isset($req_data[$this->name()])) {
1067
+			$value = $req_data[$this->name()];
1068
+		}
1069
+		return $value;
1070
+	}
1071
+
1072
+
1073
+
1074
+	/**
1075
+	 * @param array $html_name_parts
1076
+	 * @param array $req_data
1077
+	 * @return array | NULL
1078
+	 */
1079
+	public function _find_form_data_for_this_section_using_name_parts($html_name_parts, $req_data)
1080
+	{
1081
+		$first_part_to_consider = array_shift($html_name_parts);
1082
+		if (isset($req_data[$first_part_to_consider])) {
1083
+			if (empty($html_name_parts)) {
1084
+				return $req_data[$first_part_to_consider];
1085
+			} else {
1086
+				return $this->_find_form_data_for_this_section_using_name_parts(
1087
+					$html_name_parts,
1088
+					$req_data[$first_part_to_consider]
1089
+				);
1090
+			}
1091
+		} else {
1092
+			return null;
1093
+		}
1094
+	}
1095
+
1096
+
1097
+
1098
+	/**
1099
+	 * Checks if this form input's data is in the request data
1100
+	 *
1101
+	 * @param array $req_data like $_POST
1102
+	 * @return boolean
1103
+	 * @throws \EE_Error
1104
+	 */
1105
+	public function form_data_present_in($req_data = null)
1106
+	{
1107
+		if ($req_data === null) {
1108
+			$req_data = $_POST;
1109
+		}
1110
+		$checked_value = $this->find_form_data_for_this_section($req_data);
1111
+		if ($checked_value !== null) {
1112
+			return true;
1113
+		} else {
1114
+			return false;
1115
+		}
1116
+	}
1117
+
1118
+
1119
+
1120
+	/**
1121
+	 * Overrides parent to add js data from validation and display strategies
1122
+	 *
1123
+	 * @param array $form_other_js_data
1124
+	 * @return array
1125
+	 */
1126
+	public function get_other_js_data($form_other_js_data = array())
1127
+	{
1128
+		$form_other_js_data = $this->get_other_js_data_from_strategies($form_other_js_data);
1129
+		return $form_other_js_data;
1130
+	}
1131
+
1132
+
1133
+
1134
+	/**
1135
+	 * Gets other JS data for localization from this input's strategies, like
1136
+	 * the validation strategies and the display strategy
1137
+	 *
1138
+	 * @param array $form_other_js_data
1139
+	 * @return array
1140
+	 */
1141
+	public function get_other_js_data_from_strategies($form_other_js_data = array())
1142
+	{
1143
+		$form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1144
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1145
+			$form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1146
+		}
1147
+		return $form_other_js_data;
1148
+	}
1149
+
1150
+
1151
+
1152
+	/**
1153
+	 * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1154
+	 *
1155
+	 * @return void
1156
+	 */
1157
+	public function enqueue_js()
1158
+	{
1159
+		//ask our display strategy and validation strategies if they have js to enqueue
1160
+		$this->enqueue_js_from_strategies();
1161
+	}
1162
+
1163
+
1164
+
1165
+	/**
1166
+	 * Tells strategies when its ok to enqueue their js and css
1167
+	 *
1168
+	 * @return void
1169
+	 */
1170
+	public function enqueue_js_from_strategies()
1171
+	{
1172
+		$this->get_display_strategy()->enqueue_js();
1173
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1174
+			$validation_strategy->enqueue_js();
1175
+		}
1176
+	}
1177
+
1178
+
1179
+
1180
+	/**
1181
+	 * Gets the default value set on the input (not the current value, which may have been
1182
+	 * changed because of a form submission). If no default was set, this us null.
1183
+	 * @return mixed
1184
+	 */
1185
+	public function get_default()
1186
+	{
1187
+		return $this->_default;
1188
+	}
1189 1189
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 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
 
@@ -191,23 +191,23 @@  discard block
 block discarded – undo
191 191
      */
192 192
     public function __construct($input_args = array())
193 193
     {
194
-        $input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
194
+        $input_args = (array) apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
195 195
         // the following properties must be cast as arrays
196 196
         if (isset($input_args['validation_strategies'])) {
197
-            foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
197
+            foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
198 198
                 if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
199 199
                     $this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
200 200
                 }
201 201
             }
202 202
             unset($input_args['validation_strategies']);
203 203
         }
204
-        if(isset($input_args['ignore_input'])) {
204
+        if (isset($input_args['ignore_input'])) {
205 205
             $this->_validation_strategies = array();
206 206
         }
207 207
         // loop thru incoming options
208 208
         foreach ($input_args as $key => $value) {
209 209
             // add underscore to $key to match property names
210
-            $_key = '_' . $key;
210
+            $_key = '_'.$key;
211 211
             if (property_exists($this, $_key)) {
212 212
                 $this->{$_key} = $value;
213 213
             }
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
         if (isset($input_args['ignore_input'])) {
227 227
             $this->_normalization_strategy = new EE_Null_Normalization();
228 228
         }
229
-        if (! $this->_normalization_strategy) {
229
+        if ( ! $this->_normalization_strategy) {
230 230
                 $this->_normalization_strategy = new EE_Text_Normalization();
231 231
         }
232 232
         $this->_normalization_strategy->_construct_finalize($this);
@@ -235,7 +235,7 @@  discard block
 block discarded – undo
235 235
             $this->set_default($input_args['default']);
236 236
             unset($input_args['default']);
237 237
         }
238
-        if (! $this->_sensitive_data_removal_strategy) {
238
+        if ( ! $this->_sensitive_data_removal_strategy) {
239 239
             $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
240 240
         }
241 241
         $this->_sensitive_data_removal_strategy->_construct_finalize($this);
@@ -252,10 +252,10 @@  discard block
 block discarded – undo
252 252
      */
253 253
     protected function _set_default_html_name_if_empty()
254 254
     {
255
-        if (! $this->_html_name) {
255
+        if ( ! $this->_html_name) {
256 256
             $this->_html_name = $this->name();
257 257
             if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
258
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
258
+                $this->_html_name = $this->_parent_section->html_name_prefix()."[{$this->name()}]";
259 259
             }
260 260
         }
261 261
     }
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
     protected function _get_display_strategy()
288 288
     {
289 289
         $this->ensure_construct_finalized_called();
290
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
290
+        if ( ! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
291 291
             throw new EE_Error(
292 292
                 sprintf(
293 293
                     __(
@@ -520,7 +520,7 @@  discard block
 block discarded – undo
520 520
      */
521 521
     public function html_other_attributes()
522 522
     {
523
-        return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
523
+        return ! empty($this->_html_other_attributes) ? ' '.$this->_html_other_attributes : '';
524 524
     }
525 525
 
526 526
 
@@ -664,7 +664,7 @@  discard block
 block discarded – undo
664 664
      */
665 665
     public function html_label_id()
666 666
     {
667
-        return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id() . '-lbl';
667
+        return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id().'-lbl';
668 668
     }
669 669
 
670 670
 
@@ -814,7 +814,7 @@  discard block
 block discarded – undo
814 814
                 $validation_strategy->get_jquery_validation_rule_array()
815 815
             );
816 816
         }
817
-        if (! empty($jquery_validation_rules)) {
817
+        if ( ! empty($jquery_validation_rules)) {
818 818
             foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
819 819
                 $jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
820 820
             }
@@ -938,7 +938,7 @@  discard block
 block discarded – undo
938 938
     public function html_class($add_required = false)
939 939
     {
940 940
         return $add_required && $this->required()
941
-            ? $this->required_css_class() . ' ' . $this->_html_class
941
+            ? $this->required_css_class().' '.$this->_html_class
942 942
             : $this->_html_class;
943 943
     }
944 944
 
@@ -1012,7 +1012,7 @@  discard block
 block discarded – undo
1012 1012
                 $button_css_attributes .= '';
1013 1013
         }
1014 1014
         $this->_button_css_attributes .= ! empty($other_attributes)
1015
-            ? $button_css_attributes . ' ' . $other_attributes
1015
+            ? $button_css_attributes.' '.$other_attributes
1016 1016
             : $button_css_attributes;
1017 1017
     }
1018 1018
 
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Proper.form.php 3 patches
Doc Comments   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
      *                                                      with construction finalize being called later
460 460
      *                                                      (realizing that the subsections' html names
461 461
      *                                                      might not be set yet, etc.)
462
-     * @return EE_Form_Section_Base
462
+     * @return EE_Form_Section_Validatable|null
463 463
      * @throws EE_Error
464 464
      */
465 465
     public function get_subsection($name, $require_construction_to_be_finalized = true)
@@ -1289,7 +1289,6 @@  discard block
 block discarded – undo
1289 1289
     /**
1290 1290
      * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1291 1291
      * @param string                           $form_submission_error_message
1292
-     * @param EE_Form_Section_Validatable $form_section unused
1293 1292
      * @throws EE_Error
1294 1293
      */
1295 1294
     public function set_submission_error_message(
Please login to merge, or discard this patch.
Spacing   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -111,8 +111,8 @@  discard block
 block discarded – undo
111 111
             //AND we are going to make sure they're in that specified order
112 112
             $reordered_subsections = array();
113 113
             foreach ($options_array['include'] as $input_name) {
114
-                if (isset($this->_subsections[ $input_name ])) {
115
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
114
+                if (isset($this->_subsections[$input_name])) {
115
+                    $reordered_subsections[$input_name] = $this->_subsections[$input_name];
116 116
                 }
117 117
             }
118 118
             $this->_subsections = $reordered_subsections;
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
         if (isset($options_array['layout_strategy'])) {
125 125
             $this->_layout_strategy = $options_array['layout_strategy'];
126 126
         }
127
-        if (! $this->_layout_strategy) {
127
+        if ( ! $this->_layout_strategy) {
128 128
             $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129 129
         }
130 130
         $this->_layout_strategy->_construct_finalize($this);
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
                 $req_data,
278 278
                 $this
279 279
             );
280
-            $this->cached_request_data = (array)$req_data;
280
+            $this->cached_request_data = (array) $req_data;
281 281
         }
282 282
         return $this->cached_request_data;
283 283
     }
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
         if ($validate) {
314 314
             $this->_validate();
315 315
             //if it's invalid, we're going to want to re-display so remember what they submitted
316
-            if (! $this->is_valid()) {
316
+            if ( ! $this->is_valid()) {
317 317
                 $this->store_submitted_form_data_in_session();
318 318
             }
319 319
         }
@@ -426,11 +426,11 @@  discard block
 block discarded – undo
426 426
     public function populate_defaults($default_data)
427 427
     {
428 428
         foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
-            if (isset($default_data[ $subsection_name ])) {
429
+            if (isset($default_data[$subsection_name])) {
430 430
                 if ($subsection instanceof EE_Form_Input_Base) {
431
-                    $subsection->set_default($default_data[ $subsection_name ]);
431
+                    $subsection->set_default($default_data[$subsection_name]);
432 432
                 } elseif ($subsection instanceof EE_Form_Section_Proper) {
433
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
433
+                    $subsection->populate_defaults($default_data[$subsection_name]);
434 434
                 }
435 435
             }
436 436
         }
@@ -445,7 +445,7 @@  discard block
 block discarded – undo
445 445
      */
446 446
     public function subsection_exists($name)
447 447
     {
448
-        return isset($this->_subsections[ $name ]) ? true : false;
448
+        return isset($this->_subsections[$name]) ? true : false;
449 449
     }
450 450
 
451 451
 
@@ -467,7 +467,7 @@  discard block
 block discarded – undo
467 467
         if ($require_construction_to_be_finalized) {
468 468
             $this->ensure_construct_finalized_called();
469 469
         }
470
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
470
+        return $this->subsection_exists($name) ? $this->_subsections[$name] : null;
471 471
     }
472 472
 
473 473
 
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
         $validatable_subsections = array();
483 483
         foreach ($this->subsections() as $name => $obj) {
484 484
             if ($obj instanceof EE_Form_Section_Validatable) {
485
-                $validatable_subsections[ $name ] = $obj;
485
+                $validatable_subsections[$name] = $obj;
486 486
             }
487 487
         }
488 488
         return $validatable_subsections;
@@ -509,7 +509,7 @@  discard block
 block discarded – undo
509 509
             $name,
510 510
             $require_construction_to_be_finalized
511 511
         );
512
-        if (! $subsection instanceof EE_Form_Input_Base) {
512
+        if ( ! $subsection instanceof EE_Form_Input_Base) {
513 513
             throw new EE_Error(
514 514
                 sprintf(
515 515
                     esc_html__(
@@ -546,7 +546,7 @@  discard block
 block discarded – undo
546 546
             $name,
547 547
             $require_construction_to_be_finalized
548 548
         );
549
-        if (! $subsection instanceof EE_Form_Section_Proper) {
549
+        if ( ! $subsection instanceof EE_Form_Section_Proper) {
550 550
             throw new EE_Error(
551 551
                 sprintf(
552 552
                     esc_html__(
@@ -585,8 +585,8 @@  discard block
 block discarded – undo
585 585
      */
586 586
     public function is_valid()
587 587
     {
588
-        if($this->is_valid === null) {
589
-            if (! $this->has_received_submission()) {
588
+        if ($this->is_valid === null) {
589
+            if ( ! $this->has_received_submission()) {
590 590
                 throw new EE_Error(
591 591
                     sprintf(
592 592
                         esc_html__(
@@ -596,14 +596,14 @@  discard block
 block discarded – undo
596 596
                     )
597 597
                 );
598 598
             }
599
-            if (! parent::is_valid()) {
599
+            if ( ! parent::is_valid()) {
600 600
                 $this->is_valid = false;
601 601
             } else {
602 602
                 // ok so no general errors to this entire form section.
603 603
                 // so let's check the subsections, but only set errors if that hasn't been done yet
604 604
                 $this->is_valid = true;
605 605
                 foreach ($this->get_validatable_subsections() as $subsection) {
606
-                    if (! $subsection->is_valid()) {
606
+                    if ( ! $subsection->is_valid()) {
607 607
                         $this->is_valid = false;
608 608
                     }
609 609
                 }
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
      */
621 621
     protected function _set_default_name_if_empty()
622 622
     {
623
-        if (! $this->_name) {
623
+        if ( ! $this->_name) {
624 624
             $classname    = get_class($this);
625 625
             $default_name = str_replace('EE_', '', $classname);
626 626
             $this->_name  = $default_name;
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
     {
711 711
         wp_register_script(
712 712
             'ee_form_section_validation',
713
-            EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
713
+            EE_GLOBAL_ASSETS_URL.'scripts'.DS.'form_section_validation.js',
714 714
             array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715 715
             EVENT_ESPRESSO_VERSION,
716 716
             true
@@ -754,13 +754,13 @@  discard block
 block discarded – undo
754 754
         // we only want to localize vars ONCE for the entire form,
755 755
         // so if the form section doesn't have a parent, then it must be the top dog
756 756
         if ($return_for_subsection || ! $this->parent_section()) {
757
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
757
+            EE_Form_Section_Proper::$_js_localization['form_data'][$this->html_id()] = array(
758 758
                 'form_section_id'  => $this->html_id(true),
759 759
                 'validation_rules' => $this->get_jquery_validation_rules(),
760 760
                 'other_data'       => $this->get_other_js_data(),
761 761
                 'errors'           => $this->subsection_validation_errors_by_html_name(),
762 762
             );
763
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
763
+            EE_Form_Section_Proper::$_scripts_localized = true;
764 764
         }
765 765
     }
766 766
 
@@ -795,7 +795,7 @@  discard block
 block discarded – undo
795 795
         $inputs = array();
796 796
         foreach ($this->subsections() as $subsection) {
797 797
             if ($subsection instanceof EE_Form_Input_Base) {
798
-                $inputs[ $subsection->html_name() ] = $subsection;
798
+                $inputs[$subsection->html_name()] = $subsection;
799 799
             } elseif ($subsection instanceof EE_Form_Section_Proper) {
800 800
                 $inputs += $subsection->inputs_in_subsections();
801 801
             }
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
         $errors = array();
819 819
         foreach ($inputs as $form_input) {
820 820
             if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
821
+                $errors[$form_input->html_name()] = $form_input->get_validation_error_string();
822 822
             }
823 823
         }
824 824
         return $errors;
@@ -841,7 +841,7 @@  discard block
 block discarded – undo
841 841
         $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842 842
             ? EE_Registry::instance()->CFG->registration->email_validation_level
843 843
             : 'wp_default';
844
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
844
+        EE_Form_Section_Proper::$_js_localization['email_validation_level'] = $email_validation_level;
845 845
         wp_enqueue_script('ee_form_section_validation');
846 846
         wp_localize_script(
847 847
             'ee_form_section_validation',
@@ -858,7 +858,7 @@  discard block
 block discarded – undo
858 858
      */
859 859
     public function ensure_scripts_localized()
860 860
     {
861
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
861
+        if ( ! EE_Form_Section_Proper::$_scripts_localized) {
862 862
             $this->_enqueue_and_localize_form_js();
863 863
         }
864 864
     }
@@ -954,8 +954,8 @@  discard block
 block discarded – undo
954 954
         //reset the cache of whether this form is valid or not- we're re-validating it now
955 955
         $this->is_valid = null;
956 956
         foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
-            if (method_exists($this, '_validate_' . $subsection_name)) {
958
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
957
+            if (method_exists($this, '_validate_'.$subsection_name)) {
958
+                call_user_func_array(array($this, '_validate_'.$subsection_name), array($subsection));
959 959
             }
960 960
             $subsection->_validate();
961 961
         }
@@ -973,9 +973,9 @@  discard block
 block discarded – undo
973 973
         $inputs = array();
974 974
         foreach ($this->subsections() as $subsection_name => $subsection) {
975 975
             if ($subsection instanceof EE_Form_Section_Proper) {
976
-                $inputs[ $subsection_name ] = $subsection->valid_data();
976
+                $inputs[$subsection_name] = $subsection->valid_data();
977 977
             } elseif ($subsection instanceof EE_Form_Input_Base) {
978
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
978
+                $inputs[$subsection_name] = $subsection->normalized_value();
979 979
             }
980 980
         }
981 981
         return $inputs;
@@ -993,7 +993,7 @@  discard block
 block discarded – undo
993 993
         $inputs = array();
994 994
         foreach ($this->subsections() as $subsection_name => $subsection) {
995 995
             if ($subsection instanceof EE_Form_Input_Base) {
996
-                $inputs[ $subsection_name ] = $subsection;
996
+                $inputs[$subsection_name] = $subsection;
997 997
             }
998 998
         }
999 999
         return $inputs;
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
         $form_sections = array();
1012 1012
         foreach ($this->subsections() as $name => $obj) {
1013 1013
             if ($obj instanceof EE_Form_Section_Proper) {
1014
-                $form_sections[ $name ] = $obj;
1014
+                $form_sections[$name] = $obj;
1015 1015
             }
1016 1016
         }
1017 1017
         return $form_sections;
@@ -1118,7 +1118,7 @@  discard block
 block discarded – undo
1118 1118
         $input_values = array();
1119 1119
         foreach ($this->subsections() as $subsection_name => $subsection) {
1120 1120
             if ($subsection instanceof EE_Form_Input_Base) {
1121
-                $input_values[ $subsection_name ] = $pretty
1121
+                $input_values[$subsection_name] = $pretty
1122 1122
                     ? $subsection->pretty_value()
1123 1123
                     : $subsection->normalized_value();
1124 1124
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
@@ -1130,7 +1130,7 @@  discard block
 block discarded – undo
1130 1130
                 if ($flatten) {
1131 1131
                     $input_values = array_merge($input_values, $subform_input_values);
1132 1132
                 } else {
1133
-                    $input_values[ $subsection_name ] = $subform_input_values;
1133
+                    $input_values[$subsection_name] = $subform_input_values;
1134 1134
                 }
1135 1135
             }
1136 1136
         }
@@ -1158,7 +1158,7 @@  discard block
 block discarded – undo
1158 1158
             if ($subsection instanceof EE_Form_Input_Base) {
1159 1159
                 // is this input part of an array of inputs?
1160 1160
                 if (strpos($subsection->html_name(), '[') !== false) {
1161
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1161
+                    $full_input_name = EEH_Array::convert_array_values_to_keys(
1162 1162
                         explode(
1163 1163
                             '[',
1164 1164
                             str_replace(']', '', $subsection->html_name())
@@ -1167,7 +1167,7 @@  discard block
 block discarded – undo
1167 1167
                     );
1168 1168
                     $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169 1169
                 } else {
1170
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1170
+                    $submitted_values[$subsection->html_name()] = $subsection->raw_value();
1171 1171
                 }
1172 1172
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173 1173
                 $subform_input_values = $subsection->submitted_values($include_subforms);
@@ -1202,7 +1202,7 @@  discard block
 block discarded – undo
1202 1202
     public function exclude(array $inputs_to_exclude = array())
1203 1203
     {
1204 1204
         foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
-            unset($this->_subsections[ $input_to_exclude_name ]);
1205
+            unset($this->_subsections[$input_to_exclude_name]);
1206 1206
         }
1207 1207
     }
1208 1208
 
@@ -1244,7 +1244,7 @@  discard block
 block discarded – undo
1244 1244
     public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1245 1245
     {
1246 1246
         foreach ($new_subsections as $subsection_name => $subsection) {
1247
-            if (! $subsection instanceof EE_Form_Section_Base) {
1247
+            if ( ! $subsection instanceof EE_Form_Section_Base) {
1248 1248
                 EE_Error::add_error(
1249 1249
                     sprintf(
1250 1250
                         esc_html__(
@@ -1256,7 +1256,7 @@  discard block
 block discarded – undo
1256 1256
                         $this->name()
1257 1257
                     )
1258 1258
                 );
1259
-                unset($new_subsections[ $subsection_name ]);
1259
+                unset($new_subsections[$subsection_name]);
1260 1260
             }
1261 1261
         }
1262 1262
         $this->_subsections = EEH_Array::insert_into_array(
@@ -1348,7 +1348,7 @@  discard block
 block discarded – undo
1348 1348
     public function html_name_prefix()
1349 1349
     {
1350 1350
         if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1351
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1351
+            return $this->parent_section()->html_name_prefix().'['.$this->name().']';
1352 1352
         }
1353 1353
         return $this->name();
1354 1354
     }
@@ -1388,7 +1388,7 @@  discard block
 block discarded – undo
1388 1388
      */
1389 1389
     public function ensure_construct_finalized_called()
1390 1390
     {
1391
-        if (! $this->_construction_finalized) {
1391
+        if ( ! $this->_construction_finalized) {
1392 1392
             $this->_construct_finalize($this->_parent_section, $this->_name);
1393 1393
         }
1394 1394
     }
@@ -1460,7 +1460,7 @@  discard block
 block discarded – undo
1460 1460
                 $form_section = $validation_error->get_form_section();
1461 1461
                 if ($form_section instanceof EE_Form_Input_Base) {
1462 1462
                    $label = $validation_error->get_form_section()->html_label_text();
1463
-                } elseif($form_section instanceof EE_Form_Section_Validatable) {
1463
+                } elseif ($form_section instanceof EE_Form_Section_Validatable) {
1464 1464
                     $label = $validation_error->get_form_section()->name();
1465 1465
                 } else {
1466 1466
                     $label = esc_html__('Unknown', 'event_espresso');
Please login to merge, or discard this patch.
Indentation   +1501 added lines, -1501 removed lines patch added patch discarded remove patch
@@ -14,1506 +14,1506 @@
 block discarded – undo
14 14
 class EE_Form_Section_Proper extends EE_Form_Section_Validatable
15 15
 {
16 16
 
17
-    const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
-
19
-    /**
20
-     * Subsections
21
-     *
22
-     * @var EE_Form_Section_Validatable[]
23
-     */
24
-    protected $_subsections = array();
25
-
26
-    /**
27
-     * Strategy for laying out the form
28
-     *
29
-     * @var EE_Form_Section_Layout_Base
30
-     */
31
-    protected $_layout_strategy;
32
-
33
-    /**
34
-     * Whether or not this form has received and validated a form submission yet
35
-     *
36
-     * @var boolean
37
-     */
38
-    protected $_received_submission = false;
39
-
40
-    /**
41
-     * message displayed to users upon successful form submission
42
-     *
43
-     * @var string
44
-     */
45
-    protected $_form_submission_success_message = '';
46
-
47
-    /**
48
-     * message displayed to users upon unsuccessful form submission
49
-     *
50
-     * @var string
51
-     */
52
-    protected $_form_submission_error_message = '';
53
-
54
-    /**
55
-     * @var array like $_REQUEST
56
-     */
57
-    protected $cached_request_data;
58
-
59
-    /**
60
-     * Stores whether this form (and its sub-sections) were found to be valid or not.
61
-     * Starts off as null, but once the form is validated, it set to either true or false
62
-     * @var boolean|null
63
-     */
64
-    protected $is_valid;
65
-
66
-    /**
67
-     * Stores all the data that will localized for form validation
68
-     *
69
-     * @var array
70
-     */
71
-    static protected $_js_localization = array();
72
-
73
-    /**
74
-     * whether or not the form's localized validation JS vars have been set
75
-     *
76
-     * @type boolean
77
-     */
78
-    static protected $_scripts_localized = false;
79
-
80
-
81
-    /**
82
-     * when constructing a proper form section, calls _construct_finalize on children
83
-     * so that they know who their parent is, and what name they've been given.
84
-     *
85
-     * @param array[] $options_array   {
86
-     * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
-     * @type          $include         string[] numerically-indexed where values are section names to be included,
88
-     *                                 and in that order. This is handy if you want
89
-     *                                 the subsections to be ordered differently than the default, and if you override
90
-     *                                 which fields are shown
91
-     * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
-     *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
-     *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
-     *                                 items from that list of inclusions)
95
-     * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
-     *                                 } @see EE_Form_Section_Validatable::__construct()
97
-     * @throws EE_Error
98
-     */
99
-    public function __construct($options_array = array())
100
-    {
101
-        $options_array = (array) apply_filters(
102
-            'FHEE__EE_Form_Section_Proper___construct__options_array',
103
-            $options_array,
104
-            $this
105
-        );
106
-        //call parent first, as it may be setting the name
107
-        parent::__construct($options_array);
108
-        //if they've included subsections in the constructor, add them now
109
-        if (isset($options_array['include'])) {
110
-            //we are going to make sure we ONLY have those subsections to include
111
-            //AND we are going to make sure they're in that specified order
112
-            $reordered_subsections = array();
113
-            foreach ($options_array['include'] as $input_name) {
114
-                if (isset($this->_subsections[ $input_name ])) {
115
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
-                }
117
-            }
118
-            $this->_subsections = $reordered_subsections;
119
-        }
120
-        if (isset($options_array['exclude'])) {
121
-            $exclude            = $options_array['exclude'];
122
-            $this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
-        }
124
-        if (isset($options_array['layout_strategy'])) {
125
-            $this->_layout_strategy = $options_array['layout_strategy'];
126
-        }
127
-        if (! $this->_layout_strategy) {
128
-            $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
-        }
130
-        $this->_layout_strategy->_construct_finalize($this);
131
-        //ok so we are definitely going to want the forms JS,
132
-        //so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
-            //ok so they've constructed this object after when they should have.
135
-            //just enqueue the generic form scripts and initialize the form immediately in the JS
136
-            EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
-        } else {
138
-            add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
-            add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
-        }
141
-        add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
-        /**
143
-         * Gives other plugins a chance to hook in before construct finalize is called.
144
-         * The form probably doesn't yet have a parent form section.
145
-         * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
-         * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
-         * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
-         *
149
-         * @since 4.9.32
150
-         * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
-         *                                              except maybe calling _construct_finalize has been done
152
-         * @param array                  $options_array options passed into the constructor
153
-         */
154
-        do_action(
155
-            'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
-            $this,
157
-            $options_array
158
-        );
159
-        if (isset($options_array['name'])) {
160
-            $this->_construct_finalize(null, $options_array['name']);
161
-        }
162
-    }
163
-
164
-
165
-    /**
166
-     * Finishes construction given the parent form section and this form section's name
167
-     *
168
-     * @param EE_Form_Section_Proper $parent_form_section
169
-     * @param string                 $name
170
-     * @throws EE_Error
171
-     */
172
-    public function _construct_finalize($parent_form_section, $name)
173
-    {
174
-        parent::_construct_finalize($parent_form_section, $name);
175
-        $this->_set_default_name_if_empty();
176
-        $this->_set_default_html_id_if_empty();
177
-        foreach ($this->_subsections as $subsection_name => $subsection) {
178
-            if ($subsection instanceof EE_Form_Section_Base) {
179
-                $subsection->_construct_finalize($this, $subsection_name);
180
-            } else {
181
-                throw new EE_Error(
182
-                    sprintf(
183
-                        esc_html__(
184
-                            'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
-                            'event_espresso'
186
-                        ),
187
-                        $subsection_name,
188
-                        get_class($this),
189
-                        $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
-                    )
191
-                );
192
-            }
193
-        }
194
-        /**
195
-         * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
-         * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
-         * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
-         * This might only happen just before displaying the form, or just before it receives form submission data.
199
-         * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
-         * ensured it has a name, HTML IDs, etc
201
-         *
202
-         * @param EE_Form_Section_Proper      $this
203
-         * @param EE_Form_Section_Proper|null $parent_form_section
204
-         * @param string                      $name
205
-         */
206
-        do_action(
207
-            'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
-            $this,
209
-            $parent_form_section,
210
-            $name
211
-        );
212
-    }
213
-
214
-
215
-    /**
216
-     * Gets the layout strategy for this form section
217
-     *
218
-     * @return EE_Form_Section_Layout_Base
219
-     */
220
-    public function get_layout_strategy()
221
-    {
222
-        return $this->_layout_strategy;
223
-    }
224
-
225
-
226
-    /**
227
-     * Gets the HTML for a single input for this form section according
228
-     * to the layout strategy
229
-     *
230
-     * @param EE_Form_Input_Base $input
231
-     * @return string
232
-     */
233
-    public function get_html_for_input($input)
234
-    {
235
-        return $this->_layout_strategy->layout_input($input);
236
-    }
237
-
238
-
239
-    /**
240
-     * was_submitted - checks if form inputs are present in request data
241
-     * Basically an alias for form_data_present_in() (which is used by both
242
-     * proper form sections and form inputs)
243
-     *
244
-     * @param null $form_data
245
-     * @return boolean
246
-     * @throws EE_Error
247
-     */
248
-    public function was_submitted($form_data = null)
249
-    {
250
-        return $this->form_data_present_in($form_data);
251
-    }
252
-
253
-    /**
254
-     * Gets the cached request data; but if there is none, or $req_data was set with
255
-     * something different, refresh the cache, and then return it
256
-     * @param null $req_data
257
-     * @return array
258
-     */
259
-    protected function getCachedRequest($req_data = null)
260
-    {
261
-        if ($this->cached_request_data === null
262
-            || (
263
-                $req_data !== null &&
264
-                $req_data !== $this->cached_request_data
265
-            )
266
-        ) {
267
-            $req_data = apply_filters(
268
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
-                $req_data,
270
-                $this
271
-            );
272
-            if ($req_data === null) {
273
-                $req_data = array_merge($_GET, $_POST);
274
-            }
275
-            $req_data = apply_filters(
276
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
-                $req_data,
278
-                $this
279
-            );
280
-            $this->cached_request_data = (array)$req_data;
281
-        }
282
-        return $this->cached_request_data;
283
-    }
284
-
285
-
286
-    /**
287
-     * After the form section is initially created, call this to sanitize the data in the submission
288
-     * which relates to this form section, validate it, and set it as properties on the form.
289
-     *
290
-     * @param array|null $req_data should usually be $_POST (the default).
291
-     *                             However, you CAN supply a different array.
292
-     *                             Consider using set_defaults() instead however.
293
-     *                             (If you rendered the form in the page using echo $form_x->get_html()
294
-     *                             the inputs will have the correct name in the request data for this function
295
-     *                             to find them and populate the form with them.
296
-     *                             If you have a flat form (with only input subsections),
297
-     *                             you can supply a flat array where keys
298
-     *                             are the form input names and values are their values)
299
-     * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
-     *                             of course, to validate that data, and set errors on the invalid values.
301
-     *                             But if the data has already been validated
302
-     *                             (eg you validated the data then stored it in the DB)
303
-     *                             you may want to skip this step.
304
-     * @throws InvalidArgumentException
305
-     * @throws InvalidInterfaceException
306
-     * @throws InvalidDataTypeException
307
-     * @throws EE_Error
308
-     */
309
-    public function receive_form_submission($req_data = null, $validate = true)
310
-    {
311
-        $req_data = $this->getCachedRequest($req_data);
312
-        $this->_normalize($req_data);
313
-        if ($validate) {
314
-            $this->_validate();
315
-            //if it's invalid, we're going to want to re-display so remember what they submitted
316
-            if (! $this->is_valid()) {
317
-                $this->store_submitted_form_data_in_session();
318
-            }
319
-        }
320
-        if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
-            $this->set_submission_error_message();
322
-        }
323
-        do_action(
324
-            'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
-            $req_data,
326
-            $this,
327
-            $validate
328
-        );
329
-    }
330
-
331
-
332
-    /**
333
-     * caches the originally submitted input values in the session
334
-     * so that they can be used to repopulate the form if it failed validation
335
-     *
336
-     * @return boolean whether or not the data was successfully stored in the session
337
-     * @throws InvalidArgumentException
338
-     * @throws InvalidInterfaceException
339
-     * @throws InvalidDataTypeException
340
-     * @throws EE_Error
341
-     */
342
-    protected function store_submitted_form_data_in_session()
343
-    {
344
-        return EE_Registry::instance()->SSN->set_session_data(
345
-            array(
346
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
-            )
348
-        );
349
-    }
350
-
351
-
352
-    /**
353
-     * retrieves the originally submitted input values in the session
354
-     * so that they can be used to repopulate the form if it failed validation
355
-     *
356
-     * @return array
357
-     * @throws InvalidArgumentException
358
-     * @throws InvalidInterfaceException
359
-     * @throws InvalidDataTypeException
360
-     */
361
-    protected function get_submitted_form_data_from_session()
362
-    {
363
-        $session = EE_Registry::instance()->SSN;
364
-        if ($session instanceof EE_Session) {
365
-            return $session->get_session_data(
366
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
-            );
368
-        }
369
-        return array();
370
-    }
371
-
372
-
373
-    /**
374
-     * flushed the originally submitted input values from the session
375
-     *
376
-     * @return boolean whether or not the data was successfully removed from the session
377
-     * @throws InvalidArgumentException
378
-     * @throws InvalidInterfaceException
379
-     * @throws InvalidDataTypeException
380
-     */
381
-    protected function flush_submitted_form_data_from_session()
382
-    {
383
-        return EE_Registry::instance()->SSN->reset_data(
384
-            array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
-        );
386
-    }
387
-
388
-
389
-    /**
390
-     * Populates this form and its subsections with data from the session.
391
-     * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
-     * validation errors when displaying too)
393
-     * Returns true if the form was populated from the session, false otherwise
394
-     *
395
-     * @return boolean
396
-     * @throws InvalidArgumentException
397
-     * @throws InvalidInterfaceException
398
-     * @throws InvalidDataTypeException
399
-     * @throws EE_Error
400
-     */
401
-    public function populate_from_session()
402
-    {
403
-        $form_data_in_session = $this->get_submitted_form_data_from_session();
404
-        if (empty($form_data_in_session)) {
405
-            return false;
406
-        }
407
-        $this->receive_form_submission($form_data_in_session);
408
-        $this->flush_submitted_form_data_from_session();
409
-        if ($this->form_data_present_in($form_data_in_session)) {
410
-            return true;
411
-        }
412
-        return false;
413
-    }
414
-
415
-
416
-    /**
417
-     * Populates the default data for the form, given an array where keys are
418
-     * the input names, and values are their values (preferably normalized to be their
419
-     * proper PHP types, not all strings... although that should be ok too).
420
-     * Proper subsections are sub-arrays, the key being the subsection's name, and
421
-     * the value being an array formatted in teh same way
422
-     *
423
-     * @param array $default_data
424
-     * @throws EE_Error
425
-     */
426
-    public function populate_defaults($default_data)
427
-    {
428
-        foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
-            if (isset($default_data[ $subsection_name ])) {
430
-                if ($subsection instanceof EE_Form_Input_Base) {
431
-                    $subsection->set_default($default_data[ $subsection_name ]);
432
-                } elseif ($subsection instanceof EE_Form_Section_Proper) {
433
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
434
-                }
435
-            }
436
-        }
437
-    }
438
-
439
-
440
-    /**
441
-     * returns true if subsection exists
442
-     *
443
-     * @param string $name
444
-     * @return boolean
445
-     */
446
-    public function subsection_exists($name)
447
-    {
448
-        return isset($this->_subsections[ $name ]) ? true : false;
449
-    }
450
-
451
-
452
-    /**
453
-     * Gets the subsection specified by its name
454
-     *
455
-     * @param string  $name
456
-     * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
-     *                                                      so that the inputs will be properly configured.
458
-     *                                                      However, some client code may be ok
459
-     *                                                      with construction finalize being called later
460
-     *                                                      (realizing that the subsections' html names
461
-     *                                                      might not be set yet, etc.)
462
-     * @return EE_Form_Section_Base
463
-     * @throws EE_Error
464
-     */
465
-    public function get_subsection($name, $require_construction_to_be_finalized = true)
466
-    {
467
-        if ($require_construction_to_be_finalized) {
468
-            $this->ensure_construct_finalized_called();
469
-        }
470
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
-    }
472
-
473
-
474
-    /**
475
-     * Gets all the validatable subsections of this form section
476
-     *
477
-     * @return EE_Form_Section_Validatable[]
478
-     * @throws EE_Error
479
-     */
480
-    public function get_validatable_subsections()
481
-    {
482
-        $validatable_subsections = array();
483
-        foreach ($this->subsections() as $name => $obj) {
484
-            if ($obj instanceof EE_Form_Section_Validatable) {
485
-                $validatable_subsections[ $name ] = $obj;
486
-            }
487
-        }
488
-        return $validatable_subsections;
489
-    }
490
-
491
-
492
-    /**
493
-     * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
-     * throw an EE_Error.
495
-     *
496
-     * @param string  $name
497
-     * @param boolean $require_construction_to_be_finalized most client code should
498
-     *                                                      leave this as TRUE so that the inputs will be properly
499
-     *                                                      configured. However, some client code may be ok with
500
-     *                                                      construction finalize being called later
501
-     *                                                      (realizing that the subsections' html names might not be
502
-     *                                                      set yet, etc.)
503
-     * @return EE_Form_Input_Base
504
-     * @throws EE_Error
505
-     */
506
-    public function get_input($name, $require_construction_to_be_finalized = true)
507
-    {
508
-        $subsection = $this->get_subsection(
509
-            $name,
510
-            $require_construction_to_be_finalized
511
-        );
512
-        if (! $subsection instanceof EE_Form_Input_Base) {
513
-            throw new EE_Error(
514
-                sprintf(
515
-                    esc_html__(
516
-                        "Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
-                        'event_espresso'
518
-                    ),
519
-                    $name,
520
-                    get_class($this),
521
-                    $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
-                )
523
-            );
524
-        }
525
-        return $subsection;
526
-    }
527
-
528
-
529
-    /**
530
-     * Like get_input(), gets the proper subsection of the form given the name,
531
-     * otherwise throws an EE_Error
532
-     *
533
-     * @param string  $name
534
-     * @param boolean $require_construction_to_be_finalized most client code should
535
-     *                                                      leave this as TRUE so that the inputs will be properly
536
-     *                                                      configured. However, some client code may be ok with
537
-     *                                                      construction finalize being called later
538
-     *                                                      (realizing that the subsections' html names might not be
539
-     *                                                      set yet, etc.)
540
-     * @return EE_Form_Section_Proper
541
-     * @throws EE_Error
542
-     */
543
-    public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
-    {
545
-        $subsection = $this->get_subsection(
546
-            $name,
547
-            $require_construction_to_be_finalized
548
-        );
549
-        if (! $subsection instanceof EE_Form_Section_Proper) {
550
-            throw new EE_Error(
551
-                sprintf(
552
-                    esc_html__(
553
-                        "Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
-                        'event_espresso'
555
-                    ),
556
-                    $name,
557
-                    get_class($this)
558
-                )
559
-            );
560
-        }
561
-        return $subsection;
562
-    }
563
-
564
-
565
-    /**
566
-     * Gets the value of the specified input. Should be called after receive_form_submission()
567
-     * or populate_defaults() on the form, where the normalized value on the input is set.
568
-     *
569
-     * @param string $name
570
-     * @return mixed depending on the input's type and its normalization strategy
571
-     * @throws EE_Error
572
-     */
573
-    public function get_input_value($name)
574
-    {
575
-        $input = $this->get_input($name);
576
-        return $input->normalized_value();
577
-    }
578
-
579
-
580
-    /**
581
-     * Checks if this form section itself is valid, and then checks its subsections
582
-     *
583
-     * @throws EE_Error
584
-     * @return boolean
585
-     */
586
-    public function is_valid()
587
-    {
588
-        if($this->is_valid === null) {
589
-            if (! $this->has_received_submission()) {
590
-                throw new EE_Error(
591
-                    sprintf(
592
-                        esc_html__(
593
-                            'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
-                            'event_espresso'
595
-                        )
596
-                    )
597
-                );
598
-            }
599
-            if (! parent::is_valid()) {
600
-                $this->is_valid = false;
601
-            } else {
602
-                // ok so no general errors to this entire form section.
603
-                // so let's check the subsections, but only set errors if that hasn't been done yet
604
-                $this->is_valid = true;
605
-                foreach ($this->get_validatable_subsections() as $subsection) {
606
-                    if (! $subsection->is_valid()) {
607
-                        $this->is_valid = false;
608
-                    }
609
-                }
610
-            }
611
-        }
612
-        return $this->is_valid;
613
-    }
614
-
615
-
616
-    /**
617
-     * gets the default name of this form section if none is specified
618
-     *
619
-     * @return void
620
-     */
621
-    protected function _set_default_name_if_empty()
622
-    {
623
-        if (! $this->_name) {
624
-            $classname    = get_class($this);
625
-            $default_name = str_replace('EE_', '', $classname);
626
-            $this->_name  = $default_name;
627
-        }
628
-    }
629
-
630
-
631
-    /**
632
-     * Returns the HTML for the form, except for the form opening and closing tags
633
-     * (as the form section doesn't know where you necessarily want to send the information to),
634
-     * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
-     * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
-     * Not doing_it_wrong because theoretically this CAN be used properly,
637
-     * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
-     * any CSS.
639
-     *
640
-     * @throws InvalidArgumentException
641
-     * @throws InvalidInterfaceException
642
-     * @throws InvalidDataTypeException
643
-     * @throws EE_Error
644
-     */
645
-    public function get_html_and_js()
646
-    {
647
-        $this->enqueue_js();
648
-        return $this->get_html();
649
-    }
650
-
651
-
652
-    /**
653
-     * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
-     *
655
-     * @param bool $display_previously_submitted_data
656
-     * @return string
657
-     * @throws InvalidArgumentException
658
-     * @throws InvalidInterfaceException
659
-     * @throws InvalidDataTypeException
660
-     * @throws EE_Error
661
-     * @throws EE_Error
662
-     * @throws EE_Error
663
-     */
664
-    public function get_html($display_previously_submitted_data = true)
665
-    {
666
-        $this->ensure_construct_finalized_called();
667
-        if ($display_previously_submitted_data) {
668
-            $this->populate_from_session();
669
-        }
670
-        return $this->_form_html_filter
671
-            ? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
-            : $this->_layout_strategy->layout_form();
673
-    }
674
-
675
-
676
-    /**
677
-     * enqueues JS and CSS for the form.
678
-     * It is preferred to call this before wp_enqueue_scripts so the
679
-     * scripts and styles can be put in the header, but if called later
680
-     * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
-     * only be in the header; but in HTML5 its ok in the body.
682
-     * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
-     * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
-     *
685
-     * @return void
686
-     * @throws EE_Error
687
-     */
688
-    public function enqueue_js()
689
-    {
690
-        $this->_enqueue_and_localize_form_js();
691
-        foreach ($this->subsections() as $subsection) {
692
-            $subsection->enqueue_js();
693
-        }
694
-    }
695
-
696
-
697
-    /**
698
-     * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
-     * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
-     * the wp_enqueue_scripts hook.
701
-     * However, registering the form js and localizing it can happen when we
702
-     * actually output the form (which is preferred, seeing how teh form's fields
703
-     * could change until it's actually outputted)
704
-     *
705
-     * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
-     *                                                    to be triggered automatically or not
707
-     * @return void
708
-     */
709
-    public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
-    {
711
-        wp_register_script(
712
-            'ee_form_section_validation',
713
-            EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
714
-            array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
-            EVENT_ESPRESSO_VERSION,
716
-            true
717
-        );
718
-        wp_localize_script(
719
-            'ee_form_section_validation',
720
-            'ee_form_section_validation_init',
721
-            array('init' => $init_form_validation_automatically ? '1' : '0')
722
-        );
723
-    }
724
-
725
-
726
-    /**
727
-     * gets the variables used by form_section_validation.js.
728
-     * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
-     * but before the wordpress hook wp_loaded
730
-     *
731
-     * @throws EE_Error
732
-     */
733
-    public function _enqueue_and_localize_form_js()
734
-    {
735
-        $this->ensure_construct_finalized_called();
736
-        //actually, we don't want to localize just yet. There may be other forms on the page.
737
-        //so we need to add our form section data to a static variable accessible by all form sections
738
-        //and localize it just before the footer
739
-        $this->localize_validation_rules();
740
-        add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
-        add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
-    }
743
-
744
-
745
-    /**
746
-     * add our form section data to a static variable accessible by all form sections
747
-     *
748
-     * @param bool $return_for_subsection
749
-     * @return void
750
-     * @throws EE_Error
751
-     */
752
-    public function localize_validation_rules($return_for_subsection = false)
753
-    {
754
-        // we only want to localize vars ONCE for the entire form,
755
-        // so if the form section doesn't have a parent, then it must be the top dog
756
-        if ($return_for_subsection || ! $this->parent_section()) {
757
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
-                'form_section_id'  => $this->html_id(true),
759
-                'validation_rules' => $this->get_jquery_validation_rules(),
760
-                'other_data'       => $this->get_other_js_data(),
761
-                'errors'           => $this->subsection_validation_errors_by_html_name(),
762
-            );
763
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
764
-        }
765
-    }
766
-
767
-
768
-    /**
769
-     * Gets an array of extra data that will be useful for client-side javascript.
770
-     * This is primarily data added by inputs and forms in addition to any
771
-     * scripts they might enqueue
772
-     *
773
-     * @param array $form_other_js_data
774
-     * @return array
775
-     * @throws EE_Error
776
-     */
777
-    public function get_other_js_data($form_other_js_data = array())
778
-    {
779
-        foreach ($this->subsections() as $subsection) {
780
-            $form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
-        }
782
-        return $form_other_js_data;
783
-    }
784
-
785
-
786
-    /**
787
-     * Gets a flat array of inputs for this form section and its subsections.
788
-     * Keys are their form names, and values are the inputs themselves
789
-     *
790
-     * @return EE_Form_Input_Base
791
-     * @throws EE_Error
792
-     */
793
-    public function inputs_in_subsections()
794
-    {
795
-        $inputs = array();
796
-        foreach ($this->subsections() as $subsection) {
797
-            if ($subsection instanceof EE_Form_Input_Base) {
798
-                $inputs[ $subsection->html_name() ] = $subsection;
799
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
800
-                $inputs += $subsection->inputs_in_subsections();
801
-            }
802
-        }
803
-        return $inputs;
804
-    }
805
-
806
-
807
-    /**
808
-     * Gets a flat array of all the validation errors.
809
-     * Keys are html names (because those should be unique)
810
-     * and values are a string of all their validation errors
811
-     *
812
-     * @return string[]
813
-     * @throws EE_Error
814
-     */
815
-    public function subsection_validation_errors_by_html_name()
816
-    {
817
-        $inputs = $this->inputs();
818
-        $errors = array();
819
-        foreach ($inputs as $form_input) {
820
-            if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
-            }
823
-        }
824
-        return $errors;
825
-    }
826
-
827
-
828
-    /**
829
-     * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
-     * Should be setup by each form during the _enqueues_and_localize_form_js
831
-     *
832
-     * @throws InvalidArgumentException
833
-     * @throws InvalidInterfaceException
834
-     * @throws InvalidDataTypeException
835
-     */
836
-    public static function localize_script_for_all_forms()
837
-    {
838
-        //allow inputs and stuff to hook in their JS and stuff here
839
-        do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
-        EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
-        $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
-            ? EE_Registry::instance()->CFG->registration->email_validation_level
843
-            : 'wp_default';
844
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
-        wp_enqueue_script('ee_form_section_validation');
846
-        wp_localize_script(
847
-            'ee_form_section_validation',
848
-            'ee_form_section_vars',
849
-            EE_Form_Section_Proper::$_js_localization
850
-        );
851
-    }
852
-
853
-
854
-    /**
855
-     * ensure_scripts_localized
856
-     *
857
-     * @throws EE_Error
858
-     */
859
-    public function ensure_scripts_localized()
860
-    {
861
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
862
-            $this->_enqueue_and_localize_form_js();
863
-        }
864
-    }
865
-
866
-
867
-    /**
868
-     * Gets the hard-coded validation error messages to be used in the JS. The convention
869
-     * is that the key here should be the same as the custom validation rule put in the JS file
870
-     *
871
-     * @return array keys are custom validation rules, and values are internationalized strings
872
-     */
873
-    private static function _get_localized_error_messages()
874
-    {
875
-        return array(
876
-            'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
-            'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
-        );
879
-    }
880
-
881
-
882
-    /**
883
-     * @return array
884
-     */
885
-    public static function js_localization()
886
-    {
887
-        return self::$_js_localization;
888
-    }
889
-
890
-
891
-    /**
892
-     * @return void
893
-     */
894
-    public static function reset_js_localization()
895
-    {
896
-        self::$_js_localization = array();
897
-    }
898
-
899
-
900
-    /**
901
-     * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
-     * See parent function for more...
903
-     *
904
-     * @return array
905
-     * @throws EE_Error
906
-     */
907
-    public function get_jquery_validation_rules()
908
-    {
909
-        $jquery_validation_rules = array();
910
-        foreach ($this->get_validatable_subsections() as $subsection) {
911
-            $jquery_validation_rules = array_merge(
912
-                $jquery_validation_rules,
913
-                $subsection->get_jquery_validation_rules()
914
-            );
915
-        }
916
-        return $jquery_validation_rules;
917
-    }
918
-
919
-
920
-    /**
921
-     * Sanitizes all the data and sets the sanitized value of each field
922
-     *
923
-     * @param array $req_data like $_POST
924
-     * @return void
925
-     * @throws EE_Error
926
-     */
927
-    protected function _normalize($req_data)
928
-    {
929
-        $this->_received_submission = true;
930
-        $this->_validation_errors   = array();
931
-        foreach ($this->get_validatable_subsections() as $subsection) {
932
-            try {
933
-                $subsection->_normalize($req_data);
934
-            } catch (EE_Validation_Error $e) {
935
-                $subsection->add_validation_error($e);
936
-            }
937
-        }
938
-    }
939
-
940
-
941
-    /**
942
-     * Performs validation on this form section and its subsections.
943
-     * For each subsection,
944
-     * calls _validate_{subsection_name} on THIS form (if the function exists)
945
-     * and passes it the subsection, then calls _validate on that subsection.
946
-     * If you need to perform validation on the form as a whole (considering multiple)
947
-     * you would be best to override this _validate method,
948
-     * calling parent::_validate() first.
949
-     *
950
-     * @throws EE_Error
951
-     */
952
-    protected function _validate()
953
-    {
954
-        //reset the cache of whether this form is valid or not- we're re-validating it now
955
-        $this->is_valid = null;
956
-        foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
-            if (method_exists($this, '_validate_' . $subsection_name)) {
958
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
-            }
960
-            $subsection->_validate();
961
-        }
962
-    }
963
-
964
-
965
-    /**
966
-     * Gets all the validated inputs for the form section
967
-     *
968
-     * @return array
969
-     * @throws EE_Error
970
-     */
971
-    public function valid_data()
972
-    {
973
-        $inputs = array();
974
-        foreach ($this->subsections() as $subsection_name => $subsection) {
975
-            if ($subsection instanceof EE_Form_Section_Proper) {
976
-                $inputs[ $subsection_name ] = $subsection->valid_data();
977
-            } elseif ($subsection instanceof EE_Form_Input_Base) {
978
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
979
-            }
980
-        }
981
-        return $inputs;
982
-    }
983
-
984
-
985
-    /**
986
-     * Gets all the inputs on this form section
987
-     *
988
-     * @return EE_Form_Input_Base[]
989
-     * @throws EE_Error
990
-     */
991
-    public function inputs()
992
-    {
993
-        $inputs = array();
994
-        foreach ($this->subsections() as $subsection_name => $subsection) {
995
-            if ($subsection instanceof EE_Form_Input_Base) {
996
-                $inputs[ $subsection_name ] = $subsection;
997
-            }
998
-        }
999
-        return $inputs;
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     * Gets all the subsections which are a proper form
1005
-     *
1006
-     * @return EE_Form_Section_Proper[]
1007
-     * @throws EE_Error
1008
-     */
1009
-    public function subforms()
1010
-    {
1011
-        $form_sections = array();
1012
-        foreach ($this->subsections() as $name => $obj) {
1013
-            if ($obj instanceof EE_Form_Section_Proper) {
1014
-                $form_sections[ $name ] = $obj;
1015
-            }
1016
-        }
1017
-        return $form_sections;
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
-     * Consider using inputs() or subforms()
1024
-     * if you only want form inputs or proper form sections.
1025
-     *
1026
-     * @param boolean $require_construction_to_be_finalized most client code should
1027
-     *                                                      leave this as TRUE so that the inputs will be properly
1028
-     *                                                      configured. However, some client code may be ok with
1029
-     *                                                      construction finalize being called later
1030
-     *                                                      (realizing that the subsections' html names might not be
1031
-     *                                                      set yet, etc.)
1032
-     * @return EE_Form_Section_Proper[]
1033
-     * @throws EE_Error
1034
-     */
1035
-    public function subsections($require_construction_to_be_finalized = true)
1036
-    {
1037
-        if ($require_construction_to_be_finalized) {
1038
-            $this->ensure_construct_finalized_called();
1039
-        }
1040
-        return $this->_subsections;
1041
-    }
1042
-
1043
-
1044
-    /**
1045
-     * Returns whether this form has any subforms or inputs
1046
-     * @return bool
1047
-     */
1048
-    public function hasSubsections()
1049
-    {
1050
-        return ! empty($this->_subsections);
1051
-    }
1052
-
1053
-
1054
-    /**
1055
-     * Returns a simple array where keys are input names, and values are their normalized
1056
-     * values. (Similar to calling get_input_value on inputs)
1057
-     *
1058
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
-     *                                        or just this forms' direct children inputs
1060
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
-     *                                        or allow multidimensional array
1062
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
-     *                                        with array keys being input names
1064
-     *                                        (regardless of whether they are from a subsection or not),
1065
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1066
-     *                                        where keys are always subsection names and values are either
1067
-     *                                        the input's normalized value, or an array like the top-level array
1068
-     * @throws EE_Error
1069
-     */
1070
-    public function input_values($include_subform_inputs = false, $flatten = false)
1071
-    {
1072
-        return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
-     * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
-     * is not necessarily the value we want to display to users. This creates an array
1080
-     * where keys are the input names, and values are their display values
1081
-     *
1082
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
-     *                                        or just this forms' direct children inputs
1084
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
-     *                                        or allow multidimensional array
1086
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
-     *                                        with array keys being input names
1088
-     *                                        (regardless of whether they are from a subsection or not),
1089
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1090
-     *                                        where keys are always subsection names and values are either
1091
-     *                                        the input's normalized value, or an array like the top-level array
1092
-     * @throws EE_Error
1093
-     */
1094
-    public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
-    {
1096
-        return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
-    }
1098
-
1099
-
1100
-    /**
1101
-     * Gets the input values from the form
1102
-     *
1103
-     * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
-     *                                        or just the normalized value
1105
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
-     *                                        or just this forms' direct children inputs
1107
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
-     *                                        or allow multidimensional array
1109
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
-     *                                        input names (regardless of whether they are from a subsection or not),
1111
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1112
-     *                                        where keys are always subsection names and values are either
1113
-     *                                        the input's normalized value, or an array like the top-level array
1114
-     * @throws EE_Error
1115
-     */
1116
-    public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
-    {
1118
-        $input_values = array();
1119
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1120
-            if ($subsection instanceof EE_Form_Input_Base) {
1121
-                $input_values[ $subsection_name ] = $pretty
1122
-                    ? $subsection->pretty_value()
1123
-                    : $subsection->normalized_value();
1124
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
-                $subform_input_values = $subsection->_input_values(
1126
-                    $pretty,
1127
-                    $include_subform_inputs,
1128
-                    $flatten
1129
-                );
1130
-                if ($flatten) {
1131
-                    $input_values = array_merge($input_values, $subform_input_values);
1132
-                } else {
1133
-                    $input_values[ $subsection_name ] = $subform_input_values;
1134
-                }
1135
-            }
1136
-        }
1137
-        return $input_values;
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * Gets the originally submitted input values from the form
1143
-     *
1144
-     * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
-     *                                   or just this forms' direct children inputs
1146
-     * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
-     *                                   with array keys being input names
1148
-     *                                   (regardless of whether they are from a subsection or not),
1149
-     *                                   and if $flatten is FALSE it can be a multidimensional array
1150
-     *                                   where keys are always subsection names and values are either
1151
-     *                                   the input's normalized value, or an array like the top-level array
1152
-     * @throws EE_Error
1153
-     */
1154
-    public function submitted_values($include_subforms = false)
1155
-    {
1156
-        $submitted_values = array();
1157
-        foreach ($this->subsections() as $subsection) {
1158
-            if ($subsection instanceof EE_Form_Input_Base) {
1159
-                // is this input part of an array of inputs?
1160
-                if (strpos($subsection->html_name(), '[') !== false) {
1161
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
-                        explode(
1163
-                            '[',
1164
-                            str_replace(']', '', $subsection->html_name())
1165
-                        ),
1166
-                        $subsection->raw_value()
1167
-                    );
1168
-                    $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
-                } else {
1170
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
-                }
1172
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
-                $subform_input_values = $subsection->submitted_values($include_subforms);
1174
-                $submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
-            }
1176
-        }
1177
-        return $submitted_values;
1178
-    }
1179
-
1180
-
1181
-    /**
1182
-     * Indicates whether or not this form has received a submission yet
1183
-     * (ie, had receive_form_submission called on it yet)
1184
-     *
1185
-     * @return boolean
1186
-     * @throws EE_Error
1187
-     */
1188
-    public function has_received_submission()
1189
-    {
1190
-        $this->ensure_construct_finalized_called();
1191
-        return $this->_received_submission;
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * Equivalent to passing 'exclude' in the constructor's options array.
1197
-     * Removes the listed inputs from the form
1198
-     *
1199
-     * @param array $inputs_to_exclude values are the input names
1200
-     * @return void
1201
-     */
1202
-    public function exclude(array $inputs_to_exclude = array())
1203
-    {
1204
-        foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
-            unset($this->_subsections[ $input_to_exclude_name ]);
1206
-        }
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1212
-     * @param array $inputs_to_hide
1213
-     * @throws EE_Error
1214
-     */
1215
-    public function hide(array $inputs_to_hide = array())
1216
-    {
1217
-        foreach ($inputs_to_hide as $input_to_hide) {
1218
-            $input = $this->get_input($input_to_hide);
1219
-            $input->set_display_strategy(new EE_Hidden_Display_Strategy());
1220
-        }
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * add_subsections
1226
-     * Adds the listed subsections to the form section.
1227
-     * If $subsection_name_to_target is provided,
1228
-     * then new subsections are added before or after that subsection,
1229
-     * otherwise to the start or end of the entire subsections array.
1230
-     *
1231
-     * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1232
-     *                                                          where keys are their names
1233
-     * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1234
-     *                                                          should be added before or after
1235
-     *                                                          IF $subsection_name_to_target is null,
1236
-     *                                                          then $new_subsections will be added to
1237
-     *                                                          the beginning or end of the entire subsections array
1238
-     * @param boolean                $add_before                whether to add $new_subsections, before or after
1239
-     *                                                          $subsection_name_to_target,
1240
-     *                                                          or if $subsection_name_to_target is null,
1241
-     *                                                          before or after entire subsections array
1242
-     * @return void
1243
-     * @throws EE_Error
1244
-     */
1245
-    public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1246
-    {
1247
-        foreach ($new_subsections as $subsection_name => $subsection) {
1248
-            if (! $subsection instanceof EE_Form_Section_Base) {
1249
-                EE_Error::add_error(
1250
-                    sprintf(
1251
-                        esc_html__(
1252
-                            "Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1253
-                            'event_espresso'
1254
-                        ),
1255
-                        get_class($subsection),
1256
-                        $subsection_name,
1257
-                        $this->name()
1258
-                    )
1259
-                );
1260
-                unset($new_subsections[ $subsection_name ]);
1261
-            }
1262
-        }
1263
-        $this->_subsections = EEH_Array::insert_into_array(
1264
-            $this->_subsections,
1265
-            $new_subsections,
1266
-            $subsection_name_to_target,
1267
-            $add_before
1268
-        );
1269
-        if ($this->_construction_finalized) {
1270
-            foreach ($this->_subsections as $name => $subsection) {
1271
-                $subsection->_construct_finalize($this, $name);
1272
-            }
1273
-        }
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     * Just gets all validatable subsections to clean their sensitive data
1279
-     *
1280
-     * @throws EE_Error
1281
-     */
1282
-    public function clean_sensitive_data()
1283
-    {
1284
-        foreach ($this->get_validatable_subsections() as $subsection) {
1285
-            $subsection->clean_sensitive_data();
1286
-        }
1287
-    }
1288
-
1289
-
1290
-    /**
1291
-     * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1292
-     * @param string                           $form_submission_error_message
1293
-     * @param EE_Form_Section_Validatable $form_section unused
1294
-     * @throws EE_Error
1295
-     */
1296
-    public function set_submission_error_message(
1297
-        $form_submission_error_message = ''
1298
-    ) {
1299
-        $this->_form_submission_error_message = ! empty($form_submission_error_message)
1300
-            ? $form_submission_error_message
1301
-            : $this->getAllValidationErrorsString();
1302
-    }
1303
-
1304
-
1305
-    /**
1306
-     * Returns the cached error message. A default value is set for this during _validate(),
1307
-     * (called during receive_form_submission) but it can be explicitly set using
1308
-     * set_submission_error_message
1309
-     *
1310
-     * @return string
1311
-     */
1312
-    public function submission_error_message()
1313
-    {
1314
-        return $this->_form_submission_error_message;
1315
-    }
1316
-
1317
-
1318
-    /**
1319
-     * Sets a message to display if the data submitted to the form was valid.
1320
-     * @param string $form_submission_success_message
1321
-     */
1322
-    public function set_submission_success_message($form_submission_success_message = '')
1323
-    {
1324
-        $this->_form_submission_success_message = ! empty($form_submission_success_message)
1325
-            ? $form_submission_success_message
1326
-            : esc_html__('Form submitted successfully', 'event_espresso');
1327
-    }
1328
-
1329
-
1330
-    /**
1331
-     * Gets a message appropriate for display when the form is correctly submitted
1332
-     * @return string
1333
-     */
1334
-    public function submission_success_message()
1335
-    {
1336
-        return $this->_form_submission_success_message;
1337
-    }
1338
-
1339
-
1340
-    /**
1341
-     * Returns the prefix that should be used on child of this form section for
1342
-     * their html names. If this form section itself has a parent, prepends ITS
1343
-     * prefix onto this form section's prefix. Used primarily by
1344
-     * EE_Form_Input_Base::_set_default_html_name_if_empty
1345
-     *
1346
-     * @return string
1347
-     * @throws EE_Error
1348
-     */
1349
-    public function html_name_prefix()
1350
-    {
1351
-        if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1352
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1353
-        }
1354
-        return $this->name();
1355
-    }
1356
-
1357
-
1358
-    /**
1359
-     * Gets the name, but first checks _construct_finalize has been called. If not,
1360
-     * calls it (assumes there is no parent and that we want the name to be whatever
1361
-     * was set, which is probably nothing, or the classname)
1362
-     *
1363
-     * @return string
1364
-     * @throws EE_Error
1365
-     */
1366
-    public function name()
1367
-    {
1368
-        $this->ensure_construct_finalized_called();
1369
-        return parent::name();
1370
-    }
1371
-
1372
-
1373
-    /**
1374
-     * @return EE_Form_Section_Proper
1375
-     * @throws EE_Error
1376
-     */
1377
-    public function parent_section()
1378
-    {
1379
-        $this->ensure_construct_finalized_called();
1380
-        return parent::parent_section();
1381
-    }
1382
-
1383
-
1384
-    /**
1385
-     * make sure construction finalized was called, otherwise children might not be ready
1386
-     *
1387
-     * @return void
1388
-     * @throws EE_Error
1389
-     */
1390
-    public function ensure_construct_finalized_called()
1391
-    {
1392
-        if (! $this->_construction_finalized) {
1393
-            $this->_construct_finalize($this->_parent_section, $this->_name);
1394
-        }
1395
-    }
1396
-
1397
-
1398
-    /**
1399
-     * Checks if any of this form section's inputs, or any of its children's inputs,
1400
-     * are in teh form data. If any are found, returns true. Else false
1401
-     *
1402
-     * @param array $req_data
1403
-     * @return boolean
1404
-     * @throws EE_Error
1405
-     */
1406
-    public function form_data_present_in($req_data = null)
1407
-    {
1408
-        $req_data = $this->getCachedRequest($req_data);
1409
-        foreach ($this->subsections() as $subsection) {
1410
-            if ($subsection instanceof EE_Form_Input_Base) {
1411
-                if ($subsection->form_data_present_in($req_data)) {
1412
-                    return true;
1413
-                }
1414
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
1415
-                if ($subsection->form_data_present_in($req_data)) {
1416
-                    return true;
1417
-                }
1418
-            }
1419
-        }
1420
-        return false;
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * Gets validation errors for this form section and subsections
1426
-     * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1427
-     * gets the validation errors for ALL subsection
1428
-     *
1429
-     * @return EE_Validation_Error[]
1430
-     * @throws EE_Error
1431
-     */
1432
-    public function get_validation_errors_accumulated()
1433
-    {
1434
-        $validation_errors = $this->get_validation_errors();
1435
-        foreach ($this->get_validatable_subsections() as $subsection) {
1436
-            if ($subsection instanceof EE_Form_Section_Proper) {
1437
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1438
-            } else {
1439
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors();
1440
-            }
1441
-            if ($validation_errors_on_this_subsection) {
1442
-                $validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1443
-            }
1444
-        }
1445
-        return $validation_errors;
1446
-    }
1447
-
1448
-    /**
1449
-     * Fetch validation errors from children and grandchildren and puts them in a single string.
1450
-     * This traverses the form section tree to generate this, but you probably want to instead use
1451
-     * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1452
-     *
1453
-     * @return string
1454
-     * @since $VID:$
1455
-     */
1456
-    protected function getAllValidationErrorsString()
1457
-    {
1458
-        $submission_error_messages = array();
1459
-        // bad, bad, bad registrant
1460
-        foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1461
-            if ($validation_error instanceof EE_Validation_Error) {
1462
-                $form_section = $validation_error->get_form_section();
1463
-                if ($form_section instanceof EE_Form_Input_Base) {
1464
-                   $label = $validation_error->get_form_section()->html_label_text();
1465
-                } elseif($form_section instanceof EE_Form_Section_Validatable) {
1466
-                    $label = $validation_error->get_form_section()->name();
1467
-                } else {
1468
-                    $label = esc_html__('Unknown', 'event_espresso');
1469
-                }
1470
-                $submission_error_messages[] = sprintf(
1471
-                    __('%s : %s', 'event_espresso'),
1472
-                    $label,
1473
-                    $validation_error->getMessage()
1474
-                );
1475
-            }
1476
-        }
1477
-        return implode('<br', $submission_error_messages);
1478
-    }
1479
-
1480
-
1481
-    /**
1482
-     * This isn't just the name of an input, it's a path pointing to an input. The
1483
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
1484
-     * dot-dot-slash (../) means to ascend into the parent section.
1485
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1486
-     * which will be returned.
1487
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1488
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1489
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1490
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1491
-     * Etc
1492
-     *
1493
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1494
-     * @return EE_Form_Section_Base
1495
-     * @throws EE_Error
1496
-     */
1497
-    public function find_section_from_path($form_section_path)
1498
-    {
1499
-        //check if we can find the input from purely going straight up the tree
1500
-        $input = parent::find_section_from_path($form_section_path);
1501
-        if ($input instanceof EE_Form_Section_Base) {
1502
-            return $input;
1503
-        }
1504
-        $next_slash_pos = strpos($form_section_path, '/');
1505
-        if ($next_slash_pos !== false) {
1506
-            $child_section_name = substr($form_section_path, 0, $next_slash_pos);
1507
-            $subpath            = substr($form_section_path, $next_slash_pos + 1);
1508
-        } else {
1509
-            $child_section_name = $form_section_path;
1510
-            $subpath            = '';
1511
-        }
1512
-        $child_section = $this->get_subsection($child_section_name);
1513
-        if ($child_section instanceof EE_Form_Section_Base) {
1514
-            return $child_section->find_section_from_path($subpath);
1515
-        }
1516
-        return null;
1517
-    }
17
+	const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
+
19
+	/**
20
+	 * Subsections
21
+	 *
22
+	 * @var EE_Form_Section_Validatable[]
23
+	 */
24
+	protected $_subsections = array();
25
+
26
+	/**
27
+	 * Strategy for laying out the form
28
+	 *
29
+	 * @var EE_Form_Section_Layout_Base
30
+	 */
31
+	protected $_layout_strategy;
32
+
33
+	/**
34
+	 * Whether or not this form has received and validated a form submission yet
35
+	 *
36
+	 * @var boolean
37
+	 */
38
+	protected $_received_submission = false;
39
+
40
+	/**
41
+	 * message displayed to users upon successful form submission
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $_form_submission_success_message = '';
46
+
47
+	/**
48
+	 * message displayed to users upon unsuccessful form submission
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $_form_submission_error_message = '';
53
+
54
+	/**
55
+	 * @var array like $_REQUEST
56
+	 */
57
+	protected $cached_request_data;
58
+
59
+	/**
60
+	 * Stores whether this form (and its sub-sections) were found to be valid or not.
61
+	 * Starts off as null, but once the form is validated, it set to either true or false
62
+	 * @var boolean|null
63
+	 */
64
+	protected $is_valid;
65
+
66
+	/**
67
+	 * Stores all the data that will localized for form validation
68
+	 *
69
+	 * @var array
70
+	 */
71
+	static protected $_js_localization = array();
72
+
73
+	/**
74
+	 * whether or not the form's localized validation JS vars have been set
75
+	 *
76
+	 * @type boolean
77
+	 */
78
+	static protected $_scripts_localized = false;
79
+
80
+
81
+	/**
82
+	 * when constructing a proper form section, calls _construct_finalize on children
83
+	 * so that they know who their parent is, and what name they've been given.
84
+	 *
85
+	 * @param array[] $options_array   {
86
+	 * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
+	 * @type          $include         string[] numerically-indexed where values are section names to be included,
88
+	 *                                 and in that order. This is handy if you want
89
+	 *                                 the subsections to be ordered differently than the default, and if you override
90
+	 *                                 which fields are shown
91
+	 * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
+	 *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
+	 *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
+	 *                                 items from that list of inclusions)
95
+	 * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
+	 *                                 } @see EE_Form_Section_Validatable::__construct()
97
+	 * @throws EE_Error
98
+	 */
99
+	public function __construct($options_array = array())
100
+	{
101
+		$options_array = (array) apply_filters(
102
+			'FHEE__EE_Form_Section_Proper___construct__options_array',
103
+			$options_array,
104
+			$this
105
+		);
106
+		//call parent first, as it may be setting the name
107
+		parent::__construct($options_array);
108
+		//if they've included subsections in the constructor, add them now
109
+		if (isset($options_array['include'])) {
110
+			//we are going to make sure we ONLY have those subsections to include
111
+			//AND we are going to make sure they're in that specified order
112
+			$reordered_subsections = array();
113
+			foreach ($options_array['include'] as $input_name) {
114
+				if (isset($this->_subsections[ $input_name ])) {
115
+					$reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
+				}
117
+			}
118
+			$this->_subsections = $reordered_subsections;
119
+		}
120
+		if (isset($options_array['exclude'])) {
121
+			$exclude            = $options_array['exclude'];
122
+			$this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
+		}
124
+		if (isset($options_array['layout_strategy'])) {
125
+			$this->_layout_strategy = $options_array['layout_strategy'];
126
+		}
127
+		if (! $this->_layout_strategy) {
128
+			$this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
+		}
130
+		$this->_layout_strategy->_construct_finalize($this);
131
+		//ok so we are definitely going to want the forms JS,
132
+		//so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
+			//ok so they've constructed this object after when they should have.
135
+			//just enqueue the generic form scripts and initialize the form immediately in the JS
136
+			EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
+		} else {
138
+			add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
+			add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
+		}
141
+		add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
+		/**
143
+		 * Gives other plugins a chance to hook in before construct finalize is called.
144
+		 * The form probably doesn't yet have a parent form section.
145
+		 * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
+		 * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
+		 * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
+		 *
149
+		 * @since 4.9.32
150
+		 * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
+		 *                                              except maybe calling _construct_finalize has been done
152
+		 * @param array                  $options_array options passed into the constructor
153
+		 */
154
+		do_action(
155
+			'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
+			$this,
157
+			$options_array
158
+		);
159
+		if (isset($options_array['name'])) {
160
+			$this->_construct_finalize(null, $options_array['name']);
161
+		}
162
+	}
163
+
164
+
165
+	/**
166
+	 * Finishes construction given the parent form section and this form section's name
167
+	 *
168
+	 * @param EE_Form_Section_Proper $parent_form_section
169
+	 * @param string                 $name
170
+	 * @throws EE_Error
171
+	 */
172
+	public function _construct_finalize($parent_form_section, $name)
173
+	{
174
+		parent::_construct_finalize($parent_form_section, $name);
175
+		$this->_set_default_name_if_empty();
176
+		$this->_set_default_html_id_if_empty();
177
+		foreach ($this->_subsections as $subsection_name => $subsection) {
178
+			if ($subsection instanceof EE_Form_Section_Base) {
179
+				$subsection->_construct_finalize($this, $subsection_name);
180
+			} else {
181
+				throw new EE_Error(
182
+					sprintf(
183
+						esc_html__(
184
+							'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
+							'event_espresso'
186
+						),
187
+						$subsection_name,
188
+						get_class($this),
189
+						$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
+					)
191
+				);
192
+			}
193
+		}
194
+		/**
195
+		 * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
+		 * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
+		 * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
+		 * This might only happen just before displaying the form, or just before it receives form submission data.
199
+		 * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
+		 * ensured it has a name, HTML IDs, etc
201
+		 *
202
+		 * @param EE_Form_Section_Proper      $this
203
+		 * @param EE_Form_Section_Proper|null $parent_form_section
204
+		 * @param string                      $name
205
+		 */
206
+		do_action(
207
+			'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
+			$this,
209
+			$parent_form_section,
210
+			$name
211
+		);
212
+	}
213
+
214
+
215
+	/**
216
+	 * Gets the layout strategy for this form section
217
+	 *
218
+	 * @return EE_Form_Section_Layout_Base
219
+	 */
220
+	public function get_layout_strategy()
221
+	{
222
+		return $this->_layout_strategy;
223
+	}
224
+
225
+
226
+	/**
227
+	 * Gets the HTML for a single input for this form section according
228
+	 * to the layout strategy
229
+	 *
230
+	 * @param EE_Form_Input_Base $input
231
+	 * @return string
232
+	 */
233
+	public function get_html_for_input($input)
234
+	{
235
+		return $this->_layout_strategy->layout_input($input);
236
+	}
237
+
238
+
239
+	/**
240
+	 * was_submitted - checks if form inputs are present in request data
241
+	 * Basically an alias for form_data_present_in() (which is used by both
242
+	 * proper form sections and form inputs)
243
+	 *
244
+	 * @param null $form_data
245
+	 * @return boolean
246
+	 * @throws EE_Error
247
+	 */
248
+	public function was_submitted($form_data = null)
249
+	{
250
+		return $this->form_data_present_in($form_data);
251
+	}
252
+
253
+	/**
254
+	 * Gets the cached request data; but if there is none, or $req_data was set with
255
+	 * something different, refresh the cache, and then return it
256
+	 * @param null $req_data
257
+	 * @return array
258
+	 */
259
+	protected function getCachedRequest($req_data = null)
260
+	{
261
+		if ($this->cached_request_data === null
262
+			|| (
263
+				$req_data !== null &&
264
+				$req_data !== $this->cached_request_data
265
+			)
266
+		) {
267
+			$req_data = apply_filters(
268
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
+				$req_data,
270
+				$this
271
+			);
272
+			if ($req_data === null) {
273
+				$req_data = array_merge($_GET, $_POST);
274
+			}
275
+			$req_data = apply_filters(
276
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
+				$req_data,
278
+				$this
279
+			);
280
+			$this->cached_request_data = (array)$req_data;
281
+		}
282
+		return $this->cached_request_data;
283
+	}
284
+
285
+
286
+	/**
287
+	 * After the form section is initially created, call this to sanitize the data in the submission
288
+	 * which relates to this form section, validate it, and set it as properties on the form.
289
+	 *
290
+	 * @param array|null $req_data should usually be $_POST (the default).
291
+	 *                             However, you CAN supply a different array.
292
+	 *                             Consider using set_defaults() instead however.
293
+	 *                             (If you rendered the form in the page using echo $form_x->get_html()
294
+	 *                             the inputs will have the correct name in the request data for this function
295
+	 *                             to find them and populate the form with them.
296
+	 *                             If you have a flat form (with only input subsections),
297
+	 *                             you can supply a flat array where keys
298
+	 *                             are the form input names and values are their values)
299
+	 * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
+	 *                             of course, to validate that data, and set errors on the invalid values.
301
+	 *                             But if the data has already been validated
302
+	 *                             (eg you validated the data then stored it in the DB)
303
+	 *                             you may want to skip this step.
304
+	 * @throws InvalidArgumentException
305
+	 * @throws InvalidInterfaceException
306
+	 * @throws InvalidDataTypeException
307
+	 * @throws EE_Error
308
+	 */
309
+	public function receive_form_submission($req_data = null, $validate = true)
310
+	{
311
+		$req_data = $this->getCachedRequest($req_data);
312
+		$this->_normalize($req_data);
313
+		if ($validate) {
314
+			$this->_validate();
315
+			//if it's invalid, we're going to want to re-display so remember what they submitted
316
+			if (! $this->is_valid()) {
317
+				$this->store_submitted_form_data_in_session();
318
+			}
319
+		}
320
+		if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
+			$this->set_submission_error_message();
322
+		}
323
+		do_action(
324
+			'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
+			$req_data,
326
+			$this,
327
+			$validate
328
+		);
329
+	}
330
+
331
+
332
+	/**
333
+	 * caches the originally submitted input values in the session
334
+	 * so that they can be used to repopulate the form if it failed validation
335
+	 *
336
+	 * @return boolean whether or not the data was successfully stored in the session
337
+	 * @throws InvalidArgumentException
338
+	 * @throws InvalidInterfaceException
339
+	 * @throws InvalidDataTypeException
340
+	 * @throws EE_Error
341
+	 */
342
+	protected function store_submitted_form_data_in_session()
343
+	{
344
+		return EE_Registry::instance()->SSN->set_session_data(
345
+			array(
346
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
+			)
348
+		);
349
+	}
350
+
351
+
352
+	/**
353
+	 * retrieves the originally submitted input values in the session
354
+	 * so that they can be used to repopulate the form if it failed validation
355
+	 *
356
+	 * @return array
357
+	 * @throws InvalidArgumentException
358
+	 * @throws InvalidInterfaceException
359
+	 * @throws InvalidDataTypeException
360
+	 */
361
+	protected function get_submitted_form_data_from_session()
362
+	{
363
+		$session = EE_Registry::instance()->SSN;
364
+		if ($session instanceof EE_Session) {
365
+			return $session->get_session_data(
366
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
+			);
368
+		}
369
+		return array();
370
+	}
371
+
372
+
373
+	/**
374
+	 * flushed the originally submitted input values from the session
375
+	 *
376
+	 * @return boolean whether or not the data was successfully removed from the session
377
+	 * @throws InvalidArgumentException
378
+	 * @throws InvalidInterfaceException
379
+	 * @throws InvalidDataTypeException
380
+	 */
381
+	protected function flush_submitted_form_data_from_session()
382
+	{
383
+		return EE_Registry::instance()->SSN->reset_data(
384
+			array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
+		);
386
+	}
387
+
388
+
389
+	/**
390
+	 * Populates this form and its subsections with data from the session.
391
+	 * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
+	 * validation errors when displaying too)
393
+	 * Returns true if the form was populated from the session, false otherwise
394
+	 *
395
+	 * @return boolean
396
+	 * @throws InvalidArgumentException
397
+	 * @throws InvalidInterfaceException
398
+	 * @throws InvalidDataTypeException
399
+	 * @throws EE_Error
400
+	 */
401
+	public function populate_from_session()
402
+	{
403
+		$form_data_in_session = $this->get_submitted_form_data_from_session();
404
+		if (empty($form_data_in_session)) {
405
+			return false;
406
+		}
407
+		$this->receive_form_submission($form_data_in_session);
408
+		$this->flush_submitted_form_data_from_session();
409
+		if ($this->form_data_present_in($form_data_in_session)) {
410
+			return true;
411
+		}
412
+		return false;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Populates the default data for the form, given an array where keys are
418
+	 * the input names, and values are their values (preferably normalized to be their
419
+	 * proper PHP types, not all strings... although that should be ok too).
420
+	 * Proper subsections are sub-arrays, the key being the subsection's name, and
421
+	 * the value being an array formatted in teh same way
422
+	 *
423
+	 * @param array $default_data
424
+	 * @throws EE_Error
425
+	 */
426
+	public function populate_defaults($default_data)
427
+	{
428
+		foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
+			if (isset($default_data[ $subsection_name ])) {
430
+				if ($subsection instanceof EE_Form_Input_Base) {
431
+					$subsection->set_default($default_data[ $subsection_name ]);
432
+				} elseif ($subsection instanceof EE_Form_Section_Proper) {
433
+					$subsection->populate_defaults($default_data[ $subsection_name ]);
434
+				}
435
+			}
436
+		}
437
+	}
438
+
439
+
440
+	/**
441
+	 * returns true if subsection exists
442
+	 *
443
+	 * @param string $name
444
+	 * @return boolean
445
+	 */
446
+	public function subsection_exists($name)
447
+	{
448
+		return isset($this->_subsections[ $name ]) ? true : false;
449
+	}
450
+
451
+
452
+	/**
453
+	 * Gets the subsection specified by its name
454
+	 *
455
+	 * @param string  $name
456
+	 * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
+	 *                                                      so that the inputs will be properly configured.
458
+	 *                                                      However, some client code may be ok
459
+	 *                                                      with construction finalize being called later
460
+	 *                                                      (realizing that the subsections' html names
461
+	 *                                                      might not be set yet, etc.)
462
+	 * @return EE_Form_Section_Base
463
+	 * @throws EE_Error
464
+	 */
465
+	public function get_subsection($name, $require_construction_to_be_finalized = true)
466
+	{
467
+		if ($require_construction_to_be_finalized) {
468
+			$this->ensure_construct_finalized_called();
469
+		}
470
+		return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
+	}
472
+
473
+
474
+	/**
475
+	 * Gets all the validatable subsections of this form section
476
+	 *
477
+	 * @return EE_Form_Section_Validatable[]
478
+	 * @throws EE_Error
479
+	 */
480
+	public function get_validatable_subsections()
481
+	{
482
+		$validatable_subsections = array();
483
+		foreach ($this->subsections() as $name => $obj) {
484
+			if ($obj instanceof EE_Form_Section_Validatable) {
485
+				$validatable_subsections[ $name ] = $obj;
486
+			}
487
+		}
488
+		return $validatable_subsections;
489
+	}
490
+
491
+
492
+	/**
493
+	 * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
+	 * throw an EE_Error.
495
+	 *
496
+	 * @param string  $name
497
+	 * @param boolean $require_construction_to_be_finalized most client code should
498
+	 *                                                      leave this as TRUE so that the inputs will be properly
499
+	 *                                                      configured. However, some client code may be ok with
500
+	 *                                                      construction finalize being called later
501
+	 *                                                      (realizing that the subsections' html names might not be
502
+	 *                                                      set yet, etc.)
503
+	 * @return EE_Form_Input_Base
504
+	 * @throws EE_Error
505
+	 */
506
+	public function get_input($name, $require_construction_to_be_finalized = true)
507
+	{
508
+		$subsection = $this->get_subsection(
509
+			$name,
510
+			$require_construction_to_be_finalized
511
+		);
512
+		if (! $subsection instanceof EE_Form_Input_Base) {
513
+			throw new EE_Error(
514
+				sprintf(
515
+					esc_html__(
516
+						"Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
+						'event_espresso'
518
+					),
519
+					$name,
520
+					get_class($this),
521
+					$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
+				)
523
+			);
524
+		}
525
+		return $subsection;
526
+	}
527
+
528
+
529
+	/**
530
+	 * Like get_input(), gets the proper subsection of the form given the name,
531
+	 * otherwise throws an EE_Error
532
+	 *
533
+	 * @param string  $name
534
+	 * @param boolean $require_construction_to_be_finalized most client code should
535
+	 *                                                      leave this as TRUE so that the inputs will be properly
536
+	 *                                                      configured. However, some client code may be ok with
537
+	 *                                                      construction finalize being called later
538
+	 *                                                      (realizing that the subsections' html names might not be
539
+	 *                                                      set yet, etc.)
540
+	 * @return EE_Form_Section_Proper
541
+	 * @throws EE_Error
542
+	 */
543
+	public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
+	{
545
+		$subsection = $this->get_subsection(
546
+			$name,
547
+			$require_construction_to_be_finalized
548
+		);
549
+		if (! $subsection instanceof EE_Form_Section_Proper) {
550
+			throw new EE_Error(
551
+				sprintf(
552
+					esc_html__(
553
+						"Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
+						'event_espresso'
555
+					),
556
+					$name,
557
+					get_class($this)
558
+				)
559
+			);
560
+		}
561
+		return $subsection;
562
+	}
563
+
564
+
565
+	/**
566
+	 * Gets the value of the specified input. Should be called after receive_form_submission()
567
+	 * or populate_defaults() on the form, where the normalized value on the input is set.
568
+	 *
569
+	 * @param string $name
570
+	 * @return mixed depending on the input's type and its normalization strategy
571
+	 * @throws EE_Error
572
+	 */
573
+	public function get_input_value($name)
574
+	{
575
+		$input = $this->get_input($name);
576
+		return $input->normalized_value();
577
+	}
578
+
579
+
580
+	/**
581
+	 * Checks if this form section itself is valid, and then checks its subsections
582
+	 *
583
+	 * @throws EE_Error
584
+	 * @return boolean
585
+	 */
586
+	public function is_valid()
587
+	{
588
+		if($this->is_valid === null) {
589
+			if (! $this->has_received_submission()) {
590
+				throw new EE_Error(
591
+					sprintf(
592
+						esc_html__(
593
+							'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
+							'event_espresso'
595
+						)
596
+					)
597
+				);
598
+			}
599
+			if (! parent::is_valid()) {
600
+				$this->is_valid = false;
601
+			} else {
602
+				// ok so no general errors to this entire form section.
603
+				// so let's check the subsections, but only set errors if that hasn't been done yet
604
+				$this->is_valid = true;
605
+				foreach ($this->get_validatable_subsections() as $subsection) {
606
+					if (! $subsection->is_valid()) {
607
+						$this->is_valid = false;
608
+					}
609
+				}
610
+			}
611
+		}
612
+		return $this->is_valid;
613
+	}
614
+
615
+
616
+	/**
617
+	 * gets the default name of this form section if none is specified
618
+	 *
619
+	 * @return void
620
+	 */
621
+	protected function _set_default_name_if_empty()
622
+	{
623
+		if (! $this->_name) {
624
+			$classname    = get_class($this);
625
+			$default_name = str_replace('EE_', '', $classname);
626
+			$this->_name  = $default_name;
627
+		}
628
+	}
629
+
630
+
631
+	/**
632
+	 * Returns the HTML for the form, except for the form opening and closing tags
633
+	 * (as the form section doesn't know where you necessarily want to send the information to),
634
+	 * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
+	 * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
+	 * Not doing_it_wrong because theoretically this CAN be used properly,
637
+	 * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
+	 * any CSS.
639
+	 *
640
+	 * @throws InvalidArgumentException
641
+	 * @throws InvalidInterfaceException
642
+	 * @throws InvalidDataTypeException
643
+	 * @throws EE_Error
644
+	 */
645
+	public function get_html_and_js()
646
+	{
647
+		$this->enqueue_js();
648
+		return $this->get_html();
649
+	}
650
+
651
+
652
+	/**
653
+	 * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
+	 *
655
+	 * @param bool $display_previously_submitted_data
656
+	 * @return string
657
+	 * @throws InvalidArgumentException
658
+	 * @throws InvalidInterfaceException
659
+	 * @throws InvalidDataTypeException
660
+	 * @throws EE_Error
661
+	 * @throws EE_Error
662
+	 * @throws EE_Error
663
+	 */
664
+	public function get_html($display_previously_submitted_data = true)
665
+	{
666
+		$this->ensure_construct_finalized_called();
667
+		if ($display_previously_submitted_data) {
668
+			$this->populate_from_session();
669
+		}
670
+		return $this->_form_html_filter
671
+			? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
+			: $this->_layout_strategy->layout_form();
673
+	}
674
+
675
+
676
+	/**
677
+	 * enqueues JS and CSS for the form.
678
+	 * It is preferred to call this before wp_enqueue_scripts so the
679
+	 * scripts and styles can be put in the header, but if called later
680
+	 * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
+	 * only be in the header; but in HTML5 its ok in the body.
682
+	 * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
+	 * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
+	 *
685
+	 * @return void
686
+	 * @throws EE_Error
687
+	 */
688
+	public function enqueue_js()
689
+	{
690
+		$this->_enqueue_and_localize_form_js();
691
+		foreach ($this->subsections() as $subsection) {
692
+			$subsection->enqueue_js();
693
+		}
694
+	}
695
+
696
+
697
+	/**
698
+	 * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
+	 * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
+	 * the wp_enqueue_scripts hook.
701
+	 * However, registering the form js and localizing it can happen when we
702
+	 * actually output the form (which is preferred, seeing how teh form's fields
703
+	 * could change until it's actually outputted)
704
+	 *
705
+	 * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
+	 *                                                    to be triggered automatically or not
707
+	 * @return void
708
+	 */
709
+	public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
+	{
711
+		wp_register_script(
712
+			'ee_form_section_validation',
713
+			EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
714
+			array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
+			EVENT_ESPRESSO_VERSION,
716
+			true
717
+		);
718
+		wp_localize_script(
719
+			'ee_form_section_validation',
720
+			'ee_form_section_validation_init',
721
+			array('init' => $init_form_validation_automatically ? '1' : '0')
722
+		);
723
+	}
724
+
725
+
726
+	/**
727
+	 * gets the variables used by form_section_validation.js.
728
+	 * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
+	 * but before the wordpress hook wp_loaded
730
+	 *
731
+	 * @throws EE_Error
732
+	 */
733
+	public function _enqueue_and_localize_form_js()
734
+	{
735
+		$this->ensure_construct_finalized_called();
736
+		//actually, we don't want to localize just yet. There may be other forms on the page.
737
+		//so we need to add our form section data to a static variable accessible by all form sections
738
+		//and localize it just before the footer
739
+		$this->localize_validation_rules();
740
+		add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
+		add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
+	}
743
+
744
+
745
+	/**
746
+	 * add our form section data to a static variable accessible by all form sections
747
+	 *
748
+	 * @param bool $return_for_subsection
749
+	 * @return void
750
+	 * @throws EE_Error
751
+	 */
752
+	public function localize_validation_rules($return_for_subsection = false)
753
+	{
754
+		// we only want to localize vars ONCE for the entire form,
755
+		// so if the form section doesn't have a parent, then it must be the top dog
756
+		if ($return_for_subsection || ! $this->parent_section()) {
757
+			EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
+				'form_section_id'  => $this->html_id(true),
759
+				'validation_rules' => $this->get_jquery_validation_rules(),
760
+				'other_data'       => $this->get_other_js_data(),
761
+				'errors'           => $this->subsection_validation_errors_by_html_name(),
762
+			);
763
+			EE_Form_Section_Proper::$_scripts_localized                                = true;
764
+		}
765
+	}
766
+
767
+
768
+	/**
769
+	 * Gets an array of extra data that will be useful for client-side javascript.
770
+	 * This is primarily data added by inputs and forms in addition to any
771
+	 * scripts they might enqueue
772
+	 *
773
+	 * @param array $form_other_js_data
774
+	 * @return array
775
+	 * @throws EE_Error
776
+	 */
777
+	public function get_other_js_data($form_other_js_data = array())
778
+	{
779
+		foreach ($this->subsections() as $subsection) {
780
+			$form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
+		}
782
+		return $form_other_js_data;
783
+	}
784
+
785
+
786
+	/**
787
+	 * Gets a flat array of inputs for this form section and its subsections.
788
+	 * Keys are their form names, and values are the inputs themselves
789
+	 *
790
+	 * @return EE_Form_Input_Base
791
+	 * @throws EE_Error
792
+	 */
793
+	public function inputs_in_subsections()
794
+	{
795
+		$inputs = array();
796
+		foreach ($this->subsections() as $subsection) {
797
+			if ($subsection instanceof EE_Form_Input_Base) {
798
+				$inputs[ $subsection->html_name() ] = $subsection;
799
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
800
+				$inputs += $subsection->inputs_in_subsections();
801
+			}
802
+		}
803
+		return $inputs;
804
+	}
805
+
806
+
807
+	/**
808
+	 * Gets a flat array of all the validation errors.
809
+	 * Keys are html names (because those should be unique)
810
+	 * and values are a string of all their validation errors
811
+	 *
812
+	 * @return string[]
813
+	 * @throws EE_Error
814
+	 */
815
+	public function subsection_validation_errors_by_html_name()
816
+	{
817
+		$inputs = $this->inputs();
818
+		$errors = array();
819
+		foreach ($inputs as $form_input) {
820
+			if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
+				$errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
+			}
823
+		}
824
+		return $errors;
825
+	}
826
+
827
+
828
+	/**
829
+	 * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
+	 * Should be setup by each form during the _enqueues_and_localize_form_js
831
+	 *
832
+	 * @throws InvalidArgumentException
833
+	 * @throws InvalidInterfaceException
834
+	 * @throws InvalidDataTypeException
835
+	 */
836
+	public static function localize_script_for_all_forms()
837
+	{
838
+		//allow inputs and stuff to hook in their JS and stuff here
839
+		do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
+		EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
+		$email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
+			? EE_Registry::instance()->CFG->registration->email_validation_level
843
+			: 'wp_default';
844
+		EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
+		wp_enqueue_script('ee_form_section_validation');
846
+		wp_localize_script(
847
+			'ee_form_section_validation',
848
+			'ee_form_section_vars',
849
+			EE_Form_Section_Proper::$_js_localization
850
+		);
851
+	}
852
+
853
+
854
+	/**
855
+	 * ensure_scripts_localized
856
+	 *
857
+	 * @throws EE_Error
858
+	 */
859
+	public function ensure_scripts_localized()
860
+	{
861
+		if (! EE_Form_Section_Proper::$_scripts_localized) {
862
+			$this->_enqueue_and_localize_form_js();
863
+		}
864
+	}
865
+
866
+
867
+	/**
868
+	 * Gets the hard-coded validation error messages to be used in the JS. The convention
869
+	 * is that the key here should be the same as the custom validation rule put in the JS file
870
+	 *
871
+	 * @return array keys are custom validation rules, and values are internationalized strings
872
+	 */
873
+	private static function _get_localized_error_messages()
874
+	{
875
+		return array(
876
+			'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
+			'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
+		);
879
+	}
880
+
881
+
882
+	/**
883
+	 * @return array
884
+	 */
885
+	public static function js_localization()
886
+	{
887
+		return self::$_js_localization;
888
+	}
889
+
890
+
891
+	/**
892
+	 * @return void
893
+	 */
894
+	public static function reset_js_localization()
895
+	{
896
+		self::$_js_localization = array();
897
+	}
898
+
899
+
900
+	/**
901
+	 * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
+	 * See parent function for more...
903
+	 *
904
+	 * @return array
905
+	 * @throws EE_Error
906
+	 */
907
+	public function get_jquery_validation_rules()
908
+	{
909
+		$jquery_validation_rules = array();
910
+		foreach ($this->get_validatable_subsections() as $subsection) {
911
+			$jquery_validation_rules = array_merge(
912
+				$jquery_validation_rules,
913
+				$subsection->get_jquery_validation_rules()
914
+			);
915
+		}
916
+		return $jquery_validation_rules;
917
+	}
918
+
919
+
920
+	/**
921
+	 * Sanitizes all the data and sets the sanitized value of each field
922
+	 *
923
+	 * @param array $req_data like $_POST
924
+	 * @return void
925
+	 * @throws EE_Error
926
+	 */
927
+	protected function _normalize($req_data)
928
+	{
929
+		$this->_received_submission = true;
930
+		$this->_validation_errors   = array();
931
+		foreach ($this->get_validatable_subsections() as $subsection) {
932
+			try {
933
+				$subsection->_normalize($req_data);
934
+			} catch (EE_Validation_Error $e) {
935
+				$subsection->add_validation_error($e);
936
+			}
937
+		}
938
+	}
939
+
940
+
941
+	/**
942
+	 * Performs validation on this form section and its subsections.
943
+	 * For each subsection,
944
+	 * calls _validate_{subsection_name} on THIS form (if the function exists)
945
+	 * and passes it the subsection, then calls _validate on that subsection.
946
+	 * If you need to perform validation on the form as a whole (considering multiple)
947
+	 * you would be best to override this _validate method,
948
+	 * calling parent::_validate() first.
949
+	 *
950
+	 * @throws EE_Error
951
+	 */
952
+	protected function _validate()
953
+	{
954
+		//reset the cache of whether this form is valid or not- we're re-validating it now
955
+		$this->is_valid = null;
956
+		foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
+			if (method_exists($this, '_validate_' . $subsection_name)) {
958
+				call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
+			}
960
+			$subsection->_validate();
961
+		}
962
+	}
963
+
964
+
965
+	/**
966
+	 * Gets all the validated inputs for the form section
967
+	 *
968
+	 * @return array
969
+	 * @throws EE_Error
970
+	 */
971
+	public function valid_data()
972
+	{
973
+		$inputs = array();
974
+		foreach ($this->subsections() as $subsection_name => $subsection) {
975
+			if ($subsection instanceof EE_Form_Section_Proper) {
976
+				$inputs[ $subsection_name ] = $subsection->valid_data();
977
+			} elseif ($subsection instanceof EE_Form_Input_Base) {
978
+				$inputs[ $subsection_name ] = $subsection->normalized_value();
979
+			}
980
+		}
981
+		return $inputs;
982
+	}
983
+
984
+
985
+	/**
986
+	 * Gets all the inputs on this form section
987
+	 *
988
+	 * @return EE_Form_Input_Base[]
989
+	 * @throws EE_Error
990
+	 */
991
+	public function inputs()
992
+	{
993
+		$inputs = array();
994
+		foreach ($this->subsections() as $subsection_name => $subsection) {
995
+			if ($subsection instanceof EE_Form_Input_Base) {
996
+				$inputs[ $subsection_name ] = $subsection;
997
+			}
998
+		}
999
+		return $inputs;
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 * Gets all the subsections which are a proper form
1005
+	 *
1006
+	 * @return EE_Form_Section_Proper[]
1007
+	 * @throws EE_Error
1008
+	 */
1009
+	public function subforms()
1010
+	{
1011
+		$form_sections = array();
1012
+		foreach ($this->subsections() as $name => $obj) {
1013
+			if ($obj instanceof EE_Form_Section_Proper) {
1014
+				$form_sections[ $name ] = $obj;
1015
+			}
1016
+		}
1017
+		return $form_sections;
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
+	 * Consider using inputs() or subforms()
1024
+	 * if you only want form inputs or proper form sections.
1025
+	 *
1026
+	 * @param boolean $require_construction_to_be_finalized most client code should
1027
+	 *                                                      leave this as TRUE so that the inputs will be properly
1028
+	 *                                                      configured. However, some client code may be ok with
1029
+	 *                                                      construction finalize being called later
1030
+	 *                                                      (realizing that the subsections' html names might not be
1031
+	 *                                                      set yet, etc.)
1032
+	 * @return EE_Form_Section_Proper[]
1033
+	 * @throws EE_Error
1034
+	 */
1035
+	public function subsections($require_construction_to_be_finalized = true)
1036
+	{
1037
+		if ($require_construction_to_be_finalized) {
1038
+			$this->ensure_construct_finalized_called();
1039
+		}
1040
+		return $this->_subsections;
1041
+	}
1042
+
1043
+
1044
+	/**
1045
+	 * Returns whether this form has any subforms or inputs
1046
+	 * @return bool
1047
+	 */
1048
+	public function hasSubsections()
1049
+	{
1050
+		return ! empty($this->_subsections);
1051
+	}
1052
+
1053
+
1054
+	/**
1055
+	 * Returns a simple array where keys are input names, and values are their normalized
1056
+	 * values. (Similar to calling get_input_value on inputs)
1057
+	 *
1058
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
+	 *                                        or just this forms' direct children inputs
1060
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
+	 *                                        or allow multidimensional array
1062
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
+	 *                                        with array keys being input names
1064
+	 *                                        (regardless of whether they are from a subsection or not),
1065
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1066
+	 *                                        where keys are always subsection names and values are either
1067
+	 *                                        the input's normalized value, or an array like the top-level array
1068
+	 * @throws EE_Error
1069
+	 */
1070
+	public function input_values($include_subform_inputs = false, $flatten = false)
1071
+	{
1072
+		return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
+	 * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
+	 * is not necessarily the value we want to display to users. This creates an array
1080
+	 * where keys are the input names, and values are their display values
1081
+	 *
1082
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
+	 *                                        or just this forms' direct children inputs
1084
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
+	 *                                        or allow multidimensional array
1086
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
+	 *                                        with array keys being input names
1088
+	 *                                        (regardless of whether they are from a subsection or not),
1089
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1090
+	 *                                        where keys are always subsection names and values are either
1091
+	 *                                        the input's normalized value, or an array like the top-level array
1092
+	 * @throws EE_Error
1093
+	 */
1094
+	public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
+	{
1096
+		return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
+	}
1098
+
1099
+
1100
+	/**
1101
+	 * Gets the input values from the form
1102
+	 *
1103
+	 * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
+	 *                                        or just the normalized value
1105
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
+	 *                                        or just this forms' direct children inputs
1107
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
+	 *                                        or allow multidimensional array
1109
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
+	 *                                        input names (regardless of whether they are from a subsection or not),
1111
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1112
+	 *                                        where keys are always subsection names and values are either
1113
+	 *                                        the input's normalized value, or an array like the top-level array
1114
+	 * @throws EE_Error
1115
+	 */
1116
+	public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
+	{
1118
+		$input_values = array();
1119
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1120
+			if ($subsection instanceof EE_Form_Input_Base) {
1121
+				$input_values[ $subsection_name ] = $pretty
1122
+					? $subsection->pretty_value()
1123
+					: $subsection->normalized_value();
1124
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
+				$subform_input_values = $subsection->_input_values(
1126
+					$pretty,
1127
+					$include_subform_inputs,
1128
+					$flatten
1129
+				);
1130
+				if ($flatten) {
1131
+					$input_values = array_merge($input_values, $subform_input_values);
1132
+				} else {
1133
+					$input_values[ $subsection_name ] = $subform_input_values;
1134
+				}
1135
+			}
1136
+		}
1137
+		return $input_values;
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * Gets the originally submitted input values from the form
1143
+	 *
1144
+	 * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
+	 *                                   or just this forms' direct children inputs
1146
+	 * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
+	 *                                   with array keys being input names
1148
+	 *                                   (regardless of whether they are from a subsection or not),
1149
+	 *                                   and if $flatten is FALSE it can be a multidimensional array
1150
+	 *                                   where keys are always subsection names and values are either
1151
+	 *                                   the input's normalized value, or an array like the top-level array
1152
+	 * @throws EE_Error
1153
+	 */
1154
+	public function submitted_values($include_subforms = false)
1155
+	{
1156
+		$submitted_values = array();
1157
+		foreach ($this->subsections() as $subsection) {
1158
+			if ($subsection instanceof EE_Form_Input_Base) {
1159
+				// is this input part of an array of inputs?
1160
+				if (strpos($subsection->html_name(), '[') !== false) {
1161
+					$full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
+						explode(
1163
+							'[',
1164
+							str_replace(']', '', $subsection->html_name())
1165
+						),
1166
+						$subsection->raw_value()
1167
+					);
1168
+					$submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
+				} else {
1170
+					$submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
+				}
1172
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
+				$subform_input_values = $subsection->submitted_values($include_subforms);
1174
+				$submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
+			}
1176
+		}
1177
+		return $submitted_values;
1178
+	}
1179
+
1180
+
1181
+	/**
1182
+	 * Indicates whether or not this form has received a submission yet
1183
+	 * (ie, had receive_form_submission called on it yet)
1184
+	 *
1185
+	 * @return boolean
1186
+	 * @throws EE_Error
1187
+	 */
1188
+	public function has_received_submission()
1189
+	{
1190
+		$this->ensure_construct_finalized_called();
1191
+		return $this->_received_submission;
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * Equivalent to passing 'exclude' in the constructor's options array.
1197
+	 * Removes the listed inputs from the form
1198
+	 *
1199
+	 * @param array $inputs_to_exclude values are the input names
1200
+	 * @return void
1201
+	 */
1202
+	public function exclude(array $inputs_to_exclude = array())
1203
+	{
1204
+		foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
+			unset($this->_subsections[ $input_to_exclude_name ]);
1206
+		}
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1212
+	 * @param array $inputs_to_hide
1213
+	 * @throws EE_Error
1214
+	 */
1215
+	public function hide(array $inputs_to_hide = array())
1216
+	{
1217
+		foreach ($inputs_to_hide as $input_to_hide) {
1218
+			$input = $this->get_input($input_to_hide);
1219
+			$input->set_display_strategy(new EE_Hidden_Display_Strategy());
1220
+		}
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * add_subsections
1226
+	 * Adds the listed subsections to the form section.
1227
+	 * If $subsection_name_to_target is provided,
1228
+	 * then new subsections are added before or after that subsection,
1229
+	 * otherwise to the start or end of the entire subsections array.
1230
+	 *
1231
+	 * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1232
+	 *                                                          where keys are their names
1233
+	 * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1234
+	 *                                                          should be added before or after
1235
+	 *                                                          IF $subsection_name_to_target is null,
1236
+	 *                                                          then $new_subsections will be added to
1237
+	 *                                                          the beginning or end of the entire subsections array
1238
+	 * @param boolean                $add_before                whether to add $new_subsections, before or after
1239
+	 *                                                          $subsection_name_to_target,
1240
+	 *                                                          or if $subsection_name_to_target is null,
1241
+	 *                                                          before or after entire subsections array
1242
+	 * @return void
1243
+	 * @throws EE_Error
1244
+	 */
1245
+	public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1246
+	{
1247
+		foreach ($new_subsections as $subsection_name => $subsection) {
1248
+			if (! $subsection instanceof EE_Form_Section_Base) {
1249
+				EE_Error::add_error(
1250
+					sprintf(
1251
+						esc_html__(
1252
+							"Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1253
+							'event_espresso'
1254
+						),
1255
+						get_class($subsection),
1256
+						$subsection_name,
1257
+						$this->name()
1258
+					)
1259
+				);
1260
+				unset($new_subsections[ $subsection_name ]);
1261
+			}
1262
+		}
1263
+		$this->_subsections = EEH_Array::insert_into_array(
1264
+			$this->_subsections,
1265
+			$new_subsections,
1266
+			$subsection_name_to_target,
1267
+			$add_before
1268
+		);
1269
+		if ($this->_construction_finalized) {
1270
+			foreach ($this->_subsections as $name => $subsection) {
1271
+				$subsection->_construct_finalize($this, $name);
1272
+			}
1273
+		}
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 * Just gets all validatable subsections to clean their sensitive data
1279
+	 *
1280
+	 * @throws EE_Error
1281
+	 */
1282
+	public function clean_sensitive_data()
1283
+	{
1284
+		foreach ($this->get_validatable_subsections() as $subsection) {
1285
+			$subsection->clean_sensitive_data();
1286
+		}
1287
+	}
1288
+
1289
+
1290
+	/**
1291
+	 * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1292
+	 * @param string                           $form_submission_error_message
1293
+	 * @param EE_Form_Section_Validatable $form_section unused
1294
+	 * @throws EE_Error
1295
+	 */
1296
+	public function set_submission_error_message(
1297
+		$form_submission_error_message = ''
1298
+	) {
1299
+		$this->_form_submission_error_message = ! empty($form_submission_error_message)
1300
+			? $form_submission_error_message
1301
+			: $this->getAllValidationErrorsString();
1302
+	}
1303
+
1304
+
1305
+	/**
1306
+	 * Returns the cached error message. A default value is set for this during _validate(),
1307
+	 * (called during receive_form_submission) but it can be explicitly set using
1308
+	 * set_submission_error_message
1309
+	 *
1310
+	 * @return string
1311
+	 */
1312
+	public function submission_error_message()
1313
+	{
1314
+		return $this->_form_submission_error_message;
1315
+	}
1316
+
1317
+
1318
+	/**
1319
+	 * Sets a message to display if the data submitted to the form was valid.
1320
+	 * @param string $form_submission_success_message
1321
+	 */
1322
+	public function set_submission_success_message($form_submission_success_message = '')
1323
+	{
1324
+		$this->_form_submission_success_message = ! empty($form_submission_success_message)
1325
+			? $form_submission_success_message
1326
+			: esc_html__('Form submitted successfully', 'event_espresso');
1327
+	}
1328
+
1329
+
1330
+	/**
1331
+	 * Gets a message appropriate for display when the form is correctly submitted
1332
+	 * @return string
1333
+	 */
1334
+	public function submission_success_message()
1335
+	{
1336
+		return $this->_form_submission_success_message;
1337
+	}
1338
+
1339
+
1340
+	/**
1341
+	 * Returns the prefix that should be used on child of this form section for
1342
+	 * their html names. If this form section itself has a parent, prepends ITS
1343
+	 * prefix onto this form section's prefix. Used primarily by
1344
+	 * EE_Form_Input_Base::_set_default_html_name_if_empty
1345
+	 *
1346
+	 * @return string
1347
+	 * @throws EE_Error
1348
+	 */
1349
+	public function html_name_prefix()
1350
+	{
1351
+		if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1352
+			return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1353
+		}
1354
+		return $this->name();
1355
+	}
1356
+
1357
+
1358
+	/**
1359
+	 * Gets the name, but first checks _construct_finalize has been called. If not,
1360
+	 * calls it (assumes there is no parent and that we want the name to be whatever
1361
+	 * was set, which is probably nothing, or the classname)
1362
+	 *
1363
+	 * @return string
1364
+	 * @throws EE_Error
1365
+	 */
1366
+	public function name()
1367
+	{
1368
+		$this->ensure_construct_finalized_called();
1369
+		return parent::name();
1370
+	}
1371
+
1372
+
1373
+	/**
1374
+	 * @return EE_Form_Section_Proper
1375
+	 * @throws EE_Error
1376
+	 */
1377
+	public function parent_section()
1378
+	{
1379
+		$this->ensure_construct_finalized_called();
1380
+		return parent::parent_section();
1381
+	}
1382
+
1383
+
1384
+	/**
1385
+	 * make sure construction finalized was called, otherwise children might not be ready
1386
+	 *
1387
+	 * @return void
1388
+	 * @throws EE_Error
1389
+	 */
1390
+	public function ensure_construct_finalized_called()
1391
+	{
1392
+		if (! $this->_construction_finalized) {
1393
+			$this->_construct_finalize($this->_parent_section, $this->_name);
1394
+		}
1395
+	}
1396
+
1397
+
1398
+	/**
1399
+	 * Checks if any of this form section's inputs, or any of its children's inputs,
1400
+	 * are in teh form data. If any are found, returns true. Else false
1401
+	 *
1402
+	 * @param array $req_data
1403
+	 * @return boolean
1404
+	 * @throws EE_Error
1405
+	 */
1406
+	public function form_data_present_in($req_data = null)
1407
+	{
1408
+		$req_data = $this->getCachedRequest($req_data);
1409
+		foreach ($this->subsections() as $subsection) {
1410
+			if ($subsection instanceof EE_Form_Input_Base) {
1411
+				if ($subsection->form_data_present_in($req_data)) {
1412
+					return true;
1413
+				}
1414
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
1415
+				if ($subsection->form_data_present_in($req_data)) {
1416
+					return true;
1417
+				}
1418
+			}
1419
+		}
1420
+		return false;
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * Gets validation errors for this form section and subsections
1426
+	 * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1427
+	 * gets the validation errors for ALL subsection
1428
+	 *
1429
+	 * @return EE_Validation_Error[]
1430
+	 * @throws EE_Error
1431
+	 */
1432
+	public function get_validation_errors_accumulated()
1433
+	{
1434
+		$validation_errors = $this->get_validation_errors();
1435
+		foreach ($this->get_validatable_subsections() as $subsection) {
1436
+			if ($subsection instanceof EE_Form_Section_Proper) {
1437
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1438
+			} else {
1439
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors();
1440
+			}
1441
+			if ($validation_errors_on_this_subsection) {
1442
+				$validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1443
+			}
1444
+		}
1445
+		return $validation_errors;
1446
+	}
1447
+
1448
+	/**
1449
+	 * Fetch validation errors from children and grandchildren and puts them in a single string.
1450
+	 * This traverses the form section tree to generate this, but you probably want to instead use
1451
+	 * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1452
+	 *
1453
+	 * @return string
1454
+	 * @since $VID:$
1455
+	 */
1456
+	protected function getAllValidationErrorsString()
1457
+	{
1458
+		$submission_error_messages = array();
1459
+		// bad, bad, bad registrant
1460
+		foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1461
+			if ($validation_error instanceof EE_Validation_Error) {
1462
+				$form_section = $validation_error->get_form_section();
1463
+				if ($form_section instanceof EE_Form_Input_Base) {
1464
+				   $label = $validation_error->get_form_section()->html_label_text();
1465
+				} elseif($form_section instanceof EE_Form_Section_Validatable) {
1466
+					$label = $validation_error->get_form_section()->name();
1467
+				} else {
1468
+					$label = esc_html__('Unknown', 'event_espresso');
1469
+				}
1470
+				$submission_error_messages[] = sprintf(
1471
+					__('%s : %s', 'event_espresso'),
1472
+					$label,
1473
+					$validation_error->getMessage()
1474
+				);
1475
+			}
1476
+		}
1477
+		return implode('<br', $submission_error_messages);
1478
+	}
1479
+
1480
+
1481
+	/**
1482
+	 * This isn't just the name of an input, it's a path pointing to an input. The
1483
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
1484
+	 * dot-dot-slash (../) means to ascend into the parent section.
1485
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1486
+	 * which will be returned.
1487
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1488
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1489
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1490
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1491
+	 * Etc
1492
+	 *
1493
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1494
+	 * @return EE_Form_Section_Base
1495
+	 * @throws EE_Error
1496
+	 */
1497
+	public function find_section_from_path($form_section_path)
1498
+	{
1499
+		//check if we can find the input from purely going straight up the tree
1500
+		$input = parent::find_section_from_path($form_section_path);
1501
+		if ($input instanceof EE_Form_Section_Base) {
1502
+			return $input;
1503
+		}
1504
+		$next_slash_pos = strpos($form_section_path, '/');
1505
+		if ($next_slash_pos !== false) {
1506
+			$child_section_name = substr($form_section_path, 0, $next_slash_pos);
1507
+			$subpath            = substr($form_section_path, $next_slash_pos + 1);
1508
+		} else {
1509
+			$child_section_name = $form_section_path;
1510
+			$subpath            = '';
1511
+		}
1512
+		$child_section = $this->get_subsection($child_section_name);
1513
+		if ($child_section instanceof EE_Form_Section_Base) {
1514
+			return $child_section->find_section_from_path($subpath);
1515
+		}
1516
+		return null;
1517
+	}
1518 1518
 }
1519 1519
 
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Validatable.form.php 1 patch
Indentation   +147 added lines, -147 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
 
@@ -35,150 +35,150 @@  discard block
 block discarded – undo
35 35
 abstract class EE_Form_Section_Validatable extends EE_Form_Section_Base
36 36
 {
37 37
 
38
-    /**
39
-     * Array of validation errors in this section. Does not contain validation errors in subsections, however.
40
-     * Those are stored individually on each subsection.
41
-     *
42
-     * @var EE_Validation_Error[]
43
-     */
44
-    protected $_validation_errors = array();
45
-
46
-
47
-
48
-    /**
49
-     * Errors on this form section. Note: EE_Form_Section_Proper
50
-     * has another function for getting all errors in this form section and subsections
51
-     * called get_validation_errors_accumulated
52
-     *
53
-     * @return EE_Validation_Error[]
54
-     */
55
-    public function get_validation_errors()
56
-    {
57
-        return $this->_validation_errors;
58
-    }
59
-
60
-
61
-
62
-    /**
63
-     * returns a comma-separated list of all the validation errors in it.
64
-     * If we want this to be customizable, we may decide to create a strategy for displaying it
65
-     *
66
-     * @return string
67
-     */
68
-    public function get_validation_error_string()
69
-    {
70
-        $validation_error_messages = array();
71
-        if ($this->get_validation_errors()) {
72
-            foreach ($this->get_validation_errors() as $validation_error) {
73
-                if ($validation_error instanceof EE_Validation_Error) {
74
-                    $validation_error_messages[] = $validation_error->getMessage();
75
-                }
76
-            }
77
-        }
78
-        return implode(", ", $validation_error_messages);
79
-    }
80
-
81
-
82
-
83
-    /**
84
-     * Performs validation on this form section (and subsections). Should be called after _normalize()
85
-     *
86
-     * @return boolean of whether or not the form section is valid
87
-     */
88
-    abstract protected function _validate();
89
-
90
-
91
-
92
-    /**
93
-     * Checks if this field has any validation errors
94
-     *
95
-     * @return boolean
96
-     */
97
-    public function is_valid()
98
-    {
99
-        if (count($this->_validation_errors)) {
100
-            return false;
101
-        } else {
102
-            return true;
103
-        }
104
-    }
105
-
106
-
107
-
108
-    /**
109
-     * Sanitizes input for this form section
110
-     *
111
-     * @param array $req_data is the full request data like $_POST
112
-     * @return boolean of whether a normalization error occurred
113
-     */
114
-    abstract protected function _normalize($req_data);
115
-
116
-
117
-
118
-    /**
119
-     * Creates a validation error from the arguments provided, and adds it to the form section's list.
120
-     * If such an EE_Validation_Error object is passed in as the first arg, simply sets this as its form section, and
121
-     * adds it to the list of validation errors of errors
122
-     *
123
-     * @param mixed     $message_or_object  internationalized string describing the validation error; or it could be a
124
-     *                                      proper EE_Validation_Error object
125
-     * @param string    $error_code         a short key which can be used to uniquely identify the error
126
-     * @param Exception $previous_exception if there was an exception that caused the error, that exception
127
-     * @return void
128
-     */
129
-    public function add_validation_error($message_or_object, $error_code = null, $previous_exception = null)
130
-    {
131
-        if ($message_or_object instanceof EE_Validation_Error) {
132
-            $validation_error = $message_or_object;
133
-            $validation_error->set_form_section($this);
134
-        } else {
135
-            $validation_error = new EE_Validation_Error($message_or_object, $error_code, $this, $previous_exception);
136
-        }
137
-        $this->_validation_errors[] = $validation_error;
138
-    }
139
-
140
-
141
-
142
-    /**
143
-     * When generating the JS for the jquery validation rules like<br>
144
-     * <code>$( "#myform" ).validate({
145
-     * rules: {
146
-     * password: "required",
147
-     * password_again: {
148
-     * equalTo: "#password"
149
-     * }
150
-     * }
151
-     * });</code>
152
-     * gets the sections like
153
-     * <br><code>password: "required",
154
-     * password_again: {
155
-     * equalTo: "#password"
156
-     * }</code>
157
-     * except we leave it as a PHP object, and leave wp_localize_script to
158
-     * turn it into a JSON object which can be used by the js
159
-     *
160
-     * @return array
161
-     */
162
-    abstract public function get_jquery_validation_rules();
163
-
164
-
165
-
166
-    /**
167
-     * Checks if this form section's data is present in the req data specified
168
-     *
169
-     * @param array $req_data usually $_POST, if null that's what's used
170
-     * @return boolean
171
-     */
172
-    abstract public function form_data_present_in($req_data = null);
173
-
174
-
175
-
176
-    /**
177
-     * Removes teh sensitive data from this form section (usually done after
178
-     * utilizing the data business function, but before saving it somewhere. Eg,
179
-     * may remove a password from the form after verifying it was correct)
180
-     *
181
-     * @return void
182
-     */
183
-    abstract public function clean_sensitive_data();
38
+	/**
39
+	 * Array of validation errors in this section. Does not contain validation errors in subsections, however.
40
+	 * Those are stored individually on each subsection.
41
+	 *
42
+	 * @var EE_Validation_Error[]
43
+	 */
44
+	protected $_validation_errors = array();
45
+
46
+
47
+
48
+	/**
49
+	 * Errors on this form section. Note: EE_Form_Section_Proper
50
+	 * has another function for getting all errors in this form section and subsections
51
+	 * called get_validation_errors_accumulated
52
+	 *
53
+	 * @return EE_Validation_Error[]
54
+	 */
55
+	public function get_validation_errors()
56
+	{
57
+		return $this->_validation_errors;
58
+	}
59
+
60
+
61
+
62
+	/**
63
+	 * returns a comma-separated list of all the validation errors in it.
64
+	 * If we want this to be customizable, we may decide to create a strategy for displaying it
65
+	 *
66
+	 * @return string
67
+	 */
68
+	public function get_validation_error_string()
69
+	{
70
+		$validation_error_messages = array();
71
+		if ($this->get_validation_errors()) {
72
+			foreach ($this->get_validation_errors() as $validation_error) {
73
+				if ($validation_error instanceof EE_Validation_Error) {
74
+					$validation_error_messages[] = $validation_error->getMessage();
75
+				}
76
+			}
77
+		}
78
+		return implode(", ", $validation_error_messages);
79
+	}
80
+
81
+
82
+
83
+	/**
84
+	 * Performs validation on this form section (and subsections). Should be called after _normalize()
85
+	 *
86
+	 * @return boolean of whether or not the form section is valid
87
+	 */
88
+	abstract protected function _validate();
89
+
90
+
91
+
92
+	/**
93
+	 * Checks if this field has any validation errors
94
+	 *
95
+	 * @return boolean
96
+	 */
97
+	public function is_valid()
98
+	{
99
+		if (count($this->_validation_errors)) {
100
+			return false;
101
+		} else {
102
+			return true;
103
+		}
104
+	}
105
+
106
+
107
+
108
+	/**
109
+	 * Sanitizes input for this form section
110
+	 *
111
+	 * @param array $req_data is the full request data like $_POST
112
+	 * @return boolean of whether a normalization error occurred
113
+	 */
114
+	abstract protected function _normalize($req_data);
115
+
116
+
117
+
118
+	/**
119
+	 * Creates a validation error from the arguments provided, and adds it to the form section's list.
120
+	 * If such an EE_Validation_Error object is passed in as the first arg, simply sets this as its form section, and
121
+	 * adds it to the list of validation errors of errors
122
+	 *
123
+	 * @param mixed     $message_or_object  internationalized string describing the validation error; or it could be a
124
+	 *                                      proper EE_Validation_Error object
125
+	 * @param string    $error_code         a short key which can be used to uniquely identify the error
126
+	 * @param Exception $previous_exception if there was an exception that caused the error, that exception
127
+	 * @return void
128
+	 */
129
+	public function add_validation_error($message_or_object, $error_code = null, $previous_exception = null)
130
+	{
131
+		if ($message_or_object instanceof EE_Validation_Error) {
132
+			$validation_error = $message_or_object;
133
+			$validation_error->set_form_section($this);
134
+		} else {
135
+			$validation_error = new EE_Validation_Error($message_or_object, $error_code, $this, $previous_exception);
136
+		}
137
+		$this->_validation_errors[] = $validation_error;
138
+	}
139
+
140
+
141
+
142
+	/**
143
+	 * When generating the JS for the jquery validation rules like<br>
144
+	 * <code>$( "#myform" ).validate({
145
+	 * rules: {
146
+	 * password: "required",
147
+	 * password_again: {
148
+	 * equalTo: "#password"
149
+	 * }
150
+	 * }
151
+	 * });</code>
152
+	 * gets the sections like
153
+	 * <br><code>password: "required",
154
+	 * password_again: {
155
+	 * equalTo: "#password"
156
+	 * }</code>
157
+	 * except we leave it as a PHP object, and leave wp_localize_script to
158
+	 * turn it into a JSON object which can be used by the js
159
+	 *
160
+	 * @return array
161
+	 */
162
+	abstract public function get_jquery_validation_rules();
163
+
164
+
165
+
166
+	/**
167
+	 * Checks if this form section's data is present in the req data specified
168
+	 *
169
+	 * @param array $req_data usually $_POST, if null that's what's used
170
+	 * @return boolean
171
+	 */
172
+	abstract public function form_data_present_in($req_data = null);
173
+
174
+
175
+
176
+	/**
177
+	 * Removes teh sensitive data from this form section (usually done after
178
+	 * utilizing the data business function, but before saving it somewhere. Eg,
179
+	 * may remove a password from the form after verifying it was correct)
180
+	 *
181
+	 * @return void
182
+	 */
183
+	abstract public function clean_sensitive_data();
184 184
 }
185 185
\ No newline at end of file
Please login to merge, or discard this patch.
modules/single_page_checkout/inc/EE_SPCO_JSON_Response.php 1 patch
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -107,71 +107,71 @@  discard block
 block discarded – undo
107 107
 	public function __toString() {
108 108
 		$JSON_response = array();
109 109
 		// grab notices
110
-		$notices = EE_Error::get_notices( FALSE );
111
-		$this->set_attention( isset( $notices['attention'] ) ? $notices['attention'] : '' );
112
-		$this->set_errors( isset( $notices['errors'] ) ? $notices['errors'] : '' );
113
-		$this->set_success( isset( $notices['success'] ) ? $notices['success'] : '' );
110
+		$notices = EE_Error::get_notices(FALSE);
111
+		$this->set_attention(isset($notices['attention']) ? $notices['attention'] : '');
112
+		$this->set_errors(isset($notices['errors']) ? $notices['errors'] : '');
113
+		$this->set_success(isset($notices['success']) ? $notices['success'] : '');
114 114
 		// add notices to JSON response, but only if they exist
115
-		if ( $this->attention() ) {
115
+		if ($this->attention()) {
116 116
 			$JSON_response['attention'] = $this->attention();
117 117
 		}
118
-		if ( $this->errors() ) {
118
+		if ($this->errors()) {
119 119
 			$JSON_response['errors'] = $this->errors();
120 120
 		}
121
-		if ( $this->unexpected_errors() ) {
121
+		if ($this->unexpected_errors()) {
122 122
 			$JSON_response['unexpected_errors'] = $this->unexpected_errors();
123 123
 		}
124
-		if ( $this->success() ) {
124
+		if ($this->success()) {
125 125
 			$JSON_response['success'] = $this->success();
126 126
 		}
127 127
 		// but if NO notices are set... at least set the "success" as a key so that the JS knows everything worked
128
-		if ( ! isset( $JSON_response[ 'attention' ] ) && ! isset( $JSON_response[ 'errors' ] ) && ! isset( $JSON_response[ 'success' ] ) ) {
128
+		if ( ! isset($JSON_response['attention']) && ! isset($JSON_response['errors']) && ! isset($JSON_response['success'])) {
129 129
 			$JSON_response['success'] = null;
130 130
 		}
131 131
 		// set redirect_url, IF it exists
132
-		if ( $this->redirect_url() ) {
132
+		if ($this->redirect_url()) {
133 133
 			$JSON_response['redirect_url'] = $this->redirect_url();
134 134
 		}
135 135
 		// set registration_time_limit, IF it exists
136
-		if ( $this->registration_time_limit() ) {
136
+		if ($this->registration_time_limit()) {
137 137
 			$JSON_response['registration_time_limit'] = $this->registration_time_limit();
138 138
 		}
139 139
 		// set payment_amount, IF it exists
140
-		if ( $this->payment_amount() !== null ) {
141
-			$JSON_response[ 'payment_amount' ] = $this->payment_amount();
140
+		if ($this->payment_amount() !== null) {
141
+			$JSON_response['payment_amount'] = $this->payment_amount();
142 142
 		}
143 143
 		// grab generic return data
144 144
 		$return_data = $this->return_data();
145 145
 		// add billing form validation rules
146
-		if ( $this->validation_rules() ) {
146
+		if ($this->validation_rules()) {
147 147
 			$return_data['validation_rules'] = $this->validation_rules();
148 148
 		}
149 149
 		// set reg_step_html, IF it exists
150
-		if ( $this->reg_step_html() ) {
150
+		if ($this->reg_step_html()) {
151 151
 			$return_data['reg_step_html'] = $this->reg_step_html();
152 152
 		}
153 153
 		// set method of payment, IF it exists
154
-		if ( $this->method_of_payment() ) {
154
+		if ($this->method_of_payment()) {
155 155
 			$return_data['method_of_payment'] = $this->method_of_payment();
156 156
 		}
157 157
 		// set "plz_select_method_of_payment" message, IF it exists
158
-		if ( $this->plz_select_method_of_payment() ) {
158
+		if ($this->plz_select_method_of_payment()) {
159 159
 			$return_data['plz_select_method_of_payment'] = $this->plz_select_method_of_payment();
160 160
 		}
161 161
 		// set redirect_form, IF it exists
162
-		if ( $this->redirect_form() ) {
162
+		if ($this->redirect_form()) {
163 163
 			$return_data['redirect_form'] = $this->redirect_form();
164 164
 		}
165 165
 		// and finally, add return_data array to main JSON response array, IF it contains anything
166 166
 		// why did we add some of the above properties to the return data array?
167 167
 		// because it is easier and cleaner in the Javascript to deal with this way
168
-		if ( ! empty( $return_data )) {
168
+		if ( ! empty($return_data)) {
169 169
 			$JSON_response['return_data'] = $return_data;
170 170
 		}
171 171
 		// filter final array
172
-		$JSON_response = apply_filters( 'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', $JSON_response );
172
+		$JSON_response = apply_filters('FHEE__EE_SPCO_JSON_Response___toString__JSON_response', $JSON_response);
173 173
 		// return encoded array
174
-		return wp_json_encode( $JSON_response );
174
+		return wp_json_encode($JSON_response);
175 175
 	}
176 176
 
177 177
 
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 	/**
180 180
 	 * @param string $attention
181 181
 	 */
182
-	public function set_attention( $attention ) {
182
+	public function set_attention($attention) {
183 183
 		$this->_attention = $attention;
184 184
 	}
185 185
 
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
 	/**
198 198
 	 * @param string $errors
199 199
 	 */
200
-	public function set_errors( $errors ) {
200
+	public function set_errors($errors) {
201 201
 		$this->_errors = $errors;
202 202
 	}
203 203
 
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 	/**
225 225
 	 * @param string $unexpected_errors
226 226
 	 */
227
-	public function set_unexpected_errors( $unexpected_errors ) {
227
+	public function set_unexpected_errors($unexpected_errors) {
228 228
 		$this->_unexpected_errors = $unexpected_errors;
229 229
 	}
230 230
 
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
 	/**
234 234
 	 * @param string $success
235 235
 	 */
236
-	public function set_success( $success ) {
236
+	public function set_success($success) {
237 237
 		$this->_success = $success;
238 238
 	}
239 239
 
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
 	/**
252 252
 	 * @param string $method_of_payment
253 253
 	 */
254
-	public function set_method_of_payment( $method_of_payment ) {
254
+	public function set_method_of_payment($method_of_payment) {
255 255
 		$this->_method_of_payment = $method_of_payment;
256 256
 	}
257 257
 
@@ -278,8 +278,8 @@  discard block
 block discarded – undo
278 278
 	/**
279 279
 	 * @param float $payment_amount
280 280
 	 */
281
-	public function set_payment_amount( $payment_amount ) {
282
-		$this->_payment_amount = (float)$payment_amount;
281
+	public function set_payment_amount($payment_amount) {
282
+		$this->_payment_amount = (float) $payment_amount;
283 283
 	}
284 284
 
285 285
 
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
 	/**
288 288
 	 * @param string $next_step_html
289 289
 	 */
290
-	public function set_reg_step_html( $next_step_html ) {
290
+	public function set_reg_step_html($next_step_html) {
291 291
 		$this->_reg_step_html = $next_step_html;
292 292
 	}
293 293
 
@@ -305,7 +305,7 @@  discard block
 block discarded – undo
305 305
 	/**
306 306
 	 * @param string $redirect_form
307 307
 	 */
308
-	public function set_redirect_form( $redirect_form ) {
308
+	public function set_redirect_form($redirect_form) {
309 309
 		$this->_redirect_form = $redirect_form;
310 310
 	}
311 311
 
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
 	 * @return string
316 316
 	 */
317 317
 	public function redirect_form() {
318
-		return ! empty( $this->_redirect_form ) ? $this->_redirect_form : FALSE;
318
+		return ! empty($this->_redirect_form) ? $this->_redirect_form : FALSE;
319 319
 	}
320 320
 
321 321
 
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
 	/**
324 324
 	 * @param string $plz_select_method_of_payment
325 325
 	 */
326
-	public function set_plz_select_method_of_payment( $plz_select_method_of_payment ) {
326
+	public function set_plz_select_method_of_payment($plz_select_method_of_payment) {
327 327
 		$this->_plz_select_method_of_payment = $plz_select_method_of_payment;
328 328
 	}
329 329
 
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
 	/**
342 342
 	 * @param string $redirect_url
343 343
 	 */
344
-	public function set_redirect_url( $redirect_url ) {
344
+	public function set_redirect_url($redirect_url) {
345 345
 		$this->_redirect_url = $redirect_url;
346 346
 	}
347 347
 
@@ -368,7 +368,7 @@  discard block
 block discarded – undo
368 368
 	/**
369 369
 	 * @param string $registration_time_limit
370 370
 	 */
371
-	public function set_registration_time_limit( $registration_time_limit ) {
371
+	public function set_registration_time_limit($registration_time_limit) {
372 372
 		$this->_registration_time_limit = $registration_time_limit;
373 373
 	}
374 374
 
@@ -377,8 +377,8 @@  discard block
 block discarded – undo
377 377
 	/**
378 378
 	 * @param array $return_data
379 379
 	 */
380
-	public function set_return_data( $return_data ) {
381
-		$this->_return_data = array_merge( $this->_return_data, $return_data );
380
+	public function set_return_data($return_data) {
381
+		$this->_return_data = array_merge($this->_return_data, $return_data);
382 382
 	}
383 383
 
384 384
 
@@ -395,9 +395,9 @@  discard block
 block discarded – undo
395 395
 	/**
396 396
 	 * @param array $validation_rules
397 397
 	 */
398
-	public function add_validation_rules( $validation_rules = array() ) {
399
-		if ( is_array( $validation_rules ) && ! empty( $validation_rules )) {
400
-			$this->_validation_rules = array_merge( $this->_validation_rules, $validation_rules );
398
+	public function add_validation_rules($validation_rules = array()) {
399
+		if (is_array($validation_rules) && ! empty($validation_rules)) {
400
+			$this->_validation_rules = array_merge($this->_validation_rules, $validation_rules);
401 401
 		}
402 402
 	}
403 403
 
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
 	 * @return array | bool
408 408
 	 */
409 409
 	public function validation_rules() {
410
-		return ! empty( $this->_validation_rules ) ? $this->_validation_rules : FALSE;
410
+		return ! empty($this->_validation_rules) ? $this->_validation_rules : FALSE;
411 411
 	}
412 412
 
413 413
 
Please login to merge, or discard this patch.