Completed
Branch FET-10857-model-field-factory (375188)
by
unknown
118:39 queued 107:14
created
form_sections/strategies/display/EE_Number_Input_Display_Strategy.php 2 patches
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -64,6 +64,9 @@
 block discarded – undo
64 64
     }
65 65
 
66 66
 
67
+    /**
68
+     * @param string $argument_label
69
+     */
67 70
     private function throwValidationException($argument_label, $argument_value)
68 71
     {
69 72
         throw new InvalidArgumentException(
Please login to merge, or discard this patch.
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -14,111 +14,111 @@
 block discarded – undo
14 14
 class EE_Number_Input_Display_Strategy extends EE_Display_Strategy_Base
15 15
 {
16 16
 
17
-    /**
18
-     * minimum value for number field
19
-     *
20
-     * @var int|null $min
21
-     */
22
-    protected $min;
23
-
24
-    /**
25
-     * maximum value for number field
26
-     *
27
-     * @var int|null $max
28
-     */
29
-    protected $max;
30
-
31
-
32
-    /**
33
-     * This is used to set the "step" attribute for the html5 number input.
34
-     * Controls the increments on the input when incrementing or decrementing the value.
35
-     * Note:  Although the step attribute allows for the string "any" to be used, Firefox and Chrome will interpret that
36
-     * to increment by 1.  So although "any" is accepted as a value, it is converted to 1.
37
-     * @var float
38
-     */
39
-    protected $step;
40
-
41
-
42
-    /**
43
-     * EE_Number_Input_Display_Strategy constructor.
44
-     * Null is the default value for the incoming arguments because 0 is a valid value.  So we use null
45
-     * to indicate NOT setting this attribute.
46
-     *
47
-     * @param int|null $min
48
-     * @param int|null $max
49
-     * @param int|null $step
50
-     * @throws InvalidArgumentException
51
-     */
52
-    public function __construct($min = null, $max = null, $step = null)
53
-    {
54
-        $this->min = is_numeric($min) || $min === null
55
-            ? $min
56
-            : $this->throwValidationException('min', $min);
57
-        $this->max = is_numeric($max) || $max === null
58
-            ? $max
59
-            : $this->throwValidationException('max', $max);
60
-        $step = $step === 'any' ? 1 : $step;
61
-        $this->step = is_numeric($step) || $step === null
62
-            ? $step
63
-            : $this->throwValidationException('step', $step);
64
-    }
65
-
66
-
67
-    private function throwValidationException($argument_label, $argument_value)
68
-    {
69
-        throw new InvalidArgumentException(
70
-            sprintf(
71
-                esc_html__(
72
-                    'The %1$s parameter value for %2$s must be numeric or null, %3$s was passed into the constructor.',
73
-                    'event_espresso'
74
-                ),
75
-                $argument_label,
76
-                __CLASS__,
77
-                $argument_value
78
-            )
79
-        );
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * @return string of html to display the field
86
-     */
87
-    public function display()
88
-    {
89
-        $input = $this->_opening_tag('input');
90
-        $input .= $this->_attributes_string(
91
-            array_merge(
92
-                $this->_standard_attributes_array(),
93
-                $this->getNumberInputAttributes()
94
-            )
95
-        );
96
-        $input .= $this->_close_tag();
97
-        return $input;
98
-    }
99
-
100
-
101
-    /**
102
-     * Return the attributes specific to this display strategy
103
-     * @return array
104
-     */
105
-    private function getNumberInputAttributes()
106
-    {
107
-        $attributes = array(
108
-            'type' => 'number',
109
-            'value' => $this->_input->raw_value_in_form()
110
-        );
111
-        if ($this->min !== null) {
112
-            $attributes['min'] = $this->min;
113
-        }
114
-        if ($this->max !== null) {
115
-            $attributes['max'] = $this->max;
116
-        }
117
-        if ($this->step !== null) {
118
-            $attributes['step'] = $this->step;
119
-        }
120
-        return $attributes;
121
-    }
17
+	/**
18
+	 * minimum value for number field
19
+	 *
20
+	 * @var int|null $min
21
+	 */
22
+	protected $min;
23
+
24
+	/**
25
+	 * maximum value for number field
26
+	 *
27
+	 * @var int|null $max
28
+	 */
29
+	protected $max;
30
+
31
+
32
+	/**
33
+	 * This is used to set the "step" attribute for the html5 number input.
34
+	 * Controls the increments on the input when incrementing or decrementing the value.
35
+	 * Note:  Although the step attribute allows for the string "any" to be used, Firefox and Chrome will interpret that
36
+	 * to increment by 1.  So although "any" is accepted as a value, it is converted to 1.
37
+	 * @var float
38
+	 */
39
+	protected $step;
40
+
41
+
42
+	/**
43
+	 * EE_Number_Input_Display_Strategy constructor.
44
+	 * Null is the default value for the incoming arguments because 0 is a valid value.  So we use null
45
+	 * to indicate NOT setting this attribute.
46
+	 *
47
+	 * @param int|null $min
48
+	 * @param int|null $max
49
+	 * @param int|null $step
50
+	 * @throws InvalidArgumentException
51
+	 */
52
+	public function __construct($min = null, $max = null, $step = null)
53
+	{
54
+		$this->min = is_numeric($min) || $min === null
55
+			? $min
56
+			: $this->throwValidationException('min', $min);
57
+		$this->max = is_numeric($max) || $max === null
58
+			? $max
59
+			: $this->throwValidationException('max', $max);
60
+		$step = $step === 'any' ? 1 : $step;
61
+		$this->step = is_numeric($step) || $step === null
62
+			? $step
63
+			: $this->throwValidationException('step', $step);
64
+	}
65
+
66
+
67
+	private function throwValidationException($argument_label, $argument_value)
68
+	{
69
+		throw new InvalidArgumentException(
70
+			sprintf(
71
+				esc_html__(
72
+					'The %1$s parameter value for %2$s must be numeric or null, %3$s was passed into the constructor.',
73
+					'event_espresso'
74
+				),
75
+				$argument_label,
76
+				__CLASS__,
77
+				$argument_value
78
+			)
79
+		);
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * @return string of html to display the field
86
+	 */
87
+	public function display()
88
+	{
89
+		$input = $this->_opening_tag('input');
90
+		$input .= $this->_attributes_string(
91
+			array_merge(
92
+				$this->_standard_attributes_array(),
93
+				$this->getNumberInputAttributes()
94
+			)
95
+		);
96
+		$input .= $this->_close_tag();
97
+		return $input;
98
+	}
99
+
100
+
101
+	/**
102
+	 * Return the attributes specific to this display strategy
103
+	 * @return array
104
+	 */
105
+	private function getNumberInputAttributes()
106
+	{
107
+		$attributes = array(
108
+			'type' => 'number',
109
+			'value' => $this->_input->raw_value_in_form()
110
+		);
111
+		if ($this->min !== null) {
112
+			$attributes['min'] = $this->min;
113
+		}
114
+		if ($this->max !== null) {
115
+			$attributes['max'] = $this->max;
116
+		}
117
+		if ($this->step !== null) {
118
+			$attributes['step'] = $this->step;
119
+		}
120
+		return $attributes;
121
+	}
122 122
 
123 123
 }
124 124
 // End of file EE_Number_Input_Display_Strategy.php
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Float_Input.input.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -11,33 +11,33 @@
 block discarded – undo
11 11
 class EE_Float_Input extends EE_Form_Input_Base
12 12
 {
13 13
 
14
-    /**
15
-     * @param array $input_settings
16
-     * @throws InvalidArgumentException
17
-     */
18
-    public function __construct($input_settings = array())
19
-    {
20
-        $this->_set_display_strategy(
21
-            new EE_Number_Input_Display_Strategy(
22
-                isset($input_settings['min_value'])
23
-                    ? $input_settings['min_value']
24
-                    : null,
25
-                isset($input_settings['max_value'])
26
-                    ? $input_settings['max_value']
27
-                    : null,
28
-                isset($input_settings['step_value'])
29
-                    ? $input_settings['step_value']
30
-                    : null
31
-            )
32
-        );
33
-        $this->_set_normalization_strategy(new EE_Float_Normalization());
34
-        $this->_add_validation_strategy(
35
-            new EE_Float_Validation_Strategy(
36
-                isset($input_settings['validation_error_message'])
37
-                    ? $input_settings['validation_error_message']
38
-                    : null
39
-            )
40
-        );
41
-        parent::__construct($input_settings);
42
-    }
14
+	/**
15
+	 * @param array $input_settings
16
+	 * @throws InvalidArgumentException
17
+	 */
18
+	public function __construct($input_settings = array())
19
+	{
20
+		$this->_set_display_strategy(
21
+			new EE_Number_Input_Display_Strategy(
22
+				isset($input_settings['min_value'])
23
+					? $input_settings['min_value']
24
+					: null,
25
+				isset($input_settings['max_value'])
26
+					? $input_settings['max_value']
27
+					: null,
28
+				isset($input_settings['step_value'])
29
+					? $input_settings['step_value']
30
+					: null
31
+			)
32
+		);
33
+		$this->_set_normalization_strategy(new EE_Float_Normalization());
34
+		$this->_add_validation_strategy(
35
+			new EE_Float_Validation_Strategy(
36
+				isset($input_settings['validation_error_message'])
37
+					? $input_settings['validation_error_message']
38
+					: null
39
+			)
40
+		);
41
+		parent::__construct($input_settings);
42
+	}
43 43
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Base_Class.class.php 2 patches
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -155,8 +155,8 @@  discard block
 block discarded – undo
155 155
             list($this->_dt_frmt, $this->_tm_frmt) = $date_formats;
156 156
         } else {
157 157
             //set default formats for date and time
158
-            $this->_dt_frmt = (string)get_option('date_format', 'Y-m-d');
159
-            $this->_tm_frmt = (string)get_option('time_format', 'g:i a');
158
+            $this->_dt_frmt = (string) get_option('date_format', 'Y-m-d');
159
+            $this->_tm_frmt = (string) get_option('time_format', 'g:i a');
160 160
         }
161 161
         //if db model is instantiating
162 162
         if ($bydb) {
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
      */
479 479
     public function get_format($full = true)
480 480
     {
481
-        return $full ? $this->_dt_frmt . ' ' . $this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
481
+        return $full ? $this->_dt_frmt.' '.$this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
482 482
     }
483 483
 
484 484
 
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
         $model = $this->get_model();
588 588
         $model->field_settings_for($fieldname);
589 589
         $cache_type = $pretty ? 'pretty' : 'standard';
590
-        $cache_type .= ! empty($extra_cache_ref) ? '_' . $extra_cache_ref : '';
590
+        $cache_type .= ! empty($extra_cache_ref) ? '_'.$extra_cache_ref : '';
591 591
         if (isset($this->_cached_properties[$fieldname][$cache_type])) {
592 592
             return $this->_cached_properties[$fieldname][$cache_type];
593 593
         }
@@ -802,7 +802,7 @@  discard block
 block discarded – undo
802 802
         $current_cache_id = ''
803 803
     ) {
804 804
         // verify that incoming object is of the correct type
805
-        $obj_class = 'EE_' . $relationName;
805
+        $obj_class = 'EE_'.$relationName;
806 806
         if ($newly_saved_object instanceof $obj_class) {
807 807
             /* @type EE_Base_Class $newly_saved_object */
808 808
             // now get the type of relation
@@ -1288,7 +1288,7 @@  discard block
 block discarded – undo
1288 1288
      */
1289 1289
     public function get_i18n_datetime($field_name, $format = '')
1290 1290
     {
1291
-        $format = empty($format) ? $this->_dt_frmt . ' ' . $this->_tm_frmt : $format;
1291
+        $format = empty($format) ? $this->_dt_frmt.' '.$this->_tm_frmt : $format;
1292 1292
         return date_i18n(
1293 1293
             $format,
1294 1294
             EEH_DTT_Helper::get_timestamp_with_offset($this->get_raw($field_name), $this->_timezone)
@@ -1426,8 +1426,8 @@  discard block
 block discarded – undo
1426 1426
         }
1427 1427
         $original_timezone = $this->_timezone;
1428 1428
         $this->set_timezone($timezone);
1429
-        $fn = (array)$field_name;
1430
-        $args = array_merge($fn, (array)$args);
1429
+        $fn = (array) $field_name;
1430
+        $args = array_merge($fn, (array) $args);
1431 1431
         if ( ! method_exists($this, $callback)) {
1432 1432
             throw new EE_Error(
1433 1433
                 sprintf(
@@ -1439,8 +1439,8 @@  discard block
 block discarded – undo
1439 1439
                 )
1440 1440
             );
1441 1441
         }
1442
-        $args = (array)$args;
1443
-        $return = $prepend . call_user_func_array(array($this, $callback), $args) . $append;
1442
+        $args = (array) $args;
1443
+        $return = $prepend.call_user_func_array(array($this, $callback), $args).$append;
1444 1444
         $this->set_timezone($original_timezone);
1445 1445
         return $return;
1446 1446
     }
@@ -1579,14 +1579,14 @@  discard block
 block discarded – undo
1579 1579
          * @param array         $set_cols_n_values
1580 1580
          * @param EE_Base_Class $model_object
1581 1581
          */
1582
-        $set_cols_n_values = (array)apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values,
1582
+        $set_cols_n_values = (array) apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values,
1583 1583
             $this);
1584 1584
         //set attributes as provided in $set_cols_n_values
1585 1585
         foreach ($set_cols_n_values as $column => $value) {
1586 1586
             $this->set($column, $value);
1587 1587
         }
1588 1588
         // no changes ? then don't do anything
1589
-        if (! $this->_has_changes && $this->ID() && $model->get_primary_key_field()->is_auto_increment()) {
1589
+        if ( ! $this->_has_changes && $this->ID() && $model->get_primary_key_field()->is_auto_increment()) {
1590 1590
             return 0;
1591 1591
         }
1592 1592
         /**
@@ -1638,8 +1638,8 @@  discard block
 block discarded – undo
1638 1638
                                 __('Using a model object %1$s that is NOT in the entity map, can lead to unexpected errors. You should either: %4$s 1. Put it in the entity mapper by calling %2$s %4$s 2. Discard this model object and use what is in the entity mapper %4$s 3. Fetch from the database using %3$s',
1639 1639
                                     'event_espresso'),
1640 1640
                                 get_class($this),
1641
-                                get_class($model) . '::instance()->add_to_entity_map()',
1642
-                                get_class($model) . '::instance()->get_one_by_ID()',
1641
+                                get_class($model).'::instance()->add_to_entity_map()',
1642
+                                get_class($model).'::instance()->get_one_by_ID()',
1643 1643
                                 '<br />'
1644 1644
                             )
1645 1645
                         );
@@ -1772,7 +1772,7 @@  discard block
 block discarded – undo
1772 1772
      */
1773 1773
     public function get_model()
1774 1774
     {
1775
-        if( ! $this->_model){
1775
+        if ( ! $this->_model) {
1776 1776
             $modelName = self::_get_model_classname(get_class($this));
1777 1777
             $this->_model = self::_get_model_instance_with_name($modelName, $this->_timezone);
1778 1778
         } else {
@@ -1915,7 +1915,7 @@  discard block
 block discarded – undo
1915 1915
         if (strpos($model_name, "EE_") === 0) {
1916 1916
             $model_classname = str_replace("EE_", "EEM_", $model_name);
1917 1917
         } else {
1918
-            $model_classname = "EEM_" . $model_name;
1918
+            $model_classname = "EEM_".$model_name;
1919 1919
         }
1920 1920
         return $model_classname;
1921 1921
     }
@@ -2302,7 +2302,7 @@  discard block
 block discarded – undo
2302 2302
      */
2303 2303
     protected function _property_exists($properties)
2304 2304
     {
2305
-        foreach ((array)$properties as $property_name) {
2305
+        foreach ((array) $properties as $property_name) {
2306 2306
             //first make sure this property exists
2307 2307
             if ( ! $this->_fields[$property_name]) {
2308 2308
                 throw new EE_Error(
@@ -2632,8 +2632,8 @@  discard block
 block discarded – undo
2632 2632
                         __('Trying to refresh a model object with ID "%1$s" that\'s not in the entity map? First off: you should put it in the entity map by calling %2$s. Second off, if you want what\'s in the database right now, you should just call %3$s yourself and discard this model object.',
2633 2633
                             'event_espresso'),
2634 2634
                         $this->ID(),
2635
-                        get_class($this->get_model()) . '::instance()->add_to_entity_map()',
2636
-                        get_class($this->get_model()) . '::instance()->refresh_entity_map()'
2635
+                        get_class($this->get_model()).'::instance()->add_to_entity_map()',
2636
+                        get_class($this->get_model()).'::instance()->refresh_entity_map()'
2637 2637
                     )
2638 2638
                 );
2639 2639
             }
@@ -2693,7 +2693,7 @@  discard block
 block discarded – undo
2693 2693
         $model = $this->get_model();
2694 2694
         foreach ($model->relation_settings() as $relation_name => $relation_obj) {
2695 2695
             if ($relation_obj instanceof EE_Belongs_To_Relation) {
2696
-                $classname = 'EE_' . $model->get_this_model_name();
2696
+                $classname = 'EE_'.$model->get_this_model_name();
2697 2697
                 if (
2698 2698
                     $this->get_one_from_cache($relation_name) instanceof $classname
2699 2699
                     && $this->get_one_from_cache($relation_name)->ID()
Please login to merge, or discard this patch.
Indentation   +2709 added lines, -2709 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
 do_action('AHEE_log', __FILE__, ' FILE LOADED', '');
5 5
 
@@ -25,2714 +25,2714 @@  discard block
 block discarded – undo
25 25
 abstract class EE_Base_Class
26 26
 {
27 27
 
28
-    /**
29
-     * This is an array of the original properties and values provided during construction
30
-     * of this model object. (keys are model field names, values are their values).
31
-     * This list is important to remember so that when we are merging data from the db, we know
32
-     * which values to override and which to not override.
33
-     *
34
-     * @var array
35
-     */
36
-    protected $_props_n_values_provided_in_constructor;
37
-
38
-    /**
39
-     * Timezone
40
-     * This gets set by the "set_timezone()" method so that we know what timezone incoming strings|timestamps are in.
41
-     * This can also be used before a get to set what timezone you want strings coming out of the object to be in.  NOT
42
-     * all EE_Base_Class child classes use this property but any that use a EE_Datetime_Field data type will have
43
-     * access to it.
44
-     *
45
-     * @var string
46
-     */
47
-    protected $_timezone;
48
-
49
-
50
-
51
-    /**
52
-     * date format
53
-     * pattern or format for displaying dates
54
-     *
55
-     * @var string $_dt_frmt
56
-     */
57
-    protected $_dt_frmt;
58
-
59
-
60
-
61
-    /**
62
-     * time format
63
-     * pattern or format for displaying time
64
-     *
65
-     * @var string $_tm_frmt
66
-     */
67
-    protected $_tm_frmt;
68
-
69
-
70
-
71
-    /**
72
-     * This property is for holding a cached array of object properties indexed by property name as the key.
73
-     * The purpose of this is for setting a cache on properties that may have calculated values after a
74
-     * prepare_for_get.  That way the cache can be checked first and the calculated property returned instead of having
75
-     * to recalculate. Used by _set_cached_property() and _get_cached_property() methods.
76
-     *
77
-     * @var array
78
-     */
79
-    protected $_cached_properties = array();
80
-
81
-    /**
82
-     * An array containing keys of the related model, and values are either an array of related mode objects or a
83
-     * single
84
-     * related model object. see the model's _model_relations. The keys should match those specified. And if the
85
-     * relation is of type EE_Belongs_To (or one of its children), then there should only be ONE related model object,
86
-     * all others have an array)
87
-     *
88
-     * @var array
89
-     */
90
-    protected $_model_relations = array();
91
-
92
-    /**
93
-     * Array where keys are field names (see the model's _fields property) and values are their values. To see what
94
-     * their types should be, look at what that field object returns on its prepare_for_get and prepare_for_set methods)
95
-     *
96
-     * @var array
97
-     */
98
-    protected $_fields = array();
99
-
100
-    /**
101
-     * @var boolean indicating whether or not this model object is intended to ever be saved
102
-     * For example, we might create model objects intended to only be used for the duration
103
-     * of this request and to be thrown away, and if they were accidentally saved
104
-     * it would be a bug.
105
-     */
106
-    protected $_allow_persist = true;
107
-
108
-    /**
109
-     * @var boolean indicating whether or not this model object's properties have changed since construction
110
-     */
111
-    protected $_has_changes = false;
112
-
113
-    /**
114
-     * @var EEM_Base
115
-     */
116
-    protected $_model;
117
-
118
-
119
-
120
-    /**
121
-     * basic constructor for Event Espresso classes, performs any necessary initialization, and verifies it's children
122
-     * play nice
123
-     *
124
-     * @param array   $fieldValues                             where each key is a field (ie, array key in the 2nd
125
-     *                                                         layer of the model's _fields array, (eg, EVT_ID,
126
-     *                                                         TXN_amount, QST_name, etc) and values are their values
127
-     * @param boolean $bydb                                    a flag for setting if the class is instantiated by the
128
-     *                                                         corresponding db model or not.
129
-     * @param string  $timezone                                indicate what timezone you want any datetime fields to
130
-     *                                                         be in when instantiating a EE_Base_Class object.
131
-     * @param array   $date_formats                            An array of date formats to set on construct where first
132
-     *                                                         value is the date_format and second value is the time
133
-     *                                                         format.
134
-     * @throws EE_Error
135
-     */
136
-    protected function __construct($fieldValues = array(), $bydb = false, $timezone = '', $date_formats = array())
137
-    {
138
-        $className = get_class($this);
139
-        do_action("AHEE__{$className}__construct", $this, $fieldValues);
140
-        $model = $this->get_model();
141
-        $model_fields = $model->field_settings(false);
142
-        // ensure $fieldValues is an array
143
-        $fieldValues = is_array($fieldValues) ? $fieldValues : array($fieldValues);
144
-        // EEH_Debug_Tools::printr( $fieldValues, '$fieldValues  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
145
-        // verify client code has not passed any invalid field names
146
-        foreach ($fieldValues as $field_name => $field_value) {
147
-            if ( ! isset($model_fields[$field_name])) {
148
-                throw new EE_Error(sprintf(__("Invalid field (%s) passed to constructor of %s. Allowed fields are :%s",
149
-                    "event_espresso"), $field_name, get_class($this), implode(", ", array_keys($model_fields))));
150
-            }
151
-        }
152
-        // EEH_Debug_Tools::printr( $model_fields, '$model_fields  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
153
-        $this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
154
-        if ( ! empty($date_formats) && is_array($date_formats)) {
155
-            list($this->_dt_frmt, $this->_tm_frmt) = $date_formats;
156
-        } else {
157
-            //set default formats for date and time
158
-            $this->_dt_frmt = (string)get_option('date_format', 'Y-m-d');
159
-            $this->_tm_frmt = (string)get_option('time_format', 'g:i a');
160
-        }
161
-        //if db model is instantiating
162
-        if ($bydb) {
163
-            //client code has indicated these field values are from the database
164
-            foreach ($model_fields as $fieldName => $field) {
165
-                $this->set_from_db($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null);
166
-            }
167
-        } else {
168
-            //we're constructing a brand
169
-            //new instance of the model object. Generally, this means we'll need to do more field validation
170
-            foreach ($model_fields as $fieldName => $field) {
171
-                $this->set($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null, true);
172
-            }
173
-        }
174
-        //remember what values were passed to this constructor
175
-        $this->_props_n_values_provided_in_constructor = $fieldValues;
176
-        //remember in entity mapper
177
-        if ( ! $bydb && $model->has_primary_key_field() && $this->ID()) {
178
-            $model->add_to_entity_map($this);
179
-        }
180
-        //setup all the relations
181
-        foreach ($model->relation_settings() as $relation_name => $relation_obj) {
182
-            if ($relation_obj instanceof EE_Belongs_To_Relation) {
183
-                $this->_model_relations[$relation_name] = null;
184
-            } else {
185
-                $this->_model_relations[$relation_name] = array();
186
-            }
187
-        }
188
-        /**
189
-         * Action done at the end of each model object construction
190
-         *
191
-         * @param EE_Base_Class $this the model object just created
192
-         */
193
-        do_action('AHEE__EE_Base_Class__construct__finished', $this);
194
-    }
195
-
196
-
197
-
198
-    /**
199
-     * Gets whether or not this model object is allowed to persist/be saved to the database.
200
-     *
201
-     * @return boolean
202
-     */
203
-    public function allow_persist()
204
-    {
205
-        return $this->_allow_persist;
206
-    }
207
-
208
-
209
-
210
-    /**
211
-     * Sets whether or not this model object should be allowed to be saved to the DB.
212
-     * Normally once this is set to FALSE you wouldn't set it back to TRUE, unless
213
-     * you got new information that somehow made you change your mind.
214
-     *
215
-     * @param boolean $allow_persist
216
-     * @return boolean
217
-     */
218
-    public function set_allow_persist($allow_persist)
219
-    {
220
-        return $this->_allow_persist = $allow_persist;
221
-    }
222
-
223
-
224
-
225
-    /**
226
-     * Gets the field's original value when this object was constructed during this request.
227
-     * This can be helpful when determining if a model object has changed or not
228
-     *
229
-     * @param string $field_name
230
-     * @return mixed|null
231
-     * @throws \EE_Error
232
-     */
233
-    public function get_original($field_name)
234
-    {
235
-        if (isset($this->_props_n_values_provided_in_constructor[$field_name])
236
-            && $field_settings = $this->get_model()->field_settings_for($field_name)
237
-        ) {
238
-            return $field_settings->prepare_for_get($this->_props_n_values_provided_in_constructor[$field_name]);
239
-        } else {
240
-            return null;
241
-        }
242
-    }
243
-
244
-
245
-
246
-    /**
247
-     * @param EE_Base_Class $obj
248
-     * @return string
249
-     */
250
-    public function get_class($obj)
251
-    {
252
-        return get_class($obj);
253
-    }
254
-
255
-
256
-
257
-    /**
258
-     * Overrides parent because parent expects old models.
259
-     * This also doesn't do any validation, and won't work for serialized arrays
260
-     *
261
-     * @param    string $field_name
262
-     * @param    mixed  $field_value
263
-     * @param bool      $use_default
264
-     * @throws \EE_Error
265
-     */
266
-    public function set($field_name, $field_value, $use_default = false)
267
-    {
268
-        // if not using default and nothing has changed, and object has already been setup (has ID),
269
-        // then don't do anything
270
-        if (
271
-            ! $use_default
272
-            && $this->_fields[$field_name] === $field_value
273
-            && $this->ID()
274
-        ) {
275
-            return;
276
-        }
277
-        $model = $this->get_model();
278
-        $this->_has_changes = true;
279
-        $field_obj = $model->field_settings_for($field_name);
280
-        if ($field_obj instanceof EE_Model_Field_Base) {
281
-            //			if ( method_exists( $field_obj, 'set_timezone' )) {
282
-            if ($field_obj instanceof EE_Datetime_Field) {
283
-                $field_obj->set_timezone($this->_timezone);
284
-                $field_obj->set_date_format($this->_dt_frmt);
285
-                $field_obj->set_time_format($this->_tm_frmt);
286
-            }
287
-            $holder_of_value = $field_obj->prepare_for_set($field_value);
288
-            //should the value be null?
289
-            if (($field_value === null || $holder_of_value === null || $holder_of_value === '') && $use_default) {
290
-                $this->_fields[$field_name] = $field_obj->get_default_value();
291
-                /**
292
-                 * To save having to refactor all the models, if a default value is used for a
293
-                 * EE_Datetime_Field, and that value is not null nor is it a DateTime
294
-                 * object.  Then let's do a set again to ensure that it becomes a DateTime
295
-                 * object.
296
-                 *
297
-                 * @since 4.6.10+
298
-                 */
299
-                if (
300
-                    $field_obj instanceof EE_Datetime_Field
301
-                    && $this->_fields[$field_name] !== null
302
-                    && ! $this->_fields[$field_name] instanceof DateTime
303
-                ) {
304
-                    empty($this->_fields[$field_name])
305
-                        ? $this->set($field_name, time())
306
-                        : $this->set($field_name, $this->_fields[$field_name]);
307
-                }
308
-            } else {
309
-                $this->_fields[$field_name] = $holder_of_value;
310
-            }
311
-            //if we're not in the constructor...
312
-            //now check if what we set was a primary key
313
-            if (
314
-                //note: props_n_values_provided_in_constructor is only set at the END of the constructor
315
-                $this->_props_n_values_provided_in_constructor
316
-                && $field_value
317
-                && $field_name === $model->primary_key_name()
318
-            ) {
319
-                //if so, we want all this object's fields to be filled either with
320
-                //what we've explicitly set on this model
321
-                //or what we have in the db
322
-                // echo "setting primary key!";
323
-                $fields_on_model = self::_get_model(get_class($this))->field_settings();
324
-                $obj_in_db = self::_get_model(get_class($this))->get_one_by_ID($field_value);
325
-                foreach ($fields_on_model as $field_obj) {
326
-                    if ( ! array_key_exists($field_obj->get_name(), $this->_props_n_values_provided_in_constructor)
327
-                         && $field_obj->get_name() !== $field_name
328
-                    ) {
329
-                        $this->set($field_obj->get_name(), $obj_in_db->get($field_obj->get_name()));
330
-                    }
331
-                }
332
-                //oh this model object has an ID? well make sure its in the entity mapper
333
-                $model->add_to_entity_map($this);
334
-            }
335
-            //let's unset any cache for this field_name from the $_cached_properties property.
336
-            $this->_clear_cached_property($field_name);
337
-        } else {
338
-            throw new EE_Error(sprintf(__("A valid EE_Model_Field_Base could not be found for the given field name: %s",
339
-                "event_espresso"), $field_name));
340
-        }
341
-    }
342
-
343
-
344
-
345
-    /**
346
-     * This sets the field value on the db column if it exists for the given $column_name or
347
-     * saves it to EE_Extra_Meta if the given $column_name does not match a db column.
348
-     *
349
-     * @see EE_message::get_column_value for related documentation on the necessity of this method.
350
-     * @param string $field_name  Must be the exact column name.
351
-     * @param mixed  $field_value The value to set.
352
-     * @return int|bool @see EE_Base_Class::update_extra_meta() for return docs.
353
-     * @throws \EE_Error
354
-     */
355
-    public function set_field_or_extra_meta($field_name, $field_value)
356
-    {
357
-        if ($this->get_model()->has_field($field_name)) {
358
-            $this->set($field_name, $field_value);
359
-            return true;
360
-        } else {
361
-            //ensure this object is saved first so that extra meta can be properly related.
362
-            $this->save();
363
-            return $this->update_extra_meta($field_name, $field_value);
364
-        }
365
-    }
366
-
367
-
368
-
369
-    /**
370
-     * This retrieves the value of the db column set on this class or if that's not present
371
-     * it will attempt to retrieve from extra_meta if found.
372
-     * Example Usage:
373
-     * Via EE_Message child class:
374
-     * Due to the dynamic nature of the EE_messages system, EE_messengers will always have a "to",
375
-     * "from", "subject", and "content" field (as represented in the EE_Message schema), however they may
376
-     * also have additional main fields specific to the messenger.  The system accommodates those extra
377
-     * fields through the EE_Extra_Meta table.  This method allows for EE_messengers to retrieve the
378
-     * value for those extra fields dynamically via the EE_message object.
379
-     *
380
-     * @param  string $field_name expecting the fully qualified field name.
381
-     * @return mixed|null  value for the field if found.  null if not found.
382
-     * @throws \EE_Error
383
-     */
384
-    public function get_field_or_extra_meta($field_name)
385
-    {
386
-        if ($this->get_model()->has_field($field_name)) {
387
-            $column_value = $this->get($field_name);
388
-        } else {
389
-            //This isn't a column in the main table, let's see if it is in the extra meta.
390
-            $column_value = $this->get_extra_meta($field_name, true, null);
391
-        }
392
-        return $column_value;
393
-    }
394
-
395
-
396
-
397
-    /**
398
-     * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
399
-     * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
400
-     * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). This is
401
-     * available to all child classes that may be using the EE_Datetime_Field for a field data type.
402
-     *
403
-     * @access public
404
-     * @param string $timezone A valid timezone string as described by @link http://www.php.net/manual/en/timezones.php
405
-     * @return void
406
-     * @throws \EE_Error
407
-     */
408
-    public function set_timezone($timezone = '')
409
-    {
410
-        $this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
411
-        //make sure we clear all cached properties because they won't be relevant now
412
-        $this->_clear_cached_properties();
413
-        //make sure we update field settings and the date for all EE_Datetime_Fields
414
-        $model_fields = $this->get_model()->field_settings(false);
415
-        foreach ($model_fields as $field_name => $field_obj) {
416
-            if ($field_obj instanceof EE_Datetime_Field) {
417
-                $field_obj->set_timezone($this->_timezone);
418
-                if (isset($this->_fields[$field_name]) && $this->_fields[$field_name] instanceof DateTime) {
419
-                    $this->_fields[$field_name]->setTimezone(new DateTimeZone($this->_timezone));
420
-                }
421
-            }
422
-        }
423
-    }
424
-
425
-
426
-
427
-    /**
428
-     * This just returns whatever is set for the current timezone.
429
-     *
430
-     * @access public
431
-     * @return string timezone string
432
-     */
433
-    public function get_timezone()
434
-    {
435
-        return $this->_timezone;
436
-    }
437
-
438
-
439
-
440
-    /**
441
-     * This sets the internal date format to what is sent in to be used as the new default for the class
442
-     * internally instead of wp set date format options
443
-     *
444
-     * @since 4.6
445
-     * @param string $format should be a format recognizable by PHP date() functions.
446
-     */
447
-    public function set_date_format($format)
448
-    {
449
-        $this->_dt_frmt = $format;
450
-        //clear cached_properties because they won't be relevant now.
451
-        $this->_clear_cached_properties();
452
-    }
453
-
454
-
455
-
456
-    /**
457
-     * This sets the internal time format string to what is sent in to be used as the new default for the
458
-     * class internally instead of wp set time format options.
459
-     *
460
-     * @since 4.6
461
-     * @param string $format should be a format recognizable by PHP date() functions.
462
-     */
463
-    public function set_time_format($format)
464
-    {
465
-        $this->_tm_frmt = $format;
466
-        //clear cached_properties because they won't be relevant now.
467
-        $this->_clear_cached_properties();
468
-    }
469
-
470
-
471
-
472
-    /**
473
-     * This returns the current internal set format for the date and time formats.
474
-     *
475
-     * @param bool $full           if true (default), then return the full format.  Otherwise will return an array
476
-     *                             where the first value is the date format and the second value is the time format.
477
-     * @return mixed string|array
478
-     */
479
-    public function get_format($full = true)
480
-    {
481
-        return $full ? $this->_dt_frmt . ' ' . $this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
482
-    }
483
-
484
-
485
-
486
-    /**
487
-     * cache
488
-     * stores the passed model object on the current model object.
489
-     * In certain circumstances, we can use this cached model object instead of querying for another one entirely.
490
-     *
491
-     * @param string        $relationName    one of the keys in the _model_relations array on the model. Eg
492
-     *                                       'Registration' associated with this model object
493
-     * @param EE_Base_Class $object_to_cache that has a relation to this model object. (Eg, if this is a Transaction,
494
-     *                                       that could be a payment or a registration)
495
-     * @param null          $cache_id        a string or number that will be used as the key for any Belongs_To_Many
496
-     *                                       items which will be stored in an array on this object
497
-     * @throws EE_Error
498
-     * @return mixed    index into cache, or just TRUE if the relation is of type Belongs_To (because there's only one
499
-     *                  related thing, no array)
500
-     */
501
-    public function cache($relationName = '', $object_to_cache = null, $cache_id = null)
502
-    {
503
-        // its entirely possible that there IS no related object yet in which case there is nothing to cache.
504
-        if ( ! $object_to_cache instanceof EE_Base_Class) {
505
-            return false;
506
-        }
507
-        // also get "how" the object is related, or throw an error
508
-        if ( ! $relationship_to_model = $this->get_model()->related_settings_for($relationName)) {
509
-            throw new EE_Error(sprintf(__('There is no relationship to %s on a %s. Cannot cache it', 'event_espresso'),
510
-                $relationName, get_class($this)));
511
-        }
512
-        // how many things are related ?
513
-        if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
514
-            // if it's a "belongs to" relationship, then there's only one related model object  eg, if this is a registration, there's only 1 attendee for it
515
-            // so for these model objects just set it to be cached
516
-            $this->_model_relations[$relationName] = $object_to_cache;
517
-            $return = true;
518
-        } else {
519
-            // otherwise, this is the "many" side of a one to many relationship, so we'll add the object to the array of related objects for that type.
520
-            // eg: if this is an event, there are many registrations for that event, so we cache the registrations in an array
521
-            if ( ! is_array($this->_model_relations[$relationName])) {
522
-                // if for some reason, the cached item is a model object, then stick that in the array, otherwise start with an empty array
523
-                $this->_model_relations[$relationName] = $this->_model_relations[$relationName] instanceof EE_Base_Class
524
-                    ? array($this->_model_relations[$relationName]) : array();
525
-            }
526
-            // first check for a cache_id which is normally empty
527
-            if ( ! empty($cache_id)) {
528
-                // if the cache_id exists, then it means we are purposely trying to cache this with a known key that can then be used to retrieve the object later on
529
-                $this->_model_relations[$relationName][$cache_id] = $object_to_cache;
530
-                $return = $cache_id;
531
-            } elseif ($object_to_cache->ID()) {
532
-                // OR the cached object originally came from the db, so let's just use it's PK for an ID
533
-                $this->_model_relations[$relationName][$object_to_cache->ID()] = $object_to_cache;
534
-                $return = $object_to_cache->ID();
535
-            } else {
536
-                // OR it's a new object with no ID, so just throw it in the array with an auto-incremented ID
537
-                $this->_model_relations[$relationName][] = $object_to_cache;
538
-                // move the internal pointer to the end of the array
539
-                end($this->_model_relations[$relationName]);
540
-                // and grab the key so that we can return it
541
-                $return = key($this->_model_relations[$relationName]);
542
-            }
543
-        }
544
-        return $return;
545
-    }
546
-
547
-
548
-
549
-    /**
550
-     * For adding an item to the cached_properties property.
551
-     *
552
-     * @access protected
553
-     * @param string      $fieldname the property item the corresponding value is for.
554
-     * @param mixed       $value     The value we are caching.
555
-     * @param string|null $cache_type
556
-     * @return void
557
-     * @throws \EE_Error
558
-     */
559
-    protected function _set_cached_property($fieldname, $value, $cache_type = null)
560
-    {
561
-        //first make sure this property exists
562
-        $this->get_model()->field_settings_for($fieldname);
563
-        $cache_type = empty($cache_type) ? 'standard' : $cache_type;
564
-        $this->_cached_properties[$fieldname][$cache_type] = $value;
565
-    }
566
-
567
-
568
-
569
-    /**
570
-     * This returns the value cached property if it exists OR the actual property value if the cache doesn't exist.
571
-     * This also SETS the cache if we return the actual property!
572
-     *
573
-     * @param string $fieldname        the name of the property we're trying to retrieve
574
-     * @param bool   $pretty
575
-     * @param string $extra_cache_ref  This allows the user to specify an extra cache ref for the given property
576
-     *                                 (in cases where the same property may be used for different outputs
577
-     *                                 - i.e. datetime, money etc.)
578
-     *                                 It can also accept certain pre-defined "schema" strings
579
-     *                                 to define how to output the property.
580
-     *                                 see the field's prepare_for_pretty_echoing for what strings can be used
581
-     * @return mixed                   whatever the value for the property is we're retrieving
582
-     * @throws \EE_Error
583
-     */
584
-    protected function _get_cached_property($fieldname, $pretty = false, $extra_cache_ref = null)
585
-    {
586
-        //verify the field exists
587
-        $model = $this->get_model();
588
-        $model->field_settings_for($fieldname);
589
-        $cache_type = $pretty ? 'pretty' : 'standard';
590
-        $cache_type .= ! empty($extra_cache_ref) ? '_' . $extra_cache_ref : '';
591
-        if (isset($this->_cached_properties[$fieldname][$cache_type])) {
592
-            return $this->_cached_properties[$fieldname][$cache_type];
593
-        }
594
-        $value = $this->_get_fresh_property($fieldname, $pretty, $extra_cache_ref);
595
-        $this->_set_cached_property($fieldname, $value, $cache_type);
596
-        return $value;
597
-    }
598
-
599
-
600
-
601
-    /**
602
-     * If the cache didn't fetch the needed item, this fetches it.
603
-     * @param string $fieldname
604
-     * @param bool $pretty
605
-     * @param string $extra_cache_ref
606
-     * @return mixed
607
-     */
608
-    protected function _get_fresh_property($fieldname, $pretty = false, $extra_cache_ref = null)
609
-    {
610
-        $field_obj = $this->get_model()->field_settings_for($fieldname);
611
-        // If this is an EE_Datetime_Field we need to make sure timezone, formats, and output are correct
612
-        if ($field_obj instanceof EE_Datetime_Field) {
613
-            $this->_prepare_datetime_field($field_obj, $pretty, $extra_cache_ref);
614
-        }
615
-        if ( ! isset($this->_fields[$fieldname])) {
616
-            $this->_fields[$fieldname] = null;
617
-        }
618
-        $value = $pretty
619
-            ? $field_obj->prepare_for_pretty_echoing($this->_fields[$fieldname], $extra_cache_ref)
620
-            : $field_obj->prepare_for_get($this->_fields[$fieldname]);
621
-        return $value;
622
-    }
623
-
624
-
625
-
626
-    /**
627
-     * set timezone, formats, and output for EE_Datetime_Field objects
628
-     *
629
-     * @param \EE_Datetime_Field $datetime_field
630
-     * @param bool               $pretty
631
-     * @param null $date_or_time
632
-     * @return void
633
-     * @throws \EE_Error
634
-     */
635
-    protected function _prepare_datetime_field(
636
-        EE_Datetime_Field $datetime_field,
637
-        $pretty = false,
638
-        $date_or_time = null
639
-    ) {
640
-        $datetime_field->set_timezone($this->_timezone);
641
-        $datetime_field->set_date_format($this->_dt_frmt, $pretty);
642
-        $datetime_field->set_time_format($this->_tm_frmt, $pretty);
643
-        //set the output returned
644
-        switch ($date_or_time) {
645
-            case 'D' :
646
-                $datetime_field->set_date_time_output('date');
647
-                break;
648
-            case 'T' :
649
-                $datetime_field->set_date_time_output('time');
650
-                break;
651
-            default :
652
-                $datetime_field->set_date_time_output();
653
-        }
654
-    }
655
-
656
-
657
-
658
-    /**
659
-     * This just takes care of clearing out the cached_properties
660
-     *
661
-     * @return void
662
-     */
663
-    protected function _clear_cached_properties()
664
-    {
665
-        $this->_cached_properties = array();
666
-    }
667
-
668
-
669
-
670
-    /**
671
-     * This just clears out ONE property if it exists in the cache
672
-     *
673
-     * @param  string $property_name the property to remove if it exists (from the _cached_properties array)
674
-     * @return void
675
-     */
676
-    protected function _clear_cached_property($property_name)
677
-    {
678
-        if (isset($this->_cached_properties[$property_name])) {
679
-            unset($this->_cached_properties[$property_name]);
680
-        }
681
-    }
682
-
683
-
684
-
685
-    /**
686
-     * Ensures that this related thing is a model object.
687
-     *
688
-     * @param mixed  $object_or_id EE_base_Class/int/string either a related model object, or its ID
689
-     * @param string $model_name   name of the related thing, eg 'Attendee',
690
-     * @return EE_Base_Class
691
-     * @throws \EE_Error
692
-     */
693
-    protected function ensure_related_thing_is_model_obj($object_or_id, $model_name)
694
-    {
695
-        $other_model_instance = self::_get_model_instance_with_name(
696
-            self::_get_model_classname($model_name),
697
-            $this->_timezone
698
-        );
699
-        return $other_model_instance->ensure_is_obj($object_or_id);
700
-    }
701
-
702
-
703
-
704
-    /**
705
-     * Forgets the cached model of the given relation Name. So the next time we request it,
706
-     * we will fetch it again from the database. (Handy if you know it's changed somehow).
707
-     * If a specific object is supplied, and the relationship to it is either a HasMany or HABTM,
708
-     * then only remove that one object from our cached array. Otherwise, clear the entire list
709
-     *
710
-     * @param string $relationName                         one of the keys in the _model_relations array on the model.
711
-     *                                                     Eg 'Registration'
712
-     * @param mixed  $object_to_remove_or_index_into_array or an index into the array of cached things, or NULL
713
-     *                                                     if you intend to use $clear_all = TRUE, or the relation only
714
-     *                                                     has 1 object anyways (ie, it's a BelongsToRelation)
715
-     * @param bool   $clear_all                            This flags clearing the entire cache relation property if
716
-     *                                                     this is HasMany or HABTM.
717
-     * @throws EE_Error
718
-     * @return EE_Base_Class | boolean from which was cleared from the cache, or true if we requested to remove a
719
-     *                       relation from all
720
-     */
721
-    public function clear_cache($relationName, $object_to_remove_or_index_into_array = null, $clear_all = false)
722
-    {
723
-        $relationship_to_model = $this->get_model()->related_settings_for($relationName);
724
-        $index_in_cache = '';
725
-        if ( ! $relationship_to_model) {
726
-            throw new EE_Error(
727
-                sprintf(
728
-                    __("There is no relationship to %s on a %s. Cannot clear that cache", 'event_espresso'),
729
-                    $relationName,
730
-                    get_class($this)
731
-                )
732
-            );
733
-        }
734
-        if ($clear_all) {
735
-            $obj_removed = true;
736
-            $this->_model_relations[$relationName] = null;
737
-        } elseif ($relationship_to_model instanceof EE_Belongs_To_Relation) {
738
-            $obj_removed = $this->_model_relations[$relationName];
739
-            $this->_model_relations[$relationName] = null;
740
-        } else {
741
-            if ($object_to_remove_or_index_into_array instanceof EE_Base_Class
742
-                && $object_to_remove_or_index_into_array->ID()
743
-            ) {
744
-                $index_in_cache = $object_to_remove_or_index_into_array->ID();
745
-                if (is_array($this->_model_relations[$relationName])
746
-                    && ! isset($this->_model_relations[$relationName][$index_in_cache])
747
-                ) {
748
-                    $index_found_at = null;
749
-                    //find this object in the array even though it has a different key
750
-                    foreach ($this->_model_relations[$relationName] as $index => $obj) {
751
-                        if (
752
-                            $obj instanceof EE_Base_Class
753
-                            && (
754
-                                $obj == $object_to_remove_or_index_into_array
755
-                                || $obj->ID() === $object_to_remove_or_index_into_array->ID()
756
-                            )
757
-                        ) {
758
-                            $index_found_at = $index;
759
-                            break;
760
-                        }
761
-                    }
762
-                    if ($index_found_at) {
763
-                        $index_in_cache = $index_found_at;
764
-                    } else {
765
-                        //it wasn't found. huh. well obviously it doesn't need to be removed from teh cache
766
-                        //if it wasn't in it to begin with. So we're done
767
-                        return $object_to_remove_or_index_into_array;
768
-                    }
769
-                }
770
-            } elseif ($object_to_remove_or_index_into_array instanceof EE_Base_Class) {
771
-                //so they provided a model object, but it's not yet saved to the DB... so let's go hunting for it!
772
-                foreach ($this->get_all_from_cache($relationName) as $index => $potentially_obj_we_want) {
773
-                    if ($potentially_obj_we_want == $object_to_remove_or_index_into_array) {
774
-                        $index_in_cache = $index;
775
-                    }
776
-                }
777
-            } else {
778
-                $index_in_cache = $object_to_remove_or_index_into_array;
779
-            }
780
-            //supposedly we've found it. But it could just be that the client code
781
-            //provided a bad index/object
782
-            if (
783
-            isset(
784
-                $this->_model_relations[$relationName],
785
-                $this->_model_relations[$relationName][$index_in_cache]
786
-            )
787
-            ) {
788
-                $obj_removed = $this->_model_relations[$relationName][$index_in_cache];
789
-                unset($this->_model_relations[$relationName][$index_in_cache]);
790
-            } else {
791
-                //that thing was never cached anyways.
792
-                $obj_removed = null;
793
-            }
794
-        }
795
-        return $obj_removed;
796
-    }
797
-
798
-
799
-
800
-    /**
801
-     * update_cache_after_object_save
802
-     * Allows a cached item to have it's cache ID (within the array of cached items) reset using the new ID it has
803
-     * obtained after being saved to the db
804
-     *
805
-     * @param string         $relationName       - the type of object that is cached
806
-     * @param \EE_Base_Class $newly_saved_object - the newly saved object to be re-cached
807
-     * @param string         $current_cache_id   - the ID that was used when originally caching the object
808
-     * @return boolean TRUE on success, FALSE on fail
809
-     * @throws \EE_Error
810
-     */
811
-    public function update_cache_after_object_save(
812
-        $relationName,
813
-        EE_Base_Class $newly_saved_object,
814
-        $current_cache_id = ''
815
-    ) {
816
-        // verify that incoming object is of the correct type
817
-        $obj_class = 'EE_' . $relationName;
818
-        if ($newly_saved_object instanceof $obj_class) {
819
-            /* @type EE_Base_Class $newly_saved_object */
820
-            // now get the type of relation
821
-            $relationship_to_model = $this->get_model()->related_settings_for($relationName);
822
-            // if this is a 1:1 relationship
823
-            if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
824
-                // then just replace the cached object with the newly saved object
825
-                $this->_model_relations[$relationName] = $newly_saved_object;
826
-                return true;
827
-                // or if it's some kind of sordid feral polyamorous relationship...
828
-            } elseif (is_array($this->_model_relations[$relationName])
829
-                      && isset($this->_model_relations[$relationName][$current_cache_id])
830
-            ) {
831
-                // then remove the current cached item
832
-                unset($this->_model_relations[$relationName][$current_cache_id]);
833
-                // and cache the newly saved object using it's new ID
834
-                $this->_model_relations[$relationName][$newly_saved_object->ID()] = $newly_saved_object;
835
-                return true;
836
-            }
837
-        }
838
-        return false;
839
-    }
840
-
841
-
842
-
843
-    /**
844
-     * Fetches a single EE_Base_Class on that relation. (If the relation is of type
845
-     * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
846
-     *
847
-     * @param string $relationName
848
-     * @return EE_Base_Class
849
-     */
850
-    public function get_one_from_cache($relationName)
851
-    {
852
-        $cached_array_or_object = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName]
853
-            : null;
854
-        if (is_array($cached_array_or_object)) {
855
-            return array_shift($cached_array_or_object);
856
-        } else {
857
-            return $cached_array_or_object;
858
-        }
859
-    }
860
-
861
-
862
-
863
-    /**
864
-     * Fetches a single EE_Base_Class on that relation. (If the relation is of type
865
-     * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
866
-     *
867
-     * @param string $relationName
868
-     * @throws \EE_Error
869
-     * @return EE_Base_Class[] NOT necessarily indexed by primary keys
870
-     */
871
-    public function get_all_from_cache($relationName)
872
-    {
873
-        $objects = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : array();
874
-        // if the result is not an array, but exists, make it an array
875
-        $objects = is_array($objects) ? $objects : array($objects);
876
-        //bugfix for https://events.codebasehq.com/projects/event-espresso/tickets/7143
877
-        //basically, if this model object was stored in the session, and these cached model objects
878
-        //already have IDs, let's make sure they're in their model's entity mapper
879
-        //otherwise we will have duplicates next time we call
880
-        // EE_Registry::instance()->load_model( $relationName )->get_one_by_ID( $result->ID() );
881
-        $model = EE_Registry::instance()->load_model($relationName);
882
-        foreach ($objects as $model_object) {
883
-            if ($model instanceof EEM_Base && $model_object instanceof EE_Base_Class) {
884
-                //ensure its in the map if it has an ID; otherwise it will be added to the map when its saved
885
-                if ($model_object->ID()) {
886
-                    $model->add_to_entity_map($model_object);
887
-                }
888
-            } else {
889
-                throw new EE_Error(
890
-                    sprintf(
891
-                        __(
892
-                            'Error retrieving related model objects. Either $1%s is not a model or $2%s is not a model object',
893
-                            'event_espresso'
894
-                        ),
895
-                        $relationName,
896
-                        gettype($model_object)
897
-                    )
898
-                );
899
-            }
900
-        }
901
-        return $objects;
902
-    }
903
-
904
-
905
-
906
-    /**
907
-     * Returns the next x number of EE_Base_Class objects in sequence from this object as found in the database
908
-     * matching the given query conditions.
909
-     *
910
-     * @param null  $field_to_order_by  What field is being used as the reference point.
911
-     * @param int   $limit              How many objects to return.
912
-     * @param array $query_params       Any additional conditions on the query.
913
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
914
-     *                                  you can indicate just the columns you want returned
915
-     * @return array|EE_Base_Class[]
916
-     * @throws \EE_Error
917
-     */
918
-    public function next_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
919
-    {
920
-        $model = $this->get_model();
921
-        $field = empty($field_to_order_by) && $model->has_primary_key_field()
922
-            ? $model->get_primary_key_field()->get_name()
923
-            : $field_to_order_by;
924
-        $current_value = ! empty($field) ? $this->get($field) : null;
925
-        if (empty($field) || empty($current_value)) {
926
-            return array();
927
-        }
928
-        return $model->next_x($current_value, $field, $limit, $query_params, $columns_to_select);
929
-    }
930
-
931
-
932
-
933
-    /**
934
-     * Returns the previous x number of EE_Base_Class objects in sequence from this object as found in the database
935
-     * matching the given query conditions.
936
-     *
937
-     * @param null  $field_to_order_by  What field is being used as the reference point.
938
-     * @param int   $limit              How many objects to return.
939
-     * @param array $query_params       Any additional conditions on the query.
940
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
941
-     *                                  you can indicate just the columns you want returned
942
-     * @return array|EE_Base_Class[]
943
-     * @throws \EE_Error
944
-     */
945
-    public function previous_x(
946
-        $field_to_order_by = null,
947
-        $limit = 1,
948
-        $query_params = array(),
949
-        $columns_to_select = null
950
-    ) {
951
-        $model = $this->get_model();
952
-        $field = empty($field_to_order_by) && $model->has_primary_key_field()
953
-            ? $model->get_primary_key_field()->get_name()
954
-            : $field_to_order_by;
955
-        $current_value = ! empty($field) ? $this->get($field) : null;
956
-        if (empty($field) || empty($current_value)) {
957
-            return array();
958
-        }
959
-        return $model->previous_x($current_value, $field, $limit, $query_params, $columns_to_select);
960
-    }
961
-
962
-
963
-
964
-    /**
965
-     * Returns the next EE_Base_Class object in sequence from this object as found in the database
966
-     * matching the given query conditions.
967
-     *
968
-     * @param null  $field_to_order_by  What field is being used as the reference point.
969
-     * @param array $query_params       Any additional conditions on the query.
970
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
971
-     *                                  you can indicate just the columns you want returned
972
-     * @return array|EE_Base_Class
973
-     * @throws \EE_Error
974
-     */
975
-    public function next($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
976
-    {
977
-        $model = $this->get_model();
978
-        $field = empty($field_to_order_by) && $model->has_primary_key_field()
979
-            ? $model->get_primary_key_field()->get_name()
980
-            : $field_to_order_by;
981
-        $current_value = ! empty($field) ? $this->get($field) : null;
982
-        if (empty($field) || empty($current_value)) {
983
-            return array();
984
-        }
985
-        return $model->next($current_value, $field, $query_params, $columns_to_select);
986
-    }
987
-
988
-
989
-
990
-    /**
991
-     * Returns the previous EE_Base_Class object in sequence from this object as found in the database
992
-     * matching the given query conditions.
993
-     *
994
-     * @param null  $field_to_order_by  What field is being used as the reference point.
995
-     * @param array $query_params       Any additional conditions on the query.
996
-     * @param null  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
997
-     *                                  you can indicate just the column you want returned
998
-     * @return array|EE_Base_Class
999
-     * @throws \EE_Error
1000
-     */
1001
-    public function previous($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
1002
-    {
1003
-        $model = $this->get_model();
1004
-        $field = empty($field_to_order_by) && $model->has_primary_key_field()
1005
-            ? $model->get_primary_key_field()->get_name()
1006
-            : $field_to_order_by;
1007
-        $current_value = ! empty($field) ? $this->get($field) : null;
1008
-        if (empty($field) || empty($current_value)) {
1009
-            return array();
1010
-        }
1011
-        return $model->previous($current_value, $field, $query_params, $columns_to_select);
1012
-    }
1013
-
1014
-
1015
-
1016
-    /**
1017
-     * Overrides parent because parent expects old models.
1018
-     * This also doesn't do any validation, and won't work for serialized arrays
1019
-     *
1020
-     * @param string $field_name
1021
-     * @param mixed  $field_value_from_db
1022
-     * @throws \EE_Error
1023
-     */
1024
-    public function set_from_db($field_name, $field_value_from_db)
1025
-    {
1026
-        $field_obj = $this->get_model()->field_settings_for($field_name);
1027
-        if ($field_obj instanceof EE_Model_Field_Base) {
1028
-            //you would think the DB has no NULLs for non-null label fields right? wrong!
1029
-            //eg, a CPT model object could have an entry in the posts table, but no
1030
-            //entry in the meta table. Meaning that all its columns in the meta table
1031
-            //are null! yikes! so when we find one like that, use defaults for its meta columns
1032
-            if ($field_value_from_db === null) {
1033
-                if ($field_obj->is_nullable()) {
1034
-                    //if the field allows nulls, then let it be null
1035
-                    $field_value = null;
1036
-                } else {
1037
-                    $field_value = $field_obj->get_default_value();
1038
-                }
1039
-            } else {
1040
-                $field_value = $field_obj->prepare_for_set_from_db($field_value_from_db);
1041
-            }
1042
-            $this->_fields[$field_name] = $field_value;
1043
-            $this->_clear_cached_property($field_name);
1044
-        }
1045
-    }
1046
-
1047
-
1048
-
1049
-    /**
1050
-     * verifies that the specified field is of the correct type
1051
-     *
1052
-     * @param string $field_name
1053
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1054
-     *                                (in cases where the same property may be used for different outputs
1055
-     *                                - i.e. datetime, money etc.)
1056
-     * @return mixed
1057
-     * @throws \EE_Error
1058
-     */
1059
-    public function get($field_name, $extra_cache_ref = null)
1060
-    {
1061
-        return $this->_get_cached_property($field_name, false, $extra_cache_ref);
1062
-    }
1063
-
1064
-
1065
-
1066
-    /**
1067
-     * This method simply returns the RAW unprocessed value for the given property in this class
1068
-     *
1069
-     * @param  string $field_name A valid fieldname
1070
-     * @return mixed              Whatever the raw value stored on the property is.
1071
-     * @throws EE_Error if fieldSettings is misconfigured or the field doesn't exist.
1072
-     */
1073
-    public function get_raw($field_name)
1074
-    {
1075
-        $field_settings = $this->get_model()->field_settings_for($field_name);
1076
-        return $field_settings instanceof EE_Datetime_Field && $this->_fields[$field_name] instanceof DateTime
1077
-            ? $this->_fields[$field_name]->format('U')
1078
-            : $this->_fields[$field_name];
1079
-    }
1080
-
1081
-
1082
-
1083
-    /**
1084
-     * This is used to return the internal DateTime object used for a field that is a
1085
-     * EE_Datetime_Field.
1086
-     *
1087
-     * @param string $field_name               The field name retrieving the DateTime object.
1088
-     * @return mixed null | false | DateTime  If the requested field is NOT a EE_Datetime_Field then
1089
-     * @throws \EE_Error
1090
-     *                                         an error is set and false returned.  If the field IS an
1091
-     *                                         EE_Datetime_Field and but the field value is null, then
1092
-     *                                         just null is returned (because that indicates that likely
1093
-     *                                         this field is nullable).
1094
-     */
1095
-    public function get_DateTime_object($field_name)
1096
-    {
1097
-        $field_settings = $this->get_model()->field_settings_for($field_name);
1098
-        if ( ! $field_settings instanceof EE_Datetime_Field) {
1099
-            EE_Error::add_error(
1100
-                sprintf(
1101
-                    __(
1102
-                        'The field %s is not an EE_Datetime_Field field.  There is no DateTime object stored on this field type.',
1103
-                        'event_espresso'
1104
-                    ),
1105
-                    $field_name
1106
-                ),
1107
-                __FILE__,
1108
-                __FUNCTION__,
1109
-                __LINE__
1110
-            );
1111
-            return false;
1112
-        }
1113
-        return $this->_fields[$field_name];
1114
-    }
1115
-
1116
-
1117
-
1118
-    /**
1119
-     * To be used in template to immediately echo out the value, and format it for output.
1120
-     * Eg, should call stripslashes and whatnot before echoing
1121
-     *
1122
-     * @param string $field_name      the name of the field as it appears in the DB
1123
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1124
-     *                                (in cases where the same property may be used for different outputs
1125
-     *                                - i.e. datetime, money etc.)
1126
-     * @return void
1127
-     * @throws \EE_Error
1128
-     */
1129
-    public function e($field_name, $extra_cache_ref = null)
1130
-    {
1131
-        echo $this->get_pretty($field_name, $extra_cache_ref);
1132
-    }
1133
-
1134
-
1135
-
1136
-    /**
1137
-     * Exactly like e(), echoes out the field, but sets its schema to 'form_input', so that it
1138
-     * can be easily used as the value of form input.
1139
-     *
1140
-     * @param string $field_name
1141
-     * @return void
1142
-     * @throws \EE_Error
1143
-     */
1144
-    public function f($field_name)
1145
-    {
1146
-        $this->e($field_name, 'form_input');
1147
-    }
1148
-
1149
-
1150
-
1151
-    /**
1152
-     * Gets a pretty view of the field's value. $extra_cache_ref can specify different formats for this.
1153
-     * The $extra_cache_ref will be passed to the model field's prepare_for_pretty_echoing, so consult the field's class
1154
-     * to see what options are available.
1155
-     * @param string $field_name
1156
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1157
-     *                                (in cases where the same property may be used for different outputs
1158
-     *                                - i.e. datetime, money etc.)
1159
-     * @return mixed
1160
-     * @throws \EE_Error
1161
-     */
1162
-    public function get_pretty($field_name, $extra_cache_ref = null)
1163
-    {
1164
-        return $this->_get_cached_property($field_name, true, $extra_cache_ref);
1165
-    }
1166
-
1167
-
1168
-
1169
-    /**
1170
-     * This simply returns the datetime for the given field name
1171
-     * Note: this protected function is called by the wrapper get_date or get_time or get_datetime functions
1172
-     * (and the equivalent e_date, e_time, e_datetime).
1173
-     *
1174
-     * @access   protected
1175
-     * @param string   $field_name   Field on the instantiated EE_Base_Class child object
1176
-     * @param string   $dt_frmt      valid datetime format used for date
1177
-     *                               (if '' then we just use the default on the field,
1178
-     *                               if NULL we use the last-used format)
1179
-     * @param string   $tm_frmt      Same as above except this is for time format
1180
-     * @param string   $date_or_time if NULL then both are returned, otherwise "D" = only date and "T" = only time.
1181
-     * @param  boolean $echo         Whether the dtt is echoing using pretty echoing or just returned using vanilla get
1182
-     * @return string|bool|EE_Error string on success, FALSE on fail, or EE_Error Exception is thrown
1183
-     *                               if field is not a valid dtt field, or void if echoing
1184
-     * @throws \EE_Error
1185
-     */
1186
-    protected function _get_datetime($field_name, $dt_frmt = '', $tm_frmt = '', $date_or_time = '', $echo = false)
1187
-    {
1188
-        // clear cached property
1189
-        $this->_clear_cached_property($field_name);
1190
-        //reset format properties because they are used in get()
1191
-        $this->_dt_frmt = $dt_frmt !== '' ? $dt_frmt : $this->_dt_frmt;
1192
-        $this->_tm_frmt = $tm_frmt !== '' ? $tm_frmt : $this->_tm_frmt;
1193
-        if ($echo) {
1194
-            $this->e($field_name, $date_or_time);
1195
-            return '';
1196
-        }
1197
-        return $this->get($field_name, $date_or_time);
1198
-    }
1199
-
1200
-
1201
-
1202
-    /**
1203
-     * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the date
1204
-     * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1205
-     * other echoes the pretty value for dtt)
1206
-     *
1207
-     * @param  string $field_name name of model object datetime field holding the value
1208
-     * @param  string $format     format for the date returned (if NULL we use default in dt_frmt property)
1209
-     * @return string            datetime value formatted
1210
-     * @throws \EE_Error
1211
-     */
1212
-    public function get_date($field_name, $format = '')
1213
-    {
1214
-        return $this->_get_datetime($field_name, $format, null, 'D');
1215
-    }
1216
-
1217
-
1218
-
1219
-    /**
1220
-     * @param      $field_name
1221
-     * @param string $format
1222
-     * @throws \EE_Error
1223
-     */
1224
-    public function e_date($field_name, $format = '')
1225
-    {
1226
-        $this->_get_datetime($field_name, $format, null, 'D', true);
1227
-    }
1228
-
1229
-
1230
-
1231
-    /**
1232
-     * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the time
1233
-     * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1234
-     * other echoes the pretty value for dtt)
1235
-     *
1236
-     * @param  string $field_name name of model object datetime field holding the value
1237
-     * @param  string $format     format for the time returned ( if NULL we use default in tm_frmt property)
1238
-     * @return string             datetime value formatted
1239
-     * @throws \EE_Error
1240
-     */
1241
-    public function get_time($field_name, $format = '')
1242
-    {
1243
-        return $this->_get_datetime($field_name, null, $format, 'T');
1244
-    }
1245
-
1246
-
1247
-
1248
-    /**
1249
-     * @param      $field_name
1250
-     * @param string $format
1251
-     * @throws \EE_Error
1252
-     */
1253
-    public function e_time($field_name, $format = '')
1254
-    {
1255
-        $this->_get_datetime($field_name, null, $format, 'T', true);
1256
-    }
1257
-
1258
-
1259
-
1260
-    /**
1261
-     * below are wrapper functions for the various datetime outputs that can be obtained for returning the date AND
1262
-     * time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1263
-     * other echoes the pretty value for dtt)
1264
-     *
1265
-     * @param  string $field_name name of model object datetime field holding the value
1266
-     * @param  string $dt_frmt    format for the date returned (if NULL we use default in dt_frmt property)
1267
-     * @param  string $tm_frmt    format for the time returned (if NULL we use default in tm_frmt property)
1268
-     * @return string             datetime value formatted
1269
-     * @throws \EE_Error
1270
-     */
1271
-    public function get_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1272
-    {
1273
-        return $this->_get_datetime($field_name, $dt_frmt, $tm_frmt);
1274
-    }
1275
-
1276
-
1277
-
1278
-    /**
1279
-     * @param string $field_name
1280
-     * @param string $dt_frmt
1281
-     * @param string $tm_frmt
1282
-     * @throws \EE_Error
1283
-     */
1284
-    public function e_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1285
-    {
1286
-        $this->_get_datetime($field_name, $dt_frmt, $tm_frmt, null, true);
1287
-    }
1288
-
1289
-
1290
-
1291
-    /**
1292
-     * Get the i8ln value for a date using the WordPress @see date_i18n function.
1293
-     *
1294
-     * @param string $field_name The EE_Datetime_Field reference for the date being retrieved.
1295
-     * @param string $format     PHP valid date/time string format.  If none is provided then the internal set format
1296
-     *                           on the object will be used.
1297
-     * @return string Date and time string in set locale or false if no field exists for the given
1298
-     * @throws \EE_Error
1299
-     *                           field name.
1300
-     */
1301
-    public function get_i18n_datetime($field_name, $format = '')
1302
-    {
1303
-        $format = empty($format) ? $this->_dt_frmt . ' ' . $this->_tm_frmt : $format;
1304
-        return date_i18n(
1305
-            $format,
1306
-            EEH_DTT_Helper::get_timestamp_with_offset($this->get_raw($field_name), $this->_timezone)
1307
-        );
1308
-    }
1309
-
1310
-
1311
-
1312
-    /**
1313
-     * This method validates whether the given field name is a valid field on the model object as well as it is of a
1314
-     * type EE_Datetime_Field.  On success there will be returned the field settings.  On fail an EE_Error exception is
1315
-     * thrown.
1316
-     *
1317
-     * @param  string $field_name The field name being checked
1318
-     * @throws EE_Error
1319
-     * @return EE_Datetime_Field
1320
-     */
1321
-    protected function _get_dtt_field_settings($field_name)
1322
-    {
1323
-        $field = $this->get_model()->field_settings_for($field_name);
1324
-        //check if field is dtt
1325
-        if ($field instanceof EE_Datetime_Field) {
1326
-            return $field;
1327
-        } else {
1328
-            throw new EE_Error(sprintf(__('The field name "%s" has been requested for the EE_Base_Class datetime functions and it is not a valid EE_Datetime_Field.  Please check the spelling of the field and make sure it has been setup as a EE_Datetime_Field in the %s model constructor',
1329
-                'event_espresso'), $field_name, self::_get_model_classname(get_class($this))));
1330
-        }
1331
-    }
1332
-
1333
-
1334
-
1335
-
1336
-    /**
1337
-     * NOTE ABOUT BELOW:
1338
-     * These convenience date and time setters are for setting date and time independently.  In other words you might
1339
-     * want to change the time on a datetime_field but leave the date the same (or vice versa). IF on the other hand
1340
-     * you want to set both date and time at the same time, you can just use the models default set($fieldname,$value)
1341
-     * method and make sure you send the entire datetime value for setting.
1342
-     */
1343
-    /**
1344
-     * sets the time on a datetime property
1345
-     *
1346
-     * @access protected
1347
-     * @param string|Datetime $time      a valid time string for php datetime functions (or DateTime object)
1348
-     * @param string          $fieldname the name of the field the time is being set on (must match a EE_Datetime_Field)
1349
-     * @throws \EE_Error
1350
-     */
1351
-    protected function _set_time_for($time, $fieldname)
1352
-    {
1353
-        $this->_set_date_time('T', $time, $fieldname);
1354
-    }
1355
-
1356
-
1357
-
1358
-    /**
1359
-     * sets the date on a datetime property
1360
-     *
1361
-     * @access protected
1362
-     * @param string|DateTime $date      a valid date string for php datetime functions ( or DateTime object)
1363
-     * @param string          $fieldname the name of the field the date is being set on (must match a EE_Datetime_Field)
1364
-     * @throws \EE_Error
1365
-     */
1366
-    protected function _set_date_for($date, $fieldname)
1367
-    {
1368
-        $this->_set_date_time('D', $date, $fieldname);
1369
-    }
1370
-
1371
-
1372
-
1373
-    /**
1374
-     * This takes care of setting a date or time independently on a given model object property. This method also
1375
-     * verifies that the given fieldname matches a model object property and is for a EE_Datetime_Field field
1376
-     *
1377
-     * @access protected
1378
-     * @param string          $what           "T" for time, 'B' for both, 'D' for Date.
1379
-     * @param string|DateTime $datetime_value A valid Date or Time string (or DateTime object)
1380
-     * @param string          $fieldname      the name of the field the date OR time is being set on (must match a
1381
-     *                                        EE_Datetime_Field property)
1382
-     * @throws \EE_Error
1383
-     */
1384
-    protected function _set_date_time($what = 'T', $datetime_value, $fieldname)
1385
-    {
1386
-        $field = $this->_get_dtt_field_settings($fieldname);
1387
-        $field->set_timezone($this->_timezone);
1388
-        $field->set_date_format($this->_dt_frmt);
1389
-        $field->set_time_format($this->_tm_frmt);
1390
-        switch ($what) {
1391
-            case 'T' :
1392
-                $this->_fields[$fieldname] = $field->prepare_for_set_with_new_time(
1393
-                    $datetime_value,
1394
-                    $this->_fields[$fieldname]
1395
-                );
1396
-                break;
1397
-            case 'D' :
1398
-                $this->_fields[$fieldname] = $field->prepare_for_set_with_new_date(
1399
-                    $datetime_value,
1400
-                    $this->_fields[$fieldname]
1401
-                );
1402
-                break;
1403
-            case 'B' :
1404
-                $this->_fields[$fieldname] = $field->prepare_for_set($datetime_value);
1405
-                break;
1406
-        }
1407
-        $this->_clear_cached_property($fieldname);
1408
-    }
1409
-
1410
-
1411
-
1412
-    /**
1413
-     * This will return a timestamp for the website timezone but ONLY when the current website timezone is different
1414
-     * than the timezone set for the website. NOTE, this currently only works well with methods that return values.  If
1415
-     * you use it with methods that echo values the $_timestamp property may not get reset to its original value and
1416
-     * that could lead to some unexpected results!
1417
-     *
1418
-     * @access public
1419
-     * @param string               $field_name This is the name of the field on the object that contains the date/time
1420
-     *                                         value being returned.
1421
-     * @param string               $callback   must match a valid method in this class (defaults to get_datetime)
1422
-     * @param mixed (array|string) $args       This is the arguments that will be passed to the callback.
1423
-     * @param string               $prepend    You can include something to prepend on the timestamp
1424
-     * @param string               $append     You can include something to append on the timestamp
1425
-     * @throws EE_Error
1426
-     * @return string timestamp
1427
-     */
1428
-    public function display_in_my_timezone(
1429
-        $field_name,
1430
-        $callback = 'get_datetime',
1431
-        $args = null,
1432
-        $prepend = '',
1433
-        $append = ''
1434
-    ) {
1435
-        $timezone = EEH_DTT_Helper::get_timezone();
1436
-        if ($timezone === $this->_timezone) {
1437
-            return '';
1438
-        }
1439
-        $original_timezone = $this->_timezone;
1440
-        $this->set_timezone($timezone);
1441
-        $fn = (array)$field_name;
1442
-        $args = array_merge($fn, (array)$args);
1443
-        if ( ! method_exists($this, $callback)) {
1444
-            throw new EE_Error(
1445
-                sprintf(
1446
-                    __(
1447
-                        'The method named "%s" given as the callback param in "display_in_my_timezone" does not exist.  Please check your spelling',
1448
-                        'event_espresso'
1449
-                    ),
1450
-                    $callback
1451
-                )
1452
-            );
1453
-        }
1454
-        $args = (array)$args;
1455
-        $return = $prepend . call_user_func_array(array($this, $callback), $args) . $append;
1456
-        $this->set_timezone($original_timezone);
1457
-        return $return;
1458
-    }
1459
-
1460
-
1461
-
1462
-    /**
1463
-     * Deletes this model object.
1464
-     * This calls the `EE_Base_Class::_delete` method.  Child classes wishing to change default behaviour should
1465
-     * override
1466
-     * `EE_Base_Class::_delete` NOT this class.
1467
-     *
1468
-     * @return boolean | int
1469
-     * @throws \EE_Error
1470
-     */
1471
-    public function delete()
1472
-    {
1473
-        /**
1474
-         * Called just before the `EE_Base_Class::_delete` method call.
1475
-         * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1476
-         * should be aware that `_delete` may not always result in a permanent delete.  For example, `EE_Soft_Delete_Base_Class::_delete`
1477
-         * soft deletes (trash) the object and does not permanently delete it.
1478
-         *
1479
-         * @param EE_Base_Class $model_object about to be 'deleted'
1480
-         */
1481
-        do_action('AHEE__EE_Base_Class__delete__before', $this);
1482
-        $result = $this->_delete();
1483
-        /**
1484
-         * Called just after the `EE_Base_Class::_delete` method call.
1485
-         * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1486
-         * should be aware that `_delete` may not always result in a permanent delete.  For example `EE_Soft_Base_Class::_delete`
1487
-         * soft deletes (trash) the object and does not permanently delete it.
1488
-         *
1489
-         * @param EE_Base_Class $model_object that was just 'deleted'
1490
-         * @param boolean       $result
1491
-         */
1492
-        do_action('AHEE__EE_Base_Class__delete__end', $this, $result);
1493
-        return $result;
1494
-    }
1495
-
1496
-
1497
-
1498
-    /**
1499
-     * Calls the specific delete method for the instantiated class.
1500
-     * This method is called by the public `EE_Base_Class::delete` method.  Any child classes desiring to override
1501
-     * default functionality for "delete" (which is to call `permanently_delete`) should override this method NOT
1502
-     * `EE_Base_Class::delete`
1503
-     *
1504
-     * @return bool|int
1505
-     * @throws \EE_Error
1506
-     */
1507
-    protected function _delete()
1508
-    {
1509
-        return $this->delete_permanently();
1510
-    }
1511
-
1512
-
1513
-
1514
-    /**
1515
-     * Deletes this model object permanently from db (but keep in mind related models my block the delete and return an
1516
-     * error)
1517
-     *
1518
-     * @return bool | int
1519
-     * @throws \EE_Error
1520
-     */
1521
-    public function delete_permanently()
1522
-    {
1523
-        /**
1524
-         * Called just before HARD deleting a model object
1525
-         *
1526
-         * @param EE_Base_Class $model_object about to be 'deleted'
1527
-         */
1528
-        do_action('AHEE__EE_Base_Class__delete_permanently__before', $this);
1529
-        $model = $this->get_model();
1530
-        $result = $model->delete_permanently_by_ID($this->ID());
1531
-        $this->refresh_cache_of_related_objects();
1532
-        /**
1533
-         * Called just after HARD deleting a model object
1534
-         *
1535
-         * @param EE_Base_Class $model_object that was just 'deleted'
1536
-         * @param boolean       $result
1537
-         */
1538
-        do_action('AHEE__EE_Base_Class__delete_permanently__end', $this, $result);
1539
-        return $result;
1540
-    }
1541
-
1542
-
1543
-
1544
-    /**
1545
-     * When this model object is deleted, it may still be cached on related model objects. This clears the cache of
1546
-     * related model objects
1547
-     *
1548
-     * @throws \EE_Error
1549
-     */
1550
-    public function refresh_cache_of_related_objects()
1551
-    {
1552
-        $model = $this->get_model();
1553
-        foreach ($model->relation_settings() as $relation_name => $relation_obj) {
1554
-            if ( ! empty($this->_model_relations[$relation_name])) {
1555
-                $related_objects = $this->_model_relations[$relation_name];
1556
-                if ($relation_obj instanceof EE_Belongs_To_Relation) {
1557
-                    //this relation only stores a single model object, not an array
1558
-                    //but let's make it consistent
1559
-                    $related_objects = array($related_objects);
1560
-                }
1561
-                foreach ($related_objects as $related_object) {
1562
-                    //only refresh their cache if they're in memory
1563
-                    if ($related_object instanceof EE_Base_Class) {
1564
-                        $related_object->clear_cache($model->get_this_model_name(), $this);
1565
-                    }
1566
-                }
1567
-            }
1568
-        }
1569
-    }
1570
-
1571
-
1572
-
1573
-    /**
1574
-     *        Saves this object to the database. An array may be supplied to set some values on this
1575
-     * object just before saving.
1576
-     *
1577
-     * @access public
1578
-     * @param array $set_cols_n_values keys are field names, values are their new values,
1579
-     *                                 if provided during the save() method (often client code will change the fields'
1580
-     *                                 values before calling save)
1581
-     * @throws \EE_Error
1582
-     * @return int , 1 on a successful update, the ID of the new entry on insert; 0 on failure or if the model object
1583
-     *                                 isn't allowed to persist (as determined by EE_Base_Class::allow_persist())
1584
-     */
1585
-    public function save($set_cols_n_values = array())
1586
-    {
1587
-        $model = $this->get_model();
1588
-        /**
1589
-         * Filters the fields we're about to save on the model object
1590
-         *
1591
-         * @param array         $set_cols_n_values
1592
-         * @param EE_Base_Class $model_object
1593
-         */
1594
-        $set_cols_n_values = (array)apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values,
1595
-            $this);
1596
-        //set attributes as provided in $set_cols_n_values
1597
-        foreach ($set_cols_n_values as $column => $value) {
1598
-            $this->set($column, $value);
1599
-        }
1600
-        // no changes ? then don't do anything
1601
-        if (! $this->_has_changes && $this->ID() && $model->get_primary_key_field()->is_auto_increment()) {
1602
-            return 0;
1603
-        }
1604
-        /**
1605
-         * Saving a model object.
1606
-         * Before we perform a save, this action is fired.
1607
-         *
1608
-         * @param EE_Base_Class $model_object the model object about to be saved.
1609
-         */
1610
-        do_action('AHEE__EE_Base_Class__save__begin', $this);
1611
-        if ( ! $this->allow_persist()) {
1612
-            return 0;
1613
-        }
1614
-        //now get current attribute values
1615
-        $save_cols_n_values = $this->_fields;
1616
-        //if the object already has an ID, update it. Otherwise, insert it
1617
-        //also: change the assumption about values passed to the model NOT being prepare dby the model object. They have been
1618
-        $old_assumption_concerning_value_preparation = $model
1619
-                                                            ->get_assumption_concerning_values_already_prepared_by_model_object();
1620
-        $model->assume_values_already_prepared_by_model_object(true);
1621
-        //does this model have an autoincrement PK?
1622
-        if ($model->has_primary_key_field()) {
1623
-            if ($model->get_primary_key_field()->is_auto_increment()) {
1624
-                //ok check if it's set, if so: update; if not, insert
1625
-                if ( ! empty($save_cols_n_values[$model->primary_key_name()])) {
1626
-                    $results = $model->update_by_ID($save_cols_n_values, $this->ID());
1627
-                } else {
1628
-                    unset($save_cols_n_values[$model->primary_key_name()]);
1629
-                    $results = $model->insert($save_cols_n_values);
1630
-                    if ($results) {
1631
-                        //if successful, set the primary key
1632
-                        //but don't use the normal SET method, because it will check if
1633
-                        //an item with the same ID exists in the mapper & db, then
1634
-                        //will find it in the db (because we just added it) and THAT object
1635
-                        //will get added to the mapper before we can add this one!
1636
-                        //but if we just avoid using the SET method, all that headache can be avoided
1637
-                        $pk_field_name = $model->primary_key_name();
1638
-                        $this->_fields[$pk_field_name] = $results;
1639
-                        $this->_clear_cached_property($pk_field_name);
1640
-                        $model->add_to_entity_map($this);
1641
-                        $this->_update_cached_related_model_objs_fks();
1642
-                    }
1643
-                }
1644
-            } else {//PK is NOT auto-increment
1645
-                //so check if one like it already exists in the db
1646
-                if ($model->exists_by_ID($this->ID())) {
1647
-                    if (WP_DEBUG && ! $this->in_entity_map()) {
1648
-                        throw new EE_Error(
1649
-                            sprintf(
1650
-                                __('Using a model object %1$s that is NOT in the entity map, can lead to unexpected errors. You should either: %4$s 1. Put it in the entity mapper by calling %2$s %4$s 2. Discard this model object and use what is in the entity mapper %4$s 3. Fetch from the database using %3$s',
1651
-                                    'event_espresso'),
1652
-                                get_class($this),
1653
-                                get_class($model) . '::instance()->add_to_entity_map()',
1654
-                                get_class($model) . '::instance()->get_one_by_ID()',
1655
-                                '<br />'
1656
-                            )
1657
-                        );
1658
-                    }
1659
-                    $results = $model->update_by_ID($save_cols_n_values, $this->ID());
1660
-                } else {
1661
-                    $results = $model->insert($save_cols_n_values);
1662
-                    $this->_update_cached_related_model_objs_fks();
1663
-                }
1664
-            }
1665
-        } else {//there is NO primary key
1666
-            $already_in_db = false;
1667
-            foreach ($model->unique_indexes() as $index) {
1668
-                $uniqueness_where_params = array_intersect_key($save_cols_n_values, $index->fields());
1669
-                if ($model->exists(array($uniqueness_where_params))) {
1670
-                    $already_in_db = true;
1671
-                }
1672
-            }
1673
-            if ($already_in_db) {
1674
-                $combined_pk_fields_n_values = array_intersect_key($save_cols_n_values,
1675
-                    $model->get_combined_primary_key_fields());
1676
-                $results = $model->update($save_cols_n_values, $combined_pk_fields_n_values);
1677
-            } else {
1678
-                $results = $model->insert($save_cols_n_values);
1679
-            }
1680
-        }
1681
-        //restore the old assumption about values being prepared by the model object
1682
-        $model
1683
-             ->assume_values_already_prepared_by_model_object($old_assumption_concerning_value_preparation);
1684
-        /**
1685
-         * After saving the model object this action is called
1686
-         *
1687
-         * @param EE_Base_Class $model_object which was just saved
1688
-         * @param boolean|int   $results      if it were updated, TRUE or FALSE; if it were newly inserted
1689
-         *                                    the new ID (or 0 if an error occurred and it wasn't updated)
1690
-         */
1691
-        do_action('AHEE__EE_Base_Class__save__end', $this, $results);
1692
-        $this->_has_changes = false;
1693
-        return $results;
1694
-    }
1695
-
1696
-
1697
-
1698
-    /**
1699
-     * Updates the foreign key on related models objects pointing to this to have this model object's ID
1700
-     * as their foreign key.  If the cached related model objects already exist in the db, saves them (so that the DB
1701
-     * is consistent) Especially useful in case we JUST added this model object ot the database and we want to let its
1702
-     * cached relations with foreign keys to it know about that change. Eg: we've created a transaction but haven't
1703
-     * saved it to the db. We also create a registration and don't save it to the DB, but we DO cache it on the
1704
-     * transaction. Now, when we save the transaction, the registration's TXN_ID will be automatically updated, whether
1705
-     * or not they exist in the DB (if they do, their DB records will be automatically updated)
1706
-     *
1707
-     * @return void
1708
-     * @throws \EE_Error
1709
-     */
1710
-    protected function _update_cached_related_model_objs_fks()
1711
-    {
1712
-        $model = $this->get_model();
1713
-        foreach ($model->relation_settings() as $relation_name => $relation_obj) {
1714
-            if ($relation_obj instanceof EE_Has_Many_Relation) {
1715
-                foreach ($this->get_all_from_cache($relation_name) as $related_model_obj_in_cache) {
1716
-                    $fk_to_this = $related_model_obj_in_cache->get_model()->get_foreign_key_to(
1717
-                        $model->get_this_model_name()
1718
-                    );
1719
-                    $related_model_obj_in_cache->set($fk_to_this->get_name(), $this->ID());
1720
-                    if ($related_model_obj_in_cache->ID()) {
1721
-                        $related_model_obj_in_cache->save();
1722
-                    }
1723
-                }
1724
-            }
1725
-        }
1726
-    }
1727
-
1728
-
1729
-
1730
-    /**
1731
-     * Saves this model object and its NEW cached relations to the database.
1732
-     * (Meaning, for now, IT DOES NOT WORK if the cached items already exist in the DB.
1733
-     * In order for that to work, we would need to mark model objects as dirty/clean...
1734
-     * because otherwise, there's a potential for infinite looping of saving
1735
-     * Saves the cached related model objects, and ensures the relation between them
1736
-     * and this object and properly setup
1737
-     *
1738
-     * @return int ID of new model object on save; 0 on failure+
1739
-     * @throws \EE_Error
1740
-     */
1741
-    public function save_new_cached_related_model_objs()
1742
-    {
1743
-        //make sure this has been saved
1744
-        if ( ! $this->ID()) {
1745
-            $id = $this->save();
1746
-        } else {
1747
-            $id = $this->ID();
1748
-        }
1749
-        //now save all the NEW cached model objects  (ie they don't exist in the DB)
1750
-        foreach ($this->get_model()->relation_settings() as $relationName => $relationObj) {
1751
-            if ($this->_model_relations[$relationName]) {
1752
-                //is this a relation where we should expect just ONE related object (ie, EE_Belongs_To_relation)
1753
-                //or MANY related objects (ie, EE_HABTM_Relation or EE_Has_Many_Relation)?
1754
-                if ($relationObj instanceof EE_Belongs_To_Relation) {
1755
-                    //add a relation to that relation type (which saves the appropriate thing in the process)
1756
-                    //but ONLY if it DOES NOT exist in the DB
1757
-                    /* @var $related_model_obj EE_Base_Class */
1758
-                    $related_model_obj = $this->_model_relations[$relationName];
1759
-                    //					if( ! $related_model_obj->ID()){
1760
-                    $this->_add_relation_to($related_model_obj, $relationName);
1761
-                    $related_model_obj->save_new_cached_related_model_objs();
1762
-                    //					}
1763
-                } else {
1764
-                    foreach ($this->_model_relations[$relationName] as $related_model_obj) {
1765
-                        //add a relation to that relation type (which saves the appropriate thing in the process)
1766
-                        //but ONLY if it DOES NOT exist in the DB
1767
-                        //						if( ! $related_model_obj->ID()){
1768
-                        $this->_add_relation_to($related_model_obj, $relationName);
1769
-                        $related_model_obj->save_new_cached_related_model_objs();
1770
-                        //						}
1771
-                    }
1772
-                }
1773
-            }
1774
-        }
1775
-        return $id;
1776
-    }
1777
-
1778
-
1779
-
1780
-    /**
1781
-     * for getting a model while instantiated.
1782
-     *
1783
-     * @return \EEM_Base | \EEM_CPT_Base
1784
-     */
1785
-    public function get_model()
1786
-    {
1787
-        if( ! $this->_model){
1788
-            $modelName = self::_get_model_classname(get_class($this));
1789
-            $this->_model = self::_get_model_instance_with_name($modelName, $this->_timezone);
1790
-        } else {
1791
-            $this->_model->set_timezone($this->_timezone);
1792
-        }
1793
-
1794
-        return $this->_model;
1795
-    }
1796
-
1797
-
1798
-
1799
-    /**
1800
-     * @param $props_n_values
1801
-     * @param $classname
1802
-     * @return mixed bool|EE_Base_Class|EEM_CPT_Base
1803
-     * @throws \EE_Error
1804
-     */
1805
-    protected static function _get_object_from_entity_mapper($props_n_values, $classname)
1806
-    {
1807
-        //TODO: will not work for Term_Relationships because they have no PK!
1808
-        $primary_id_ref = self::_get_primary_key_name($classname);
1809
-        if (array_key_exists($primary_id_ref, $props_n_values) && ! empty($props_n_values[$primary_id_ref])) {
1810
-            $id = $props_n_values[$primary_id_ref];
1811
-            return self::_get_model($classname)->get_from_entity_map($id);
1812
-        }
1813
-        return false;
1814
-    }
1815
-
1816
-
1817
-
1818
-    /**
1819
-     * This is called by child static "new_instance" method and we'll check to see if there is an existing db entry for
1820
-     * the primary key (if present in incoming values). If there is a key in the incoming array that matches the
1821
-     * primary key for the model AND it is not null, then we check the db. If there's a an object we return it.  If not
1822
-     * we return false.
1823
-     *
1824
-     * @param  array  $props_n_values   incoming array of properties and their values
1825
-     * @param  string $classname        the classname of the child class
1826
-     * @param null    $timezone
1827
-     * @param array   $date_formats     incoming date_formats in an array where the first value is the
1828
-     *                                  date_format and the second value is the time format
1829
-     * @return mixed (EE_Base_Class|bool)
1830
-     * @throws \EE_Error
1831
-     */
1832
-    protected static function _check_for_object($props_n_values, $classname, $timezone = null, $date_formats = array())
1833
-    {
1834
-        $existing = null;
1835
-        $model = self::_get_model($classname, $timezone);
1836
-        if ($model->has_primary_key_field()) {
1837
-            $primary_id_ref = self::_get_primary_key_name($classname);
1838
-            if (array_key_exists($primary_id_ref, $props_n_values)
1839
-                && ! empty($props_n_values[$primary_id_ref])
1840
-            ) {
1841
-                $existing = $model->get_one_by_ID(
1842
-                    $props_n_values[$primary_id_ref]
1843
-                );
1844
-            }
1845
-        } elseif ($model->has_all_combined_primary_key_fields($props_n_values)) {
1846
-            //no primary key on this model, but there's still a matching item in the DB
1847
-            $existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1848
-                self::_get_model($classname, $timezone)->get_index_primary_key_string($props_n_values)
1849
-            );
1850
-        }
1851
-        if ($existing) {
1852
-            //set date formats if present before setting values
1853
-            if ( ! empty($date_formats) && is_array($date_formats)) {
1854
-                $existing->set_date_format($date_formats[0]);
1855
-                $existing->set_time_format($date_formats[1]);
1856
-            } else {
1857
-                //set default formats for date and time
1858
-                $existing->set_date_format(get_option('date_format'));
1859
-                $existing->set_time_format(get_option('time_format'));
1860
-            }
1861
-            foreach ($props_n_values as $property => $field_value) {
1862
-                $existing->set($property, $field_value);
1863
-            }
1864
-            return $existing;
1865
-        } else {
1866
-            return false;
1867
-        }
1868
-    }
1869
-
1870
-
1871
-
1872
-    /**
1873
-     * Gets the EEM_*_Model for this class
1874
-     *
1875
-     * @access public now, as this is more convenient
1876
-     * @param      $classname
1877
-     * @param null $timezone
1878
-     * @throws EE_Error
1879
-     * @return EEM_Base
1880
-     */
1881
-    protected static function _get_model($classname, $timezone = null)
1882
-    {
1883
-        //find model for this class
1884
-        if ( ! $classname) {
1885
-            throw new EE_Error(
1886
-                sprintf(
1887
-                    __(
1888
-                        "What were you thinking calling _get_model(%s)?? You need to specify the class name",
1889
-                        "event_espresso"
1890
-                    ),
1891
-                    $classname
1892
-                )
1893
-            );
1894
-        }
1895
-        $modelName = self::_get_model_classname($classname);
1896
-        return self::_get_model_instance_with_name($modelName, $timezone);
1897
-    }
1898
-
1899
-
1900
-
1901
-    /**
1902
-     * Gets the model instance (eg instance of EEM_Attendee) given its classname (eg EE_Attendee)
1903
-     *
1904
-     * @param string $model_classname
1905
-     * @param null   $timezone
1906
-     * @return EEM_Base
1907
-     */
1908
-    protected static function _get_model_instance_with_name($model_classname, $timezone = null)
1909
-    {
1910
-        $model_classname = str_replace('EEM_', '', $model_classname);
1911
-        $model = EE_Registry::instance()->load_model($model_classname);
1912
-        $model->set_timezone($timezone);
1913
-        return $model;
1914
-    }
1915
-
1916
-
1917
-
1918
-    /**
1919
-     * If a model name is provided (eg Registration), gets the model classname for that model.
1920
-     * Also works if a model class's classname is provided (eg EE_Registration).
1921
-     *
1922
-     * @param null $model_name
1923
-     * @return string like EEM_Attendee
1924
-     */
1925
-    private static function _get_model_classname($model_name = null)
1926
-    {
1927
-        if (strpos($model_name, "EE_") === 0) {
1928
-            $model_classname = str_replace("EE_", "EEM_", $model_name);
1929
-        } else {
1930
-            $model_classname = "EEM_" . $model_name;
1931
-        }
1932
-        return $model_classname;
1933
-    }
1934
-
1935
-
1936
-
1937
-    /**
1938
-     * returns the name of the primary key attribute
1939
-     *
1940
-     * @param null $classname
1941
-     * @throws EE_Error
1942
-     * @return string
1943
-     */
1944
-    protected static function _get_primary_key_name($classname = null)
1945
-    {
1946
-        if ( ! $classname) {
1947
-            throw new EE_Error(
1948
-                sprintf(
1949
-                    __("What were you thinking calling _get_primary_key_name(%s)", "event_espresso"),
1950
-                    $classname
1951
-                )
1952
-            );
1953
-        }
1954
-        return self::_get_model($classname)->get_primary_key_field()->get_name();
1955
-    }
1956
-
1957
-
1958
-
1959
-    /**
1960
-     * Gets the value of the primary key.
1961
-     * If the object hasn't yet been saved, it should be whatever the model field's default was
1962
-     * (eg, if this were the EE_Event class, look at the primary key field on EEM_Event and see what its default value
1963
-     * is. Usually defaults for integer primary keys are 0; string primary keys are usually NULL).
1964
-     *
1965
-     * @return mixed, if the primary key is of type INT it'll be an int. Otherwise it could be a string
1966
-     * @throws \EE_Error
1967
-     */
1968
-    public function ID()
1969
-    {
1970
-        $model = $this->get_model();
1971
-        //now that we know the name of the variable, use a variable variable to get its value and return its
1972
-        if ($model->has_primary_key_field()) {
1973
-            return $this->_fields[$model->primary_key_name()];
1974
-        } else {
1975
-            return $model->get_index_primary_key_string($this->_fields);
1976
-        }
1977
-    }
1978
-
1979
-
1980
-
1981
-    /**
1982
-     * Adds a relationship to the specified EE_Base_Class object, given the relationship's name. Eg, if the current
1983
-     * model is related to a group of events, the $relationName should be 'Event', and should be a key in the EE
1984
-     * Model's $_model_relations array. If this model object doesn't exist in the DB, just caches the related thing
1985
-     *
1986
-     * @param mixed  $otherObjectModelObjectOrID       EE_Base_Class or the ID of the other object
1987
-     * @param string $relationName                     eg 'Events','Question',etc.
1988
-     *                                                 an attendee to a group, you also want to specify which role they
1989
-     *                                                 will have in that group. So you would use this parameter to
1990
-     *                                                 specify array('role-column-name'=>'role-id')
1991
-     * @param array  $extra_join_model_fields_n_values You can optionally include an array of key=>value pairs that
1992
-     *                                                 allow you to further constrict the relation to being added.
1993
-     *                                                 However, keep in mind that the columns (keys) given must match a
1994
-     *                                                 column on the JOIN table and currently only the HABTM models
1995
-     *                                                 accept these additional conditions.  Also remember that if an
1996
-     *                                                 exact match isn't found for these extra cols/val pairs, then a
1997
-     *                                                 NEW row is created in the join table.
1998
-     * @param null   $cache_id
1999
-     * @throws EE_Error
2000
-     * @return EE_Base_Class the object the relation was added to
2001
-     */
2002
-    public function _add_relation_to(
2003
-        $otherObjectModelObjectOrID,
2004
-        $relationName,
2005
-        $extra_join_model_fields_n_values = array(),
2006
-        $cache_id = null
2007
-    ) {
2008
-        $model = $this->get_model();
2009
-        //if this thing exists in the DB, save the relation to the DB
2010
-        if ($this->ID()) {
2011
-            $otherObject = $model
2012
-                                ->add_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
2013
-                                    $extra_join_model_fields_n_values);
2014
-            //clear cache so future get_many_related and get_first_related() return new results.
2015
-            $this->clear_cache($relationName, $otherObject, true);
2016
-            if ($otherObject instanceof EE_Base_Class) {
2017
-                $otherObject->clear_cache($model->get_this_model_name(), $this);
2018
-            }
2019
-        } else {
2020
-            //this thing doesn't exist in the DB,  so just cache it
2021
-            if ( ! $otherObjectModelObjectOrID instanceof EE_Base_Class) {
2022
-                throw new EE_Error(sprintf(
2023
-                    __('Before a model object is saved to the database, calls to _add_relation_to must be passed an actual object, not just an ID. You provided %s as the model object to a %s',
2024
-                        'event_espresso'),
2025
-                    $otherObjectModelObjectOrID,
2026
-                    get_class($this)
2027
-                ));
2028
-            } else {
2029
-                $otherObject = $otherObjectModelObjectOrID;
2030
-            }
2031
-            $this->cache($relationName, $otherObjectModelObjectOrID, $cache_id);
2032
-        }
2033
-        if ($otherObject instanceof EE_Base_Class) {
2034
-            //fix the reciprocal relation too
2035
-            if ($otherObject->ID()) {
2036
-                //its saved so assumed relations exist in the DB, so we can just
2037
-                //clear the cache so future queries use the updated info in the DB
2038
-                $otherObject->clear_cache($model->get_this_model_name(), null, true);
2039
-            } else {
2040
-                //it's not saved, so it caches relations like this
2041
-                $otherObject->cache($model->get_this_model_name(), $this);
2042
-            }
2043
-        }
2044
-        return $otherObject;
2045
-    }
2046
-
2047
-
2048
-
2049
-    /**
2050
-     * Removes a relationship to the specified EE_Base_Class object, given the relationships' name. Eg, if the current
2051
-     * model is related to a group of events, the $relationName should be 'Events', and should be a key in the EE
2052
-     * Model's $_model_relations array. If this model object doesn't exist in the DB, just removes the related thing
2053
-     * from the cache
2054
-     *
2055
-     * @param mixed  $otherObjectModelObjectOrID
2056
-     *                EE_Base_Class or the ID of the other object, OR an array key into the cache if this isn't saved
2057
-     *                to the DB yet
2058
-     * @param string $relationName
2059
-     * @param array  $where_query
2060
-     *                You can optionally include an array of key=>value pairs that allow you to further constrict the
2061
-     *                relation to being added. However, keep in mind that the columns (keys) given must match a column
2062
-     *                on the JOIN table and currently only the HABTM models accept these additional conditions. Also
2063
-     *                remember that if an exact match isn't found for these extra cols/val pairs, then a NEW row is
2064
-     *                created in the join table.
2065
-     * @return EE_Base_Class the relation was removed from
2066
-     * @throws \EE_Error
2067
-     */
2068
-    public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = array())
2069
-    {
2070
-        if ($this->ID()) {
2071
-            //if this exists in the DB, save the relation change to the DB too
2072
-            $otherObject = $this->get_model()
2073
-                                ->remove_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
2074
-                                    $where_query);
2075
-            $this->clear_cache($relationName, $otherObject);
2076
-        } else {
2077
-            //this doesn't exist in the DB, just remove it from the cache
2078
-            $otherObject = $this->clear_cache($relationName, $otherObjectModelObjectOrID);
2079
-        }
2080
-        if ($otherObject instanceof EE_Base_Class) {
2081
-            $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2082
-        }
2083
-        return $otherObject;
2084
-    }
2085
-
2086
-
2087
-
2088
-    /**
2089
-     * Removes ALL the related things for the $relationName.
2090
-     *
2091
-     * @param string $relationName
2092
-     * @param array  $where_query_params like EEM_Base::get_all's $query_params[0] (where conditions)
2093
-     * @return EE_Base_Class
2094
-     * @throws \EE_Error
2095
-     */
2096
-    public function _remove_relations($relationName, $where_query_params = array())
2097
-    {
2098
-        if ($this->ID()) {
2099
-            //if this exists in the DB, save the relation change to the DB too
2100
-            $otherObjects = $this->get_model()->remove_relations($this, $relationName, $where_query_params);
2101
-            $this->clear_cache($relationName, null, true);
2102
-        } else {
2103
-            //this doesn't exist in the DB, just remove it from the cache
2104
-            $otherObjects = $this->clear_cache($relationName, null, true);
2105
-        }
2106
-        if (is_array($otherObjects)) {
2107
-            foreach ($otherObjects as $otherObject) {
2108
-                $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2109
-            }
2110
-        }
2111
-        return $otherObjects;
2112
-    }
2113
-
2114
-
2115
-
2116
-    /**
2117
-     * Gets all the related model objects of the specified type. Eg, if the current class if
2118
-     * EE_Event, you could call $this->get_many_related('Registration') to get an array of all the
2119
-     * EE_Registration objects which related to this event. Note: by default, we remove the "default query params"
2120
-     * because we want to get even deleted items etc.
2121
-     *
2122
-     * @param string $relationName key in the model's _model_relations array
2123
-     * @param array  $query_params like EEM_Base::get_all
2124
-     * @return EE_Base_Class[] Results not necessarily indexed by IDs, because some results might not have primary keys
2125
-     * @throws \EE_Error
2126
-     *                             or might not be saved yet. Consider using EEM_Base::get_IDs() on these results if
2127
-     *                             you want IDs
2128
-     */
2129
-    public function get_many_related($relationName, $query_params = array())
2130
-    {
2131
-        if ($this->ID()) {
2132
-            //this exists in the DB, so get the related things from either the cache or the DB
2133
-            //if there are query parameters, forget about caching the related model objects.
2134
-            if ($query_params) {
2135
-                $related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2136
-            } else {
2137
-                //did we already cache the result of this query?
2138
-                $cached_results = $this->get_all_from_cache($relationName);
2139
-                if ( ! $cached_results) {
2140
-                    $related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2141
-                    //if no query parameters were passed, then we got all the related model objects
2142
-                    //for that relation. We can cache them then.
2143
-                    foreach ($related_model_objects as $related_model_object) {
2144
-                        $this->cache($relationName, $related_model_object);
2145
-                    }
2146
-                } else {
2147
-                    $related_model_objects = $cached_results;
2148
-                }
2149
-            }
2150
-        } else {
2151
-            //this doesn't exist in the DB, so just get the related things from the cache
2152
-            $related_model_objects = $this->get_all_from_cache($relationName);
2153
-        }
2154
-        return $related_model_objects;
2155
-    }
2156
-
2157
-
2158
-
2159
-    /**
2160
-     * Instead of getting the related model objects, simply counts them. Ignores default_where_conditions by default,
2161
-     * unless otherwise specified in the $query_params
2162
-     *
2163
-     * @param string $relation_name  model_name like 'Event', or 'Registration'
2164
-     * @param array  $query_params   like EEM_Base::get_all's
2165
-     * @param string $field_to_count name of field to count by. By default, uses primary key
2166
-     * @param bool   $distinct       if we want to only count the distinct values for the column then you can trigger
2167
-     *                               that by the setting $distinct to TRUE;
2168
-     * @return int
2169
-     */
2170
-    public function count_related($relation_name, $query_params = array(), $field_to_count = null, $distinct = false)
2171
-    {
2172
-        return $this->get_model()->count_related($this, $relation_name, $query_params, $field_to_count, $distinct);
2173
-    }
2174
-
2175
-
2176
-
2177
-    /**
2178
-     * Instead of getting the related model objects, simply sums up the values of the specified field.
2179
-     * Note: ignores default_where_conditions by default, unless otherwise specified in the $query_params
2180
-     *
2181
-     * @param string $relation_name model_name like 'Event', or 'Registration'
2182
-     * @param array  $query_params  like EEM_Base::get_all's
2183
-     * @param string $field_to_sum  name of field to count by.
2184
-     *                              By default, uses primary key (which doesn't make much sense, so you should probably
2185
-     *                              change it)
2186
-     * @return int
2187
-     */
2188
-    public function sum_related($relation_name, $query_params = array(), $field_to_sum = null)
2189
-    {
2190
-        return $this->get_model()->sum_related($this, $relation_name, $query_params, $field_to_sum);
2191
-    }
2192
-
2193
-
2194
-
2195
-    /**
2196
-     * Gets the first (ie, one) related model object of the specified type.
2197
-     *
2198
-     * @param string $relationName key in the model's _model_relations array
2199
-     * @param array  $query_params like EEM_Base::get_all
2200
-     * @return EE_Base_Class (not an array, a single object)
2201
-     * @throws \EE_Error
2202
-     */
2203
-    public function get_first_related($relationName, $query_params = array())
2204
-    {
2205
-        $model = $this->get_model();
2206
-        if ($this->ID()) {//this exists in the DB, get from the cache OR the DB
2207
-            //if they've provided some query parameters, don't bother trying to cache the result
2208
-            //also make sure we're not caching the result of get_first_related
2209
-            //on a relation which should have an array of objects (because the cache might have an array of objects)
2210
-            if ($query_params
2211
-                || ! $model->related_settings_for($relationName)
2212
-                     instanceof
2213
-                     EE_Belongs_To_Relation
2214
-            ) {
2215
-                $related_model_object = $model->get_first_related($this, $relationName, $query_params);
2216
-            } else {
2217
-                //first, check if we've already cached the result of this query
2218
-                $cached_result = $this->get_one_from_cache($relationName);
2219
-                if ( ! $cached_result) {
2220
-                    $related_model_object = $model->get_first_related($this, $relationName, $query_params);
2221
-                    $this->cache($relationName, $related_model_object);
2222
-                } else {
2223
-                    $related_model_object = $cached_result;
2224
-                }
2225
-            }
2226
-        } else {
2227
-            $related_model_object = null;
2228
-            //this doesn't exist in the Db, but maybe the relation is of type belongs to, and so the related thing might
2229
-            if ($model->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2230
-                $related_model_object = $model->get_first_related($this, $relationName, $query_params);
2231
-            }
2232
-            //this doesn't exist in the DB and apparently the thing it belongs to doesn't either, just get what's cached on this object
2233
-            if ( ! $related_model_object) {
2234
-                $related_model_object = $this->get_one_from_cache($relationName);
2235
-            }
2236
-        }
2237
-        return $related_model_object;
2238
-    }
2239
-
2240
-
2241
-
2242
-    /**
2243
-     * Does a delete on all related objects of type $relationName and removes
2244
-     * the current model object's relation to them. If they can't be deleted (because
2245
-     * of blocking related model objects) does nothing. If the related model objects are
2246
-     * soft-deletable, they will be soft-deleted regardless of related blocking model objects.
2247
-     * If this model object doesn't exist yet in the DB, just removes its related things
2248
-     *
2249
-     * @param string $relationName
2250
-     * @param array  $query_params like EEM_Base::get_all's
2251
-     * @return int how many deleted
2252
-     * @throws \EE_Error
2253
-     */
2254
-    public function delete_related($relationName, $query_params = array())
2255
-    {
2256
-        if ($this->ID()) {
2257
-            $count = $this->get_model()->delete_related($this, $relationName, $query_params);
2258
-        } else {
2259
-            $count = count($this->get_all_from_cache($relationName));
2260
-            $this->clear_cache($relationName, null, true);
2261
-        }
2262
-        return $count;
2263
-    }
2264
-
2265
-
2266
-
2267
-    /**
2268
-     * Does a hard delete (ie, removes the DB row) on all related objects of type $relationName and removes
2269
-     * the current model object's relation to them. If they can't be deleted (because
2270
-     * of blocking related model objects) just does a soft delete on it instead, if possible.
2271
-     * If the related thing isn't a soft-deletable model object, this function is identical
2272
-     * to delete_related(). If this model object doesn't exist in the DB, just remove its related things
2273
-     *
2274
-     * @param string $relationName
2275
-     * @param array  $query_params like EEM_Base::get_all's
2276
-     * @return int how many deleted (including those soft deleted)
2277
-     * @throws \EE_Error
2278
-     */
2279
-    public function delete_related_permanently($relationName, $query_params = array())
2280
-    {
2281
-        if ($this->ID()) {
2282
-            $count = $this->get_model()->delete_related_permanently($this, $relationName, $query_params);
2283
-        } else {
2284
-            $count = count($this->get_all_from_cache($relationName));
2285
-        }
2286
-        $this->clear_cache($relationName, null, true);
2287
-        return $count;
2288
-    }
2289
-
2290
-
2291
-
2292
-    /**
2293
-     * is_set
2294
-     * Just a simple utility function children can use for checking if property exists
2295
-     *
2296
-     * @access  public
2297
-     * @param  string $field_name property to check
2298
-     * @return bool                              TRUE if existing,FALSE if not.
2299
-     */
2300
-    public function is_set($field_name)
2301
-    {
2302
-        return isset($this->_fields[$field_name]);
2303
-    }
2304
-
2305
-
2306
-
2307
-    /**
2308
-     * Just a simple utility function children can use for checking if property (or properties) exists and throwing an
2309
-     * EE_Error exception if they don't
2310
-     *
2311
-     * @param  mixed (string|array) $properties properties to check
2312
-     * @throws EE_Error
2313
-     * @return bool                              TRUE if existing, throw EE_Error if not.
2314
-     */
2315
-    protected function _property_exists($properties)
2316
-    {
2317
-        foreach ((array)$properties as $property_name) {
2318
-            //first make sure this property exists
2319
-            if ( ! $this->_fields[$property_name]) {
2320
-                throw new EE_Error(
2321
-                    sprintf(
2322
-                        __(
2323
-                            'Trying to retrieve a non-existent property (%s).  Double check the spelling please',
2324
-                            'event_espresso'
2325
-                        ),
2326
-                        $property_name
2327
-                    )
2328
-                );
2329
-            }
2330
-        }
2331
-        return true;
2332
-    }
2333
-
2334
-
2335
-
2336
-    /**
2337
-     * This simply returns an array of model fields for this object
2338
-     *
2339
-     * @return array
2340
-     * @throws \EE_Error
2341
-     */
2342
-    public function model_field_array()
2343
-    {
2344
-        $fields = $this->get_model()->field_settings(false);
2345
-        $properties = array();
2346
-        //remove prepended underscore
2347
-        foreach ($fields as $field_name => $settings) {
2348
-            $properties[$field_name] = $this->get($field_name);
2349
-        }
2350
-        return $properties;
2351
-    }
2352
-
2353
-
2354
-
2355
-    /**
2356
-     * Very handy general function to allow for plugins to extend any child of EE_Base_Class.
2357
-     * If a method is called on a child of EE_Base_Class that doesn't exist, this function is called
2358
-     * (http://www.garfieldtech.com/blog/php-magic-call) and passed the method's name and arguments. Instead of
2359
-     * requiring a plugin to extend the EE_Base_Class (which works fine is there's only 1 plugin, but when will that
2360
-     * happen?) they can add a hook onto 'filters_hook_espresso__{className}__{methodName}' (eg,
2361
-     * filters_hook_espresso__EE_Answer__my_great_function) and accepts 2 arguments: the object on which the function
2362
-     * was called, and an array of the original arguments passed to the function. Whatever their callback function
2363
-     * returns will be returned by this function. Example: in functions.php (or in a plugin):
2364
-     * add_filter('FHEE__EE_Answer__my_callback','my_callback',10,3); function
2365
-     * my_callback($previousReturnValue,EE_Base_Class $object,$argsArray){
2366
-     * $returnString= "you called my_callback! and passed args:".implode(",",$argsArray);
2367
-     *        return $previousReturnValue.$returnString;
2368
-     * }
2369
-     * require('EE_Answer.class.php');
2370
-     * $answer= EE_Answer::new_instance(array('REG_ID' => 2,'QST_ID' => 3,'ANS_value' => The answer is 42'));
2371
-     * echo $answer->my_callback('monkeys',100);
2372
-     * //will output "you called my_callback! and passed args:monkeys,100"
2373
-     *
2374
-     * @param string $methodName name of method which was called on a child of EE_Base_Class, but which
2375
-     * @param array  $args       array of original arguments passed to the function
2376
-     * @throws EE_Error
2377
-     * @return mixed whatever the plugin which calls add_filter decides
2378
-     */
2379
-    public function __call($methodName, $args)
2380
-    {
2381
-        $className = get_class($this);
2382
-        $tagName = "FHEE__{$className}__{$methodName}";
2383
-        if ( ! has_filter($tagName)) {
2384
-            throw new EE_Error(
2385
-                sprintf(
2386
-                    __(
2387
-                        "Method %s on class %s does not exist! You can create one with the following code in functions.php or in a plugin: add_filter('%s','my_callback',10,3);function my_callback(\$previousReturnValue,EE_Base_Class \$object, \$argsArray){/*function body*/return \$whatever;}",
2388
-                        "event_espresso"
2389
-                    ),
2390
-                    $methodName,
2391
-                    $className,
2392
-                    $tagName
2393
-                )
2394
-            );
2395
-        }
2396
-        return apply_filters($tagName, null, $this, $args);
2397
-    }
2398
-
2399
-
2400
-
2401
-    /**
2402
-     * Similar to insert_post_meta, adds a record in the Extra_Meta model's table with the given key and value.
2403
-     * A $previous_value can be specified in case there are many meta rows with the same key
2404
-     *
2405
-     * @param string $meta_key
2406
-     * @param mixed  $meta_value
2407
-     * @param mixed  $previous_value
2408
-     * @return bool|int # of records updated (or BOOLEAN if we actually ended up inserting the extra meta row)
2409
-     * @throws \EE_Error
2410
-     * NOTE: if the values haven't changed, returns 0
2411
-     */
2412
-    public function update_extra_meta($meta_key, $meta_value, $previous_value = null)
2413
-    {
2414
-        $query_params = array(
2415
-            array(
2416
-                'EXM_key'  => $meta_key,
2417
-                'OBJ_ID'   => $this->ID(),
2418
-                'EXM_type' => $this->get_model()->get_this_model_name(),
2419
-            ),
2420
-        );
2421
-        if ($previous_value !== null) {
2422
-            $query_params[0]['EXM_value'] = $meta_value;
2423
-        }
2424
-        $existing_rows_like_that = EEM_Extra_Meta::instance()->get_all($query_params);
2425
-        if ( ! $existing_rows_like_that) {
2426
-            return $this->add_extra_meta($meta_key, $meta_value);
2427
-        }
2428
-        foreach ($existing_rows_like_that as $existing_row) {
2429
-            $existing_row->save(array('EXM_value' => $meta_value));
2430
-        }
2431
-        return count($existing_rows_like_that);
2432
-    }
2433
-
2434
-
2435
-
2436
-    /**
2437
-     * Adds a new extra meta record. If $unique is set to TRUE, we'll first double-check
2438
-     * no other extra meta for this model object have the same key. Returns TRUE if the
2439
-     * extra meta row was entered, false if not
2440
-     *
2441
-     * @param string  $meta_key
2442
-     * @param string  $meta_value
2443
-     * @param boolean $unique
2444
-     * @return boolean
2445
-     * @throws \EE_Error
2446
-     */
2447
-    public function add_extra_meta($meta_key, $meta_value, $unique = false)
2448
-    {
2449
-        if ($unique) {
2450
-            $existing_extra_meta = EEM_Extra_Meta::instance()->get_one(
2451
-                array(
2452
-                    array(
2453
-                        'EXM_key'  => $meta_key,
2454
-                        'OBJ_ID'   => $this->ID(),
2455
-                        'EXM_type' => $this->get_model()->get_this_model_name(),
2456
-                    ),
2457
-                )
2458
-            );
2459
-            if ($existing_extra_meta) {
2460
-                return false;
2461
-            }
2462
-        }
2463
-        $new_extra_meta = EE_Extra_Meta::new_instance(
2464
-            array(
2465
-                'EXM_key'   => $meta_key,
2466
-                'EXM_value' => $meta_value,
2467
-                'OBJ_ID'    => $this->ID(),
2468
-                'EXM_type'  => $this->get_model()->get_this_model_name(),
2469
-            )
2470
-        );
2471
-        $new_extra_meta->save();
2472
-        return true;
2473
-    }
2474
-
2475
-
2476
-
2477
-    /**
2478
-     * Deletes all the extra meta rows for this record as specified by key. If $meta_value
2479
-     * is specified, only deletes extra meta records with that value.
2480
-     *
2481
-     * @param string $meta_key
2482
-     * @param string $meta_value
2483
-     * @return int number of extra meta rows deleted
2484
-     * @throws \EE_Error
2485
-     */
2486
-    public function delete_extra_meta($meta_key, $meta_value = null)
2487
-    {
2488
-        $query_params = array(
2489
-            array(
2490
-                'EXM_key'  => $meta_key,
2491
-                'OBJ_ID'   => $this->ID(),
2492
-                'EXM_type' => $this->get_model()->get_this_model_name(),
2493
-            ),
2494
-        );
2495
-        if ($meta_value !== null) {
2496
-            $query_params[0]['EXM_value'] = $meta_value;
2497
-        }
2498
-        return EEM_Extra_Meta::instance()->delete($query_params);
2499
-    }
2500
-
2501
-
2502
-
2503
-    /**
2504
-     * Gets the extra meta with the given meta key. If you specify "single" we just return 1, otherwise
2505
-     * an array of everything found. Requires that this model actually have a relation of type EE_Has_Many_Any_Relation.
2506
-     * You can specify $default is case you haven't found the extra meta
2507
-     *
2508
-     * @param string  $meta_key
2509
-     * @param boolean $single
2510
-     * @param mixed   $default if we don't find anything, what should we return?
2511
-     * @return mixed single value if $single; array if ! $single
2512
-     * @throws \EE_Error
2513
-     */
2514
-    public function get_extra_meta($meta_key, $single = false, $default = null)
2515
-    {
2516
-        if ($single) {
2517
-            $result = $this->get_first_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2518
-            if ($result instanceof EE_Extra_Meta) {
2519
-                return $result->value();
2520
-            } else {
2521
-                return $default;
2522
-            }
2523
-        } else {
2524
-            $results = $this->get_many_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2525
-            if ($results) {
2526
-                $values = array();
2527
-                foreach ($results as $result) {
2528
-                    if ($result instanceof EE_Extra_Meta) {
2529
-                        $values[$result->ID()] = $result->value();
2530
-                    }
2531
-                }
2532
-                return $values;
2533
-            } else {
2534
-                return $default;
2535
-            }
2536
-        }
2537
-    }
2538
-
2539
-
2540
-
2541
-    /**
2542
-     * Returns a simple array of all the extra meta associated with this model object.
2543
-     * If $one_of_each_key is true (Default), it will be an array of simple key-value pairs, keys being the
2544
-     * extra meta's key, and teh value being its value. However, if there are duplicate extra meta rows with
2545
-     * the same key, only one will be used. (eg array('foo'=>'bar','monkey'=>123))
2546
-     * If $one_of_each_key is false, it will return an array with the top-level keys being
2547
-     * the extra meta keys, but their values are also arrays, which have the extra-meta's ID as their sub-key, and
2548
-     * finally the extra meta's value as each sub-value. (eg
2549
-     * array('foo'=>array(1=>'bar',2=>'bill'),'monkey'=>array(3=>123)))
2550
-     *
2551
-     * @param boolean $one_of_each_key
2552
-     * @return array
2553
-     * @throws \EE_Error
2554
-     */
2555
-    public function all_extra_meta_array($one_of_each_key = true)
2556
-    {
2557
-        $return_array = array();
2558
-        if ($one_of_each_key) {
2559
-            $extra_meta_objs = $this->get_many_related('Extra_Meta', array('group_by' => 'EXM_key'));
2560
-            foreach ($extra_meta_objs as $extra_meta_obj) {
2561
-                if ($extra_meta_obj instanceof EE_Extra_Meta) {
2562
-                    $return_array[$extra_meta_obj->key()] = $extra_meta_obj->value();
2563
-                }
2564
-            }
2565
-        } else {
2566
-            $extra_meta_objs = $this->get_many_related('Extra_Meta');
2567
-            foreach ($extra_meta_objs as $extra_meta_obj) {
2568
-                if ($extra_meta_obj instanceof EE_Extra_Meta) {
2569
-                    if ( ! isset($return_array[$extra_meta_obj->key()])) {
2570
-                        $return_array[$extra_meta_obj->key()] = array();
2571
-                    }
2572
-                    $return_array[$extra_meta_obj->key()][$extra_meta_obj->ID()] = $extra_meta_obj->value();
2573
-                }
2574
-            }
2575
-        }
2576
-        return $return_array;
2577
-    }
2578
-
2579
-
2580
-
2581
-    /**
2582
-     * Gets a pretty nice displayable nice for this model object. Often overridden
2583
-     *
2584
-     * @return string
2585
-     * @throws \EE_Error
2586
-     */
2587
-    public function name()
2588
-    {
2589
-        //find a field that's not a text field
2590
-        $field_we_can_use = $this->get_model()->get_a_field_of_type('EE_Text_Field_Base');
2591
-        if ($field_we_can_use) {
2592
-            return $this->get($field_we_can_use->get_name());
2593
-        } else {
2594
-            $first_few_properties = $this->model_field_array();
2595
-            $first_few_properties = array_slice($first_few_properties, 0, 3);
2596
-            $name_parts = array();
2597
-            foreach ($first_few_properties as $name => $value) {
2598
-                $name_parts[] = "$name:$value";
2599
-            }
2600
-            return implode(",", $name_parts);
2601
-        }
2602
-    }
2603
-
2604
-
2605
-
2606
-    /**
2607
-     * in_entity_map
2608
-     * Checks if this model object has been proven to already be in the entity map
2609
-     *
2610
-     * @return boolean
2611
-     * @throws \EE_Error
2612
-     */
2613
-    public function in_entity_map()
2614
-    {
2615
-        if ($this->ID() && $this->get_model()->get_from_entity_map($this->ID()) === $this) {
2616
-            //well, if we looked, did we find it in the entity map?
2617
-            return true;
2618
-        } else {
2619
-            return false;
2620
-        }
2621
-    }
2622
-
2623
-
2624
-
2625
-    /**
2626
-     * refresh_from_db
2627
-     * Makes sure the fields and values on this model object are in-sync with what's in the database.
2628
-     *
2629
-     * @throws EE_Error if this model object isn't in the entity mapper (because then you should
2630
-     * just use what's in the entity mapper and refresh it) and WP_DEBUG is TRUE
2631
-     */
2632
-    public function refresh_from_db()
2633
-    {
2634
-        if ($this->ID() && $this->in_entity_map()) {
2635
-            $this->get_model()->refresh_entity_map_from_db($this->ID());
2636
-        } else {
2637
-            //if it doesn't have ID, you shouldn't be asking to refresh it from teh database (because its not in the database)
2638
-            //if it has an ID but it's not in the map, and you're asking me to refresh it
2639
-            //that's kinda dangerous. You should just use what's in the entity map, or add this to the entity map if there's
2640
-            //absolutely nothing in it for this ID
2641
-            if (WP_DEBUG) {
2642
-                throw new EE_Error(
2643
-                    sprintf(
2644
-                        __('Trying to refresh a model object with ID "%1$s" that\'s not in the entity map? First off: you should put it in the entity map by calling %2$s. Second off, if you want what\'s in the database right now, you should just call %3$s yourself and discard this model object.',
2645
-                            'event_espresso'),
2646
-                        $this->ID(),
2647
-                        get_class($this->get_model()) . '::instance()->add_to_entity_map()',
2648
-                        get_class($this->get_model()) . '::instance()->refresh_entity_map()'
2649
-                    )
2650
-                );
2651
-            }
2652
-        }
2653
-    }
2654
-
2655
-
2656
-
2657
-    /**
2658
-     * Because some other plugins, like Advanced Cron Manager, expect all objects to have this method
2659
-     * (probably a bad assumption they have made, oh well)
2660
-     *
2661
-     * @return string
2662
-     */
2663
-    public function __toString()
2664
-    {
2665
-        try {
2666
-            return sprintf('%s (%s)', $this->name(), $this->ID());
2667
-        } catch (Exception $e) {
2668
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2669
-            return '';
2670
-        }
2671
-    }
2672
-
2673
-
2674
-
2675
-    /**
2676
-     * Clear related model objects if they're already in the DB, because otherwise when we
2677
-     * UN-serialize this model object we'll need to be careful to add them to the entity map.
2678
-     * This means if we have made changes to those related model objects, and want to unserialize
2679
-     * the this model object on a subsequent request, changes to those related model objects will be lost.
2680
-     * Instead, those related model objects should be directly serialized and stored.
2681
-     * Eg, the following won't work:
2682
-     * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2683
-     * $att = $reg->attendee();
2684
-     * $att->set( 'ATT_fname', 'Dirk' );
2685
-     * update_option( 'my_option', serialize( $reg ) );
2686
-     * //END REQUEST
2687
-     * //START NEXT REQUEST
2688
-     * $reg = get_option( 'my_option' );
2689
-     * $reg->attendee()->save();
2690
-     * And would need to be replace with:
2691
-     * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2692
-     * $att = $reg->attendee();
2693
-     * $att->set( 'ATT_fname', 'Dirk' );
2694
-     * update_option( 'my_option', serialize( $reg ) );
2695
-     * //END REQUEST
2696
-     * //START NEXT REQUEST
2697
-     * $att = get_option( 'my_option' );
2698
-     * $att->save();
2699
-     *
2700
-     * @return array
2701
-     * @throws \EE_Error
2702
-     */
2703
-    public function __sleep()
2704
-    {
2705
-        $model = $this->get_model();
2706
-        foreach ($model->relation_settings() as $relation_name => $relation_obj) {
2707
-            if ($relation_obj instanceof EE_Belongs_To_Relation) {
2708
-                $classname = 'EE_' . $model->get_this_model_name();
2709
-                if (
2710
-                    $this->get_one_from_cache($relation_name) instanceof $classname
2711
-                    && $this->get_one_from_cache($relation_name)->ID()
2712
-                ) {
2713
-                    $this->clear_cache($relation_name, $this->get_one_from_cache($relation_name)->ID());
2714
-                }
2715
-            }
2716
-        }
2717
-        $this->_props_n_values_provided_in_constructor = array();
2718
-        $properties_to_serialize = get_object_vars($this);
2719
-        //don't serialize the model. It's big and that risks recursion
2720
-        unset($properties_to_serialize['_model']);
2721
-        return array_keys($properties_to_serialize);
2722
-    }
2723
-
2724
-
2725
-
2726
-    /**
2727
-     * restore _props_n_values_provided_in_constructor
2728
-     * PLZ NOTE: this will reset the array to whatever fields values were present prior to serialization,
2729
-     * and therefore should NOT be used to determine if state change has occurred since initial construction.
2730
-     * At best, you would only be able to detect if state change has occurred during THIS request.
2731
-     */
2732
-    public function __wakeup()
2733
-    {
2734
-        $this->_props_n_values_provided_in_constructor = $this->_fields;
2735
-    }
28
+	/**
29
+	 * This is an array of the original properties and values provided during construction
30
+	 * of this model object. (keys are model field names, values are their values).
31
+	 * This list is important to remember so that when we are merging data from the db, we know
32
+	 * which values to override and which to not override.
33
+	 *
34
+	 * @var array
35
+	 */
36
+	protected $_props_n_values_provided_in_constructor;
37
+
38
+	/**
39
+	 * Timezone
40
+	 * This gets set by the "set_timezone()" method so that we know what timezone incoming strings|timestamps are in.
41
+	 * This can also be used before a get to set what timezone you want strings coming out of the object to be in.  NOT
42
+	 * all EE_Base_Class child classes use this property but any that use a EE_Datetime_Field data type will have
43
+	 * access to it.
44
+	 *
45
+	 * @var string
46
+	 */
47
+	protected $_timezone;
48
+
49
+
50
+
51
+	/**
52
+	 * date format
53
+	 * pattern or format for displaying dates
54
+	 *
55
+	 * @var string $_dt_frmt
56
+	 */
57
+	protected $_dt_frmt;
58
+
59
+
60
+
61
+	/**
62
+	 * time format
63
+	 * pattern or format for displaying time
64
+	 *
65
+	 * @var string $_tm_frmt
66
+	 */
67
+	protected $_tm_frmt;
68
+
69
+
70
+
71
+	/**
72
+	 * This property is for holding a cached array of object properties indexed by property name as the key.
73
+	 * The purpose of this is for setting a cache on properties that may have calculated values after a
74
+	 * prepare_for_get.  That way the cache can be checked first and the calculated property returned instead of having
75
+	 * to recalculate. Used by _set_cached_property() and _get_cached_property() methods.
76
+	 *
77
+	 * @var array
78
+	 */
79
+	protected $_cached_properties = array();
80
+
81
+	/**
82
+	 * An array containing keys of the related model, and values are either an array of related mode objects or a
83
+	 * single
84
+	 * related model object. see the model's _model_relations. The keys should match those specified. And if the
85
+	 * relation is of type EE_Belongs_To (or one of its children), then there should only be ONE related model object,
86
+	 * all others have an array)
87
+	 *
88
+	 * @var array
89
+	 */
90
+	protected $_model_relations = array();
91
+
92
+	/**
93
+	 * Array where keys are field names (see the model's _fields property) and values are their values. To see what
94
+	 * their types should be, look at what that field object returns on its prepare_for_get and prepare_for_set methods)
95
+	 *
96
+	 * @var array
97
+	 */
98
+	protected $_fields = array();
99
+
100
+	/**
101
+	 * @var boolean indicating whether or not this model object is intended to ever be saved
102
+	 * For example, we might create model objects intended to only be used for the duration
103
+	 * of this request and to be thrown away, and if they were accidentally saved
104
+	 * it would be a bug.
105
+	 */
106
+	protected $_allow_persist = true;
107
+
108
+	/**
109
+	 * @var boolean indicating whether or not this model object's properties have changed since construction
110
+	 */
111
+	protected $_has_changes = false;
112
+
113
+	/**
114
+	 * @var EEM_Base
115
+	 */
116
+	protected $_model;
117
+
118
+
119
+
120
+	/**
121
+	 * basic constructor for Event Espresso classes, performs any necessary initialization, and verifies it's children
122
+	 * play nice
123
+	 *
124
+	 * @param array   $fieldValues                             where each key is a field (ie, array key in the 2nd
125
+	 *                                                         layer of the model's _fields array, (eg, EVT_ID,
126
+	 *                                                         TXN_amount, QST_name, etc) and values are their values
127
+	 * @param boolean $bydb                                    a flag for setting if the class is instantiated by the
128
+	 *                                                         corresponding db model or not.
129
+	 * @param string  $timezone                                indicate what timezone you want any datetime fields to
130
+	 *                                                         be in when instantiating a EE_Base_Class object.
131
+	 * @param array   $date_formats                            An array of date formats to set on construct where first
132
+	 *                                                         value is the date_format and second value is the time
133
+	 *                                                         format.
134
+	 * @throws EE_Error
135
+	 */
136
+	protected function __construct($fieldValues = array(), $bydb = false, $timezone = '', $date_formats = array())
137
+	{
138
+		$className = get_class($this);
139
+		do_action("AHEE__{$className}__construct", $this, $fieldValues);
140
+		$model = $this->get_model();
141
+		$model_fields = $model->field_settings(false);
142
+		// ensure $fieldValues is an array
143
+		$fieldValues = is_array($fieldValues) ? $fieldValues : array($fieldValues);
144
+		// EEH_Debug_Tools::printr( $fieldValues, '$fieldValues  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
145
+		// verify client code has not passed any invalid field names
146
+		foreach ($fieldValues as $field_name => $field_value) {
147
+			if ( ! isset($model_fields[$field_name])) {
148
+				throw new EE_Error(sprintf(__("Invalid field (%s) passed to constructor of %s. Allowed fields are :%s",
149
+					"event_espresso"), $field_name, get_class($this), implode(", ", array_keys($model_fields))));
150
+			}
151
+		}
152
+		// EEH_Debug_Tools::printr( $model_fields, '$model_fields  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
153
+		$this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
154
+		if ( ! empty($date_formats) && is_array($date_formats)) {
155
+			list($this->_dt_frmt, $this->_tm_frmt) = $date_formats;
156
+		} else {
157
+			//set default formats for date and time
158
+			$this->_dt_frmt = (string)get_option('date_format', 'Y-m-d');
159
+			$this->_tm_frmt = (string)get_option('time_format', 'g:i a');
160
+		}
161
+		//if db model is instantiating
162
+		if ($bydb) {
163
+			//client code has indicated these field values are from the database
164
+			foreach ($model_fields as $fieldName => $field) {
165
+				$this->set_from_db($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null);
166
+			}
167
+		} else {
168
+			//we're constructing a brand
169
+			//new instance of the model object. Generally, this means we'll need to do more field validation
170
+			foreach ($model_fields as $fieldName => $field) {
171
+				$this->set($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null, true);
172
+			}
173
+		}
174
+		//remember what values were passed to this constructor
175
+		$this->_props_n_values_provided_in_constructor = $fieldValues;
176
+		//remember in entity mapper
177
+		if ( ! $bydb && $model->has_primary_key_field() && $this->ID()) {
178
+			$model->add_to_entity_map($this);
179
+		}
180
+		//setup all the relations
181
+		foreach ($model->relation_settings() as $relation_name => $relation_obj) {
182
+			if ($relation_obj instanceof EE_Belongs_To_Relation) {
183
+				$this->_model_relations[$relation_name] = null;
184
+			} else {
185
+				$this->_model_relations[$relation_name] = array();
186
+			}
187
+		}
188
+		/**
189
+		 * Action done at the end of each model object construction
190
+		 *
191
+		 * @param EE_Base_Class $this the model object just created
192
+		 */
193
+		do_action('AHEE__EE_Base_Class__construct__finished', $this);
194
+	}
195
+
196
+
197
+
198
+	/**
199
+	 * Gets whether or not this model object is allowed to persist/be saved to the database.
200
+	 *
201
+	 * @return boolean
202
+	 */
203
+	public function allow_persist()
204
+	{
205
+		return $this->_allow_persist;
206
+	}
207
+
208
+
209
+
210
+	/**
211
+	 * Sets whether or not this model object should be allowed to be saved to the DB.
212
+	 * Normally once this is set to FALSE you wouldn't set it back to TRUE, unless
213
+	 * you got new information that somehow made you change your mind.
214
+	 *
215
+	 * @param boolean $allow_persist
216
+	 * @return boolean
217
+	 */
218
+	public function set_allow_persist($allow_persist)
219
+	{
220
+		return $this->_allow_persist = $allow_persist;
221
+	}
222
+
223
+
224
+
225
+	/**
226
+	 * Gets the field's original value when this object was constructed during this request.
227
+	 * This can be helpful when determining if a model object has changed or not
228
+	 *
229
+	 * @param string $field_name
230
+	 * @return mixed|null
231
+	 * @throws \EE_Error
232
+	 */
233
+	public function get_original($field_name)
234
+	{
235
+		if (isset($this->_props_n_values_provided_in_constructor[$field_name])
236
+			&& $field_settings = $this->get_model()->field_settings_for($field_name)
237
+		) {
238
+			return $field_settings->prepare_for_get($this->_props_n_values_provided_in_constructor[$field_name]);
239
+		} else {
240
+			return null;
241
+		}
242
+	}
243
+
244
+
245
+
246
+	/**
247
+	 * @param EE_Base_Class $obj
248
+	 * @return string
249
+	 */
250
+	public function get_class($obj)
251
+	{
252
+		return get_class($obj);
253
+	}
254
+
255
+
256
+
257
+	/**
258
+	 * Overrides parent because parent expects old models.
259
+	 * This also doesn't do any validation, and won't work for serialized arrays
260
+	 *
261
+	 * @param    string $field_name
262
+	 * @param    mixed  $field_value
263
+	 * @param bool      $use_default
264
+	 * @throws \EE_Error
265
+	 */
266
+	public function set($field_name, $field_value, $use_default = false)
267
+	{
268
+		// if not using default and nothing has changed, and object has already been setup (has ID),
269
+		// then don't do anything
270
+		if (
271
+			! $use_default
272
+			&& $this->_fields[$field_name] === $field_value
273
+			&& $this->ID()
274
+		) {
275
+			return;
276
+		}
277
+		$model = $this->get_model();
278
+		$this->_has_changes = true;
279
+		$field_obj = $model->field_settings_for($field_name);
280
+		if ($field_obj instanceof EE_Model_Field_Base) {
281
+			//			if ( method_exists( $field_obj, 'set_timezone' )) {
282
+			if ($field_obj instanceof EE_Datetime_Field) {
283
+				$field_obj->set_timezone($this->_timezone);
284
+				$field_obj->set_date_format($this->_dt_frmt);
285
+				$field_obj->set_time_format($this->_tm_frmt);
286
+			}
287
+			$holder_of_value = $field_obj->prepare_for_set($field_value);
288
+			//should the value be null?
289
+			if (($field_value === null || $holder_of_value === null || $holder_of_value === '') && $use_default) {
290
+				$this->_fields[$field_name] = $field_obj->get_default_value();
291
+				/**
292
+				 * To save having to refactor all the models, if a default value is used for a
293
+				 * EE_Datetime_Field, and that value is not null nor is it a DateTime
294
+				 * object.  Then let's do a set again to ensure that it becomes a DateTime
295
+				 * object.
296
+				 *
297
+				 * @since 4.6.10+
298
+				 */
299
+				if (
300
+					$field_obj instanceof EE_Datetime_Field
301
+					&& $this->_fields[$field_name] !== null
302
+					&& ! $this->_fields[$field_name] instanceof DateTime
303
+				) {
304
+					empty($this->_fields[$field_name])
305
+						? $this->set($field_name, time())
306
+						: $this->set($field_name, $this->_fields[$field_name]);
307
+				}
308
+			} else {
309
+				$this->_fields[$field_name] = $holder_of_value;
310
+			}
311
+			//if we're not in the constructor...
312
+			//now check if what we set was a primary key
313
+			if (
314
+				//note: props_n_values_provided_in_constructor is only set at the END of the constructor
315
+				$this->_props_n_values_provided_in_constructor
316
+				&& $field_value
317
+				&& $field_name === $model->primary_key_name()
318
+			) {
319
+				//if so, we want all this object's fields to be filled either with
320
+				//what we've explicitly set on this model
321
+				//or what we have in the db
322
+				// echo "setting primary key!";
323
+				$fields_on_model = self::_get_model(get_class($this))->field_settings();
324
+				$obj_in_db = self::_get_model(get_class($this))->get_one_by_ID($field_value);
325
+				foreach ($fields_on_model as $field_obj) {
326
+					if ( ! array_key_exists($field_obj->get_name(), $this->_props_n_values_provided_in_constructor)
327
+						 && $field_obj->get_name() !== $field_name
328
+					) {
329
+						$this->set($field_obj->get_name(), $obj_in_db->get($field_obj->get_name()));
330
+					}
331
+				}
332
+				//oh this model object has an ID? well make sure its in the entity mapper
333
+				$model->add_to_entity_map($this);
334
+			}
335
+			//let's unset any cache for this field_name from the $_cached_properties property.
336
+			$this->_clear_cached_property($field_name);
337
+		} else {
338
+			throw new EE_Error(sprintf(__("A valid EE_Model_Field_Base could not be found for the given field name: %s",
339
+				"event_espresso"), $field_name));
340
+		}
341
+	}
342
+
343
+
344
+
345
+	/**
346
+	 * This sets the field value on the db column if it exists for the given $column_name or
347
+	 * saves it to EE_Extra_Meta if the given $column_name does not match a db column.
348
+	 *
349
+	 * @see EE_message::get_column_value for related documentation on the necessity of this method.
350
+	 * @param string $field_name  Must be the exact column name.
351
+	 * @param mixed  $field_value The value to set.
352
+	 * @return int|bool @see EE_Base_Class::update_extra_meta() for return docs.
353
+	 * @throws \EE_Error
354
+	 */
355
+	public function set_field_or_extra_meta($field_name, $field_value)
356
+	{
357
+		if ($this->get_model()->has_field($field_name)) {
358
+			$this->set($field_name, $field_value);
359
+			return true;
360
+		} else {
361
+			//ensure this object is saved first so that extra meta can be properly related.
362
+			$this->save();
363
+			return $this->update_extra_meta($field_name, $field_value);
364
+		}
365
+	}
366
+
367
+
368
+
369
+	/**
370
+	 * This retrieves the value of the db column set on this class or if that's not present
371
+	 * it will attempt to retrieve from extra_meta if found.
372
+	 * Example Usage:
373
+	 * Via EE_Message child class:
374
+	 * Due to the dynamic nature of the EE_messages system, EE_messengers will always have a "to",
375
+	 * "from", "subject", and "content" field (as represented in the EE_Message schema), however they may
376
+	 * also have additional main fields specific to the messenger.  The system accommodates those extra
377
+	 * fields through the EE_Extra_Meta table.  This method allows for EE_messengers to retrieve the
378
+	 * value for those extra fields dynamically via the EE_message object.
379
+	 *
380
+	 * @param  string $field_name expecting the fully qualified field name.
381
+	 * @return mixed|null  value for the field if found.  null if not found.
382
+	 * @throws \EE_Error
383
+	 */
384
+	public function get_field_or_extra_meta($field_name)
385
+	{
386
+		if ($this->get_model()->has_field($field_name)) {
387
+			$column_value = $this->get($field_name);
388
+		} else {
389
+			//This isn't a column in the main table, let's see if it is in the extra meta.
390
+			$column_value = $this->get_extra_meta($field_name, true, null);
391
+		}
392
+		return $column_value;
393
+	}
394
+
395
+
396
+
397
+	/**
398
+	 * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
399
+	 * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
400
+	 * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). This is
401
+	 * available to all child classes that may be using the EE_Datetime_Field for a field data type.
402
+	 *
403
+	 * @access public
404
+	 * @param string $timezone A valid timezone string as described by @link http://www.php.net/manual/en/timezones.php
405
+	 * @return void
406
+	 * @throws \EE_Error
407
+	 */
408
+	public function set_timezone($timezone = '')
409
+	{
410
+		$this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
411
+		//make sure we clear all cached properties because they won't be relevant now
412
+		$this->_clear_cached_properties();
413
+		//make sure we update field settings and the date for all EE_Datetime_Fields
414
+		$model_fields = $this->get_model()->field_settings(false);
415
+		foreach ($model_fields as $field_name => $field_obj) {
416
+			if ($field_obj instanceof EE_Datetime_Field) {
417
+				$field_obj->set_timezone($this->_timezone);
418
+				if (isset($this->_fields[$field_name]) && $this->_fields[$field_name] instanceof DateTime) {
419
+					$this->_fields[$field_name]->setTimezone(new DateTimeZone($this->_timezone));
420
+				}
421
+			}
422
+		}
423
+	}
424
+
425
+
426
+
427
+	/**
428
+	 * This just returns whatever is set for the current timezone.
429
+	 *
430
+	 * @access public
431
+	 * @return string timezone string
432
+	 */
433
+	public function get_timezone()
434
+	{
435
+		return $this->_timezone;
436
+	}
437
+
438
+
439
+
440
+	/**
441
+	 * This sets the internal date format to what is sent in to be used as the new default for the class
442
+	 * internally instead of wp set date format options
443
+	 *
444
+	 * @since 4.6
445
+	 * @param string $format should be a format recognizable by PHP date() functions.
446
+	 */
447
+	public function set_date_format($format)
448
+	{
449
+		$this->_dt_frmt = $format;
450
+		//clear cached_properties because they won't be relevant now.
451
+		$this->_clear_cached_properties();
452
+	}
453
+
454
+
455
+
456
+	/**
457
+	 * This sets the internal time format string to what is sent in to be used as the new default for the
458
+	 * class internally instead of wp set time format options.
459
+	 *
460
+	 * @since 4.6
461
+	 * @param string $format should be a format recognizable by PHP date() functions.
462
+	 */
463
+	public function set_time_format($format)
464
+	{
465
+		$this->_tm_frmt = $format;
466
+		//clear cached_properties because they won't be relevant now.
467
+		$this->_clear_cached_properties();
468
+	}
469
+
470
+
471
+
472
+	/**
473
+	 * This returns the current internal set format for the date and time formats.
474
+	 *
475
+	 * @param bool $full           if true (default), then return the full format.  Otherwise will return an array
476
+	 *                             where the first value is the date format and the second value is the time format.
477
+	 * @return mixed string|array
478
+	 */
479
+	public function get_format($full = true)
480
+	{
481
+		return $full ? $this->_dt_frmt . ' ' . $this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
482
+	}
483
+
484
+
485
+
486
+	/**
487
+	 * cache
488
+	 * stores the passed model object on the current model object.
489
+	 * In certain circumstances, we can use this cached model object instead of querying for another one entirely.
490
+	 *
491
+	 * @param string        $relationName    one of the keys in the _model_relations array on the model. Eg
492
+	 *                                       'Registration' associated with this model object
493
+	 * @param EE_Base_Class $object_to_cache that has a relation to this model object. (Eg, if this is a Transaction,
494
+	 *                                       that could be a payment or a registration)
495
+	 * @param null          $cache_id        a string or number that will be used as the key for any Belongs_To_Many
496
+	 *                                       items which will be stored in an array on this object
497
+	 * @throws EE_Error
498
+	 * @return mixed    index into cache, or just TRUE if the relation is of type Belongs_To (because there's only one
499
+	 *                  related thing, no array)
500
+	 */
501
+	public function cache($relationName = '', $object_to_cache = null, $cache_id = null)
502
+	{
503
+		// its entirely possible that there IS no related object yet in which case there is nothing to cache.
504
+		if ( ! $object_to_cache instanceof EE_Base_Class) {
505
+			return false;
506
+		}
507
+		// also get "how" the object is related, or throw an error
508
+		if ( ! $relationship_to_model = $this->get_model()->related_settings_for($relationName)) {
509
+			throw new EE_Error(sprintf(__('There is no relationship to %s on a %s. Cannot cache it', 'event_espresso'),
510
+				$relationName, get_class($this)));
511
+		}
512
+		// how many things are related ?
513
+		if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
514
+			// if it's a "belongs to" relationship, then there's only one related model object  eg, if this is a registration, there's only 1 attendee for it
515
+			// so for these model objects just set it to be cached
516
+			$this->_model_relations[$relationName] = $object_to_cache;
517
+			$return = true;
518
+		} else {
519
+			// otherwise, this is the "many" side of a one to many relationship, so we'll add the object to the array of related objects for that type.
520
+			// eg: if this is an event, there are many registrations for that event, so we cache the registrations in an array
521
+			if ( ! is_array($this->_model_relations[$relationName])) {
522
+				// if for some reason, the cached item is a model object, then stick that in the array, otherwise start with an empty array
523
+				$this->_model_relations[$relationName] = $this->_model_relations[$relationName] instanceof EE_Base_Class
524
+					? array($this->_model_relations[$relationName]) : array();
525
+			}
526
+			// first check for a cache_id which is normally empty
527
+			if ( ! empty($cache_id)) {
528
+				// if the cache_id exists, then it means we are purposely trying to cache this with a known key that can then be used to retrieve the object later on
529
+				$this->_model_relations[$relationName][$cache_id] = $object_to_cache;
530
+				$return = $cache_id;
531
+			} elseif ($object_to_cache->ID()) {
532
+				// OR the cached object originally came from the db, so let's just use it's PK for an ID
533
+				$this->_model_relations[$relationName][$object_to_cache->ID()] = $object_to_cache;
534
+				$return = $object_to_cache->ID();
535
+			} else {
536
+				// OR it's a new object with no ID, so just throw it in the array with an auto-incremented ID
537
+				$this->_model_relations[$relationName][] = $object_to_cache;
538
+				// move the internal pointer to the end of the array
539
+				end($this->_model_relations[$relationName]);
540
+				// and grab the key so that we can return it
541
+				$return = key($this->_model_relations[$relationName]);
542
+			}
543
+		}
544
+		return $return;
545
+	}
546
+
547
+
548
+
549
+	/**
550
+	 * For adding an item to the cached_properties property.
551
+	 *
552
+	 * @access protected
553
+	 * @param string      $fieldname the property item the corresponding value is for.
554
+	 * @param mixed       $value     The value we are caching.
555
+	 * @param string|null $cache_type
556
+	 * @return void
557
+	 * @throws \EE_Error
558
+	 */
559
+	protected function _set_cached_property($fieldname, $value, $cache_type = null)
560
+	{
561
+		//first make sure this property exists
562
+		$this->get_model()->field_settings_for($fieldname);
563
+		$cache_type = empty($cache_type) ? 'standard' : $cache_type;
564
+		$this->_cached_properties[$fieldname][$cache_type] = $value;
565
+	}
566
+
567
+
568
+
569
+	/**
570
+	 * This returns the value cached property if it exists OR the actual property value if the cache doesn't exist.
571
+	 * This also SETS the cache if we return the actual property!
572
+	 *
573
+	 * @param string $fieldname        the name of the property we're trying to retrieve
574
+	 * @param bool   $pretty
575
+	 * @param string $extra_cache_ref  This allows the user to specify an extra cache ref for the given property
576
+	 *                                 (in cases where the same property may be used for different outputs
577
+	 *                                 - i.e. datetime, money etc.)
578
+	 *                                 It can also accept certain pre-defined "schema" strings
579
+	 *                                 to define how to output the property.
580
+	 *                                 see the field's prepare_for_pretty_echoing for what strings can be used
581
+	 * @return mixed                   whatever the value for the property is we're retrieving
582
+	 * @throws \EE_Error
583
+	 */
584
+	protected function _get_cached_property($fieldname, $pretty = false, $extra_cache_ref = null)
585
+	{
586
+		//verify the field exists
587
+		$model = $this->get_model();
588
+		$model->field_settings_for($fieldname);
589
+		$cache_type = $pretty ? 'pretty' : 'standard';
590
+		$cache_type .= ! empty($extra_cache_ref) ? '_' . $extra_cache_ref : '';
591
+		if (isset($this->_cached_properties[$fieldname][$cache_type])) {
592
+			return $this->_cached_properties[$fieldname][$cache_type];
593
+		}
594
+		$value = $this->_get_fresh_property($fieldname, $pretty, $extra_cache_ref);
595
+		$this->_set_cached_property($fieldname, $value, $cache_type);
596
+		return $value;
597
+	}
598
+
599
+
600
+
601
+	/**
602
+	 * If the cache didn't fetch the needed item, this fetches it.
603
+	 * @param string $fieldname
604
+	 * @param bool $pretty
605
+	 * @param string $extra_cache_ref
606
+	 * @return mixed
607
+	 */
608
+	protected function _get_fresh_property($fieldname, $pretty = false, $extra_cache_ref = null)
609
+	{
610
+		$field_obj = $this->get_model()->field_settings_for($fieldname);
611
+		// If this is an EE_Datetime_Field we need to make sure timezone, formats, and output are correct
612
+		if ($field_obj instanceof EE_Datetime_Field) {
613
+			$this->_prepare_datetime_field($field_obj, $pretty, $extra_cache_ref);
614
+		}
615
+		if ( ! isset($this->_fields[$fieldname])) {
616
+			$this->_fields[$fieldname] = null;
617
+		}
618
+		$value = $pretty
619
+			? $field_obj->prepare_for_pretty_echoing($this->_fields[$fieldname], $extra_cache_ref)
620
+			: $field_obj->prepare_for_get($this->_fields[$fieldname]);
621
+		return $value;
622
+	}
623
+
624
+
625
+
626
+	/**
627
+	 * set timezone, formats, and output for EE_Datetime_Field objects
628
+	 *
629
+	 * @param \EE_Datetime_Field $datetime_field
630
+	 * @param bool               $pretty
631
+	 * @param null $date_or_time
632
+	 * @return void
633
+	 * @throws \EE_Error
634
+	 */
635
+	protected function _prepare_datetime_field(
636
+		EE_Datetime_Field $datetime_field,
637
+		$pretty = false,
638
+		$date_or_time = null
639
+	) {
640
+		$datetime_field->set_timezone($this->_timezone);
641
+		$datetime_field->set_date_format($this->_dt_frmt, $pretty);
642
+		$datetime_field->set_time_format($this->_tm_frmt, $pretty);
643
+		//set the output returned
644
+		switch ($date_or_time) {
645
+			case 'D' :
646
+				$datetime_field->set_date_time_output('date');
647
+				break;
648
+			case 'T' :
649
+				$datetime_field->set_date_time_output('time');
650
+				break;
651
+			default :
652
+				$datetime_field->set_date_time_output();
653
+		}
654
+	}
655
+
656
+
657
+
658
+	/**
659
+	 * This just takes care of clearing out the cached_properties
660
+	 *
661
+	 * @return void
662
+	 */
663
+	protected function _clear_cached_properties()
664
+	{
665
+		$this->_cached_properties = array();
666
+	}
667
+
668
+
669
+
670
+	/**
671
+	 * This just clears out ONE property if it exists in the cache
672
+	 *
673
+	 * @param  string $property_name the property to remove if it exists (from the _cached_properties array)
674
+	 * @return void
675
+	 */
676
+	protected function _clear_cached_property($property_name)
677
+	{
678
+		if (isset($this->_cached_properties[$property_name])) {
679
+			unset($this->_cached_properties[$property_name]);
680
+		}
681
+	}
682
+
683
+
684
+
685
+	/**
686
+	 * Ensures that this related thing is a model object.
687
+	 *
688
+	 * @param mixed  $object_or_id EE_base_Class/int/string either a related model object, or its ID
689
+	 * @param string $model_name   name of the related thing, eg 'Attendee',
690
+	 * @return EE_Base_Class
691
+	 * @throws \EE_Error
692
+	 */
693
+	protected function ensure_related_thing_is_model_obj($object_or_id, $model_name)
694
+	{
695
+		$other_model_instance = self::_get_model_instance_with_name(
696
+			self::_get_model_classname($model_name),
697
+			$this->_timezone
698
+		);
699
+		return $other_model_instance->ensure_is_obj($object_or_id);
700
+	}
701
+
702
+
703
+
704
+	/**
705
+	 * Forgets the cached model of the given relation Name. So the next time we request it,
706
+	 * we will fetch it again from the database. (Handy if you know it's changed somehow).
707
+	 * If a specific object is supplied, and the relationship to it is either a HasMany or HABTM,
708
+	 * then only remove that one object from our cached array. Otherwise, clear the entire list
709
+	 *
710
+	 * @param string $relationName                         one of the keys in the _model_relations array on the model.
711
+	 *                                                     Eg 'Registration'
712
+	 * @param mixed  $object_to_remove_or_index_into_array or an index into the array of cached things, or NULL
713
+	 *                                                     if you intend to use $clear_all = TRUE, or the relation only
714
+	 *                                                     has 1 object anyways (ie, it's a BelongsToRelation)
715
+	 * @param bool   $clear_all                            This flags clearing the entire cache relation property if
716
+	 *                                                     this is HasMany or HABTM.
717
+	 * @throws EE_Error
718
+	 * @return EE_Base_Class | boolean from which was cleared from the cache, or true if we requested to remove a
719
+	 *                       relation from all
720
+	 */
721
+	public function clear_cache($relationName, $object_to_remove_or_index_into_array = null, $clear_all = false)
722
+	{
723
+		$relationship_to_model = $this->get_model()->related_settings_for($relationName);
724
+		$index_in_cache = '';
725
+		if ( ! $relationship_to_model) {
726
+			throw new EE_Error(
727
+				sprintf(
728
+					__("There is no relationship to %s on a %s. Cannot clear that cache", 'event_espresso'),
729
+					$relationName,
730
+					get_class($this)
731
+				)
732
+			);
733
+		}
734
+		if ($clear_all) {
735
+			$obj_removed = true;
736
+			$this->_model_relations[$relationName] = null;
737
+		} elseif ($relationship_to_model instanceof EE_Belongs_To_Relation) {
738
+			$obj_removed = $this->_model_relations[$relationName];
739
+			$this->_model_relations[$relationName] = null;
740
+		} else {
741
+			if ($object_to_remove_or_index_into_array instanceof EE_Base_Class
742
+				&& $object_to_remove_or_index_into_array->ID()
743
+			) {
744
+				$index_in_cache = $object_to_remove_or_index_into_array->ID();
745
+				if (is_array($this->_model_relations[$relationName])
746
+					&& ! isset($this->_model_relations[$relationName][$index_in_cache])
747
+				) {
748
+					$index_found_at = null;
749
+					//find this object in the array even though it has a different key
750
+					foreach ($this->_model_relations[$relationName] as $index => $obj) {
751
+						if (
752
+							$obj instanceof EE_Base_Class
753
+							&& (
754
+								$obj == $object_to_remove_or_index_into_array
755
+								|| $obj->ID() === $object_to_remove_or_index_into_array->ID()
756
+							)
757
+						) {
758
+							$index_found_at = $index;
759
+							break;
760
+						}
761
+					}
762
+					if ($index_found_at) {
763
+						$index_in_cache = $index_found_at;
764
+					} else {
765
+						//it wasn't found. huh. well obviously it doesn't need to be removed from teh cache
766
+						//if it wasn't in it to begin with. So we're done
767
+						return $object_to_remove_or_index_into_array;
768
+					}
769
+				}
770
+			} elseif ($object_to_remove_or_index_into_array instanceof EE_Base_Class) {
771
+				//so they provided a model object, but it's not yet saved to the DB... so let's go hunting for it!
772
+				foreach ($this->get_all_from_cache($relationName) as $index => $potentially_obj_we_want) {
773
+					if ($potentially_obj_we_want == $object_to_remove_or_index_into_array) {
774
+						$index_in_cache = $index;
775
+					}
776
+				}
777
+			} else {
778
+				$index_in_cache = $object_to_remove_or_index_into_array;
779
+			}
780
+			//supposedly we've found it. But it could just be that the client code
781
+			//provided a bad index/object
782
+			if (
783
+			isset(
784
+				$this->_model_relations[$relationName],
785
+				$this->_model_relations[$relationName][$index_in_cache]
786
+			)
787
+			) {
788
+				$obj_removed = $this->_model_relations[$relationName][$index_in_cache];
789
+				unset($this->_model_relations[$relationName][$index_in_cache]);
790
+			} else {
791
+				//that thing was never cached anyways.
792
+				$obj_removed = null;
793
+			}
794
+		}
795
+		return $obj_removed;
796
+	}
797
+
798
+
799
+
800
+	/**
801
+	 * update_cache_after_object_save
802
+	 * Allows a cached item to have it's cache ID (within the array of cached items) reset using the new ID it has
803
+	 * obtained after being saved to the db
804
+	 *
805
+	 * @param string         $relationName       - the type of object that is cached
806
+	 * @param \EE_Base_Class $newly_saved_object - the newly saved object to be re-cached
807
+	 * @param string         $current_cache_id   - the ID that was used when originally caching the object
808
+	 * @return boolean TRUE on success, FALSE on fail
809
+	 * @throws \EE_Error
810
+	 */
811
+	public function update_cache_after_object_save(
812
+		$relationName,
813
+		EE_Base_Class $newly_saved_object,
814
+		$current_cache_id = ''
815
+	) {
816
+		// verify that incoming object is of the correct type
817
+		$obj_class = 'EE_' . $relationName;
818
+		if ($newly_saved_object instanceof $obj_class) {
819
+			/* @type EE_Base_Class $newly_saved_object */
820
+			// now get the type of relation
821
+			$relationship_to_model = $this->get_model()->related_settings_for($relationName);
822
+			// if this is a 1:1 relationship
823
+			if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
824
+				// then just replace the cached object with the newly saved object
825
+				$this->_model_relations[$relationName] = $newly_saved_object;
826
+				return true;
827
+				// or if it's some kind of sordid feral polyamorous relationship...
828
+			} elseif (is_array($this->_model_relations[$relationName])
829
+					  && isset($this->_model_relations[$relationName][$current_cache_id])
830
+			) {
831
+				// then remove the current cached item
832
+				unset($this->_model_relations[$relationName][$current_cache_id]);
833
+				// and cache the newly saved object using it's new ID
834
+				$this->_model_relations[$relationName][$newly_saved_object->ID()] = $newly_saved_object;
835
+				return true;
836
+			}
837
+		}
838
+		return false;
839
+	}
840
+
841
+
842
+
843
+	/**
844
+	 * Fetches a single EE_Base_Class on that relation. (If the relation is of type
845
+	 * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
846
+	 *
847
+	 * @param string $relationName
848
+	 * @return EE_Base_Class
849
+	 */
850
+	public function get_one_from_cache($relationName)
851
+	{
852
+		$cached_array_or_object = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName]
853
+			: null;
854
+		if (is_array($cached_array_or_object)) {
855
+			return array_shift($cached_array_or_object);
856
+		} else {
857
+			return $cached_array_or_object;
858
+		}
859
+	}
860
+
861
+
862
+
863
+	/**
864
+	 * Fetches a single EE_Base_Class on that relation. (If the relation is of type
865
+	 * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
866
+	 *
867
+	 * @param string $relationName
868
+	 * @throws \EE_Error
869
+	 * @return EE_Base_Class[] NOT necessarily indexed by primary keys
870
+	 */
871
+	public function get_all_from_cache($relationName)
872
+	{
873
+		$objects = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : array();
874
+		// if the result is not an array, but exists, make it an array
875
+		$objects = is_array($objects) ? $objects : array($objects);
876
+		//bugfix for https://events.codebasehq.com/projects/event-espresso/tickets/7143
877
+		//basically, if this model object was stored in the session, and these cached model objects
878
+		//already have IDs, let's make sure they're in their model's entity mapper
879
+		//otherwise we will have duplicates next time we call
880
+		// EE_Registry::instance()->load_model( $relationName )->get_one_by_ID( $result->ID() );
881
+		$model = EE_Registry::instance()->load_model($relationName);
882
+		foreach ($objects as $model_object) {
883
+			if ($model instanceof EEM_Base && $model_object instanceof EE_Base_Class) {
884
+				//ensure its in the map if it has an ID; otherwise it will be added to the map when its saved
885
+				if ($model_object->ID()) {
886
+					$model->add_to_entity_map($model_object);
887
+				}
888
+			} else {
889
+				throw new EE_Error(
890
+					sprintf(
891
+						__(
892
+							'Error retrieving related model objects. Either $1%s is not a model or $2%s is not a model object',
893
+							'event_espresso'
894
+						),
895
+						$relationName,
896
+						gettype($model_object)
897
+					)
898
+				);
899
+			}
900
+		}
901
+		return $objects;
902
+	}
903
+
904
+
905
+
906
+	/**
907
+	 * Returns the next x number of EE_Base_Class objects in sequence from this object as found in the database
908
+	 * matching the given query conditions.
909
+	 *
910
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
911
+	 * @param int   $limit              How many objects to return.
912
+	 * @param array $query_params       Any additional conditions on the query.
913
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
914
+	 *                                  you can indicate just the columns you want returned
915
+	 * @return array|EE_Base_Class[]
916
+	 * @throws \EE_Error
917
+	 */
918
+	public function next_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
919
+	{
920
+		$model = $this->get_model();
921
+		$field = empty($field_to_order_by) && $model->has_primary_key_field()
922
+			? $model->get_primary_key_field()->get_name()
923
+			: $field_to_order_by;
924
+		$current_value = ! empty($field) ? $this->get($field) : null;
925
+		if (empty($field) || empty($current_value)) {
926
+			return array();
927
+		}
928
+		return $model->next_x($current_value, $field, $limit, $query_params, $columns_to_select);
929
+	}
930
+
931
+
932
+
933
+	/**
934
+	 * Returns the previous x number of EE_Base_Class objects in sequence from this object as found in the database
935
+	 * matching the given query conditions.
936
+	 *
937
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
938
+	 * @param int   $limit              How many objects to return.
939
+	 * @param array $query_params       Any additional conditions on the query.
940
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
941
+	 *                                  you can indicate just the columns you want returned
942
+	 * @return array|EE_Base_Class[]
943
+	 * @throws \EE_Error
944
+	 */
945
+	public function previous_x(
946
+		$field_to_order_by = null,
947
+		$limit = 1,
948
+		$query_params = array(),
949
+		$columns_to_select = null
950
+	) {
951
+		$model = $this->get_model();
952
+		$field = empty($field_to_order_by) && $model->has_primary_key_field()
953
+			? $model->get_primary_key_field()->get_name()
954
+			: $field_to_order_by;
955
+		$current_value = ! empty($field) ? $this->get($field) : null;
956
+		if (empty($field) || empty($current_value)) {
957
+			return array();
958
+		}
959
+		return $model->previous_x($current_value, $field, $limit, $query_params, $columns_to_select);
960
+	}
961
+
962
+
963
+
964
+	/**
965
+	 * Returns the next EE_Base_Class object in sequence from this object as found in the database
966
+	 * matching the given query conditions.
967
+	 *
968
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
969
+	 * @param array $query_params       Any additional conditions on the query.
970
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
971
+	 *                                  you can indicate just the columns you want returned
972
+	 * @return array|EE_Base_Class
973
+	 * @throws \EE_Error
974
+	 */
975
+	public function next($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
976
+	{
977
+		$model = $this->get_model();
978
+		$field = empty($field_to_order_by) && $model->has_primary_key_field()
979
+			? $model->get_primary_key_field()->get_name()
980
+			: $field_to_order_by;
981
+		$current_value = ! empty($field) ? $this->get($field) : null;
982
+		if (empty($field) || empty($current_value)) {
983
+			return array();
984
+		}
985
+		return $model->next($current_value, $field, $query_params, $columns_to_select);
986
+	}
987
+
988
+
989
+
990
+	/**
991
+	 * Returns the previous EE_Base_Class object in sequence from this object as found in the database
992
+	 * matching the given query conditions.
993
+	 *
994
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
995
+	 * @param array $query_params       Any additional conditions on the query.
996
+	 * @param null  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
997
+	 *                                  you can indicate just the column you want returned
998
+	 * @return array|EE_Base_Class
999
+	 * @throws \EE_Error
1000
+	 */
1001
+	public function previous($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
1002
+	{
1003
+		$model = $this->get_model();
1004
+		$field = empty($field_to_order_by) && $model->has_primary_key_field()
1005
+			? $model->get_primary_key_field()->get_name()
1006
+			: $field_to_order_by;
1007
+		$current_value = ! empty($field) ? $this->get($field) : null;
1008
+		if (empty($field) || empty($current_value)) {
1009
+			return array();
1010
+		}
1011
+		return $model->previous($current_value, $field, $query_params, $columns_to_select);
1012
+	}
1013
+
1014
+
1015
+
1016
+	/**
1017
+	 * Overrides parent because parent expects old models.
1018
+	 * This also doesn't do any validation, and won't work for serialized arrays
1019
+	 *
1020
+	 * @param string $field_name
1021
+	 * @param mixed  $field_value_from_db
1022
+	 * @throws \EE_Error
1023
+	 */
1024
+	public function set_from_db($field_name, $field_value_from_db)
1025
+	{
1026
+		$field_obj = $this->get_model()->field_settings_for($field_name);
1027
+		if ($field_obj instanceof EE_Model_Field_Base) {
1028
+			//you would think the DB has no NULLs for non-null label fields right? wrong!
1029
+			//eg, a CPT model object could have an entry in the posts table, but no
1030
+			//entry in the meta table. Meaning that all its columns in the meta table
1031
+			//are null! yikes! so when we find one like that, use defaults for its meta columns
1032
+			if ($field_value_from_db === null) {
1033
+				if ($field_obj->is_nullable()) {
1034
+					//if the field allows nulls, then let it be null
1035
+					$field_value = null;
1036
+				} else {
1037
+					$field_value = $field_obj->get_default_value();
1038
+				}
1039
+			} else {
1040
+				$field_value = $field_obj->prepare_for_set_from_db($field_value_from_db);
1041
+			}
1042
+			$this->_fields[$field_name] = $field_value;
1043
+			$this->_clear_cached_property($field_name);
1044
+		}
1045
+	}
1046
+
1047
+
1048
+
1049
+	/**
1050
+	 * verifies that the specified field is of the correct type
1051
+	 *
1052
+	 * @param string $field_name
1053
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1054
+	 *                                (in cases where the same property may be used for different outputs
1055
+	 *                                - i.e. datetime, money etc.)
1056
+	 * @return mixed
1057
+	 * @throws \EE_Error
1058
+	 */
1059
+	public function get($field_name, $extra_cache_ref = null)
1060
+	{
1061
+		return $this->_get_cached_property($field_name, false, $extra_cache_ref);
1062
+	}
1063
+
1064
+
1065
+
1066
+	/**
1067
+	 * This method simply returns the RAW unprocessed value for the given property in this class
1068
+	 *
1069
+	 * @param  string $field_name A valid fieldname
1070
+	 * @return mixed              Whatever the raw value stored on the property is.
1071
+	 * @throws EE_Error if fieldSettings is misconfigured or the field doesn't exist.
1072
+	 */
1073
+	public function get_raw($field_name)
1074
+	{
1075
+		$field_settings = $this->get_model()->field_settings_for($field_name);
1076
+		return $field_settings instanceof EE_Datetime_Field && $this->_fields[$field_name] instanceof DateTime
1077
+			? $this->_fields[$field_name]->format('U')
1078
+			: $this->_fields[$field_name];
1079
+	}
1080
+
1081
+
1082
+
1083
+	/**
1084
+	 * This is used to return the internal DateTime object used for a field that is a
1085
+	 * EE_Datetime_Field.
1086
+	 *
1087
+	 * @param string $field_name               The field name retrieving the DateTime object.
1088
+	 * @return mixed null | false | DateTime  If the requested field is NOT a EE_Datetime_Field then
1089
+	 * @throws \EE_Error
1090
+	 *                                         an error is set and false returned.  If the field IS an
1091
+	 *                                         EE_Datetime_Field and but the field value is null, then
1092
+	 *                                         just null is returned (because that indicates that likely
1093
+	 *                                         this field is nullable).
1094
+	 */
1095
+	public function get_DateTime_object($field_name)
1096
+	{
1097
+		$field_settings = $this->get_model()->field_settings_for($field_name);
1098
+		if ( ! $field_settings instanceof EE_Datetime_Field) {
1099
+			EE_Error::add_error(
1100
+				sprintf(
1101
+					__(
1102
+						'The field %s is not an EE_Datetime_Field field.  There is no DateTime object stored on this field type.',
1103
+						'event_espresso'
1104
+					),
1105
+					$field_name
1106
+				),
1107
+				__FILE__,
1108
+				__FUNCTION__,
1109
+				__LINE__
1110
+			);
1111
+			return false;
1112
+		}
1113
+		return $this->_fields[$field_name];
1114
+	}
1115
+
1116
+
1117
+
1118
+	/**
1119
+	 * To be used in template to immediately echo out the value, and format it for output.
1120
+	 * Eg, should call stripslashes and whatnot before echoing
1121
+	 *
1122
+	 * @param string $field_name      the name of the field as it appears in the DB
1123
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1124
+	 *                                (in cases where the same property may be used for different outputs
1125
+	 *                                - i.e. datetime, money etc.)
1126
+	 * @return void
1127
+	 * @throws \EE_Error
1128
+	 */
1129
+	public function e($field_name, $extra_cache_ref = null)
1130
+	{
1131
+		echo $this->get_pretty($field_name, $extra_cache_ref);
1132
+	}
1133
+
1134
+
1135
+
1136
+	/**
1137
+	 * Exactly like e(), echoes out the field, but sets its schema to 'form_input', so that it
1138
+	 * can be easily used as the value of form input.
1139
+	 *
1140
+	 * @param string $field_name
1141
+	 * @return void
1142
+	 * @throws \EE_Error
1143
+	 */
1144
+	public function f($field_name)
1145
+	{
1146
+		$this->e($field_name, 'form_input');
1147
+	}
1148
+
1149
+
1150
+
1151
+	/**
1152
+	 * Gets a pretty view of the field's value. $extra_cache_ref can specify different formats for this.
1153
+	 * The $extra_cache_ref will be passed to the model field's prepare_for_pretty_echoing, so consult the field's class
1154
+	 * to see what options are available.
1155
+	 * @param string $field_name
1156
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1157
+	 *                                (in cases where the same property may be used for different outputs
1158
+	 *                                - i.e. datetime, money etc.)
1159
+	 * @return mixed
1160
+	 * @throws \EE_Error
1161
+	 */
1162
+	public function get_pretty($field_name, $extra_cache_ref = null)
1163
+	{
1164
+		return $this->_get_cached_property($field_name, true, $extra_cache_ref);
1165
+	}
1166
+
1167
+
1168
+
1169
+	/**
1170
+	 * This simply returns the datetime for the given field name
1171
+	 * Note: this protected function is called by the wrapper get_date or get_time or get_datetime functions
1172
+	 * (and the equivalent e_date, e_time, e_datetime).
1173
+	 *
1174
+	 * @access   protected
1175
+	 * @param string   $field_name   Field on the instantiated EE_Base_Class child object
1176
+	 * @param string   $dt_frmt      valid datetime format used for date
1177
+	 *                               (if '' then we just use the default on the field,
1178
+	 *                               if NULL we use the last-used format)
1179
+	 * @param string   $tm_frmt      Same as above except this is for time format
1180
+	 * @param string   $date_or_time if NULL then both are returned, otherwise "D" = only date and "T" = only time.
1181
+	 * @param  boolean $echo         Whether the dtt is echoing using pretty echoing or just returned using vanilla get
1182
+	 * @return string|bool|EE_Error string on success, FALSE on fail, or EE_Error Exception is thrown
1183
+	 *                               if field is not a valid dtt field, or void if echoing
1184
+	 * @throws \EE_Error
1185
+	 */
1186
+	protected function _get_datetime($field_name, $dt_frmt = '', $tm_frmt = '', $date_or_time = '', $echo = false)
1187
+	{
1188
+		// clear cached property
1189
+		$this->_clear_cached_property($field_name);
1190
+		//reset format properties because they are used in get()
1191
+		$this->_dt_frmt = $dt_frmt !== '' ? $dt_frmt : $this->_dt_frmt;
1192
+		$this->_tm_frmt = $tm_frmt !== '' ? $tm_frmt : $this->_tm_frmt;
1193
+		if ($echo) {
1194
+			$this->e($field_name, $date_or_time);
1195
+			return '';
1196
+		}
1197
+		return $this->get($field_name, $date_or_time);
1198
+	}
1199
+
1200
+
1201
+
1202
+	/**
1203
+	 * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the date
1204
+	 * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1205
+	 * other echoes the pretty value for dtt)
1206
+	 *
1207
+	 * @param  string $field_name name of model object datetime field holding the value
1208
+	 * @param  string $format     format for the date returned (if NULL we use default in dt_frmt property)
1209
+	 * @return string            datetime value formatted
1210
+	 * @throws \EE_Error
1211
+	 */
1212
+	public function get_date($field_name, $format = '')
1213
+	{
1214
+		return $this->_get_datetime($field_name, $format, null, 'D');
1215
+	}
1216
+
1217
+
1218
+
1219
+	/**
1220
+	 * @param      $field_name
1221
+	 * @param string $format
1222
+	 * @throws \EE_Error
1223
+	 */
1224
+	public function e_date($field_name, $format = '')
1225
+	{
1226
+		$this->_get_datetime($field_name, $format, null, 'D', true);
1227
+	}
1228
+
1229
+
1230
+
1231
+	/**
1232
+	 * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the time
1233
+	 * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1234
+	 * other echoes the pretty value for dtt)
1235
+	 *
1236
+	 * @param  string $field_name name of model object datetime field holding the value
1237
+	 * @param  string $format     format for the time returned ( if NULL we use default in tm_frmt property)
1238
+	 * @return string             datetime value formatted
1239
+	 * @throws \EE_Error
1240
+	 */
1241
+	public function get_time($field_name, $format = '')
1242
+	{
1243
+		return $this->_get_datetime($field_name, null, $format, 'T');
1244
+	}
1245
+
1246
+
1247
+
1248
+	/**
1249
+	 * @param      $field_name
1250
+	 * @param string $format
1251
+	 * @throws \EE_Error
1252
+	 */
1253
+	public function e_time($field_name, $format = '')
1254
+	{
1255
+		$this->_get_datetime($field_name, null, $format, 'T', true);
1256
+	}
1257
+
1258
+
1259
+
1260
+	/**
1261
+	 * below are wrapper functions for the various datetime outputs that can be obtained for returning the date AND
1262
+	 * time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1263
+	 * other echoes the pretty value for dtt)
1264
+	 *
1265
+	 * @param  string $field_name name of model object datetime field holding the value
1266
+	 * @param  string $dt_frmt    format for the date returned (if NULL we use default in dt_frmt property)
1267
+	 * @param  string $tm_frmt    format for the time returned (if NULL we use default in tm_frmt property)
1268
+	 * @return string             datetime value formatted
1269
+	 * @throws \EE_Error
1270
+	 */
1271
+	public function get_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1272
+	{
1273
+		return $this->_get_datetime($field_name, $dt_frmt, $tm_frmt);
1274
+	}
1275
+
1276
+
1277
+
1278
+	/**
1279
+	 * @param string $field_name
1280
+	 * @param string $dt_frmt
1281
+	 * @param string $tm_frmt
1282
+	 * @throws \EE_Error
1283
+	 */
1284
+	public function e_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1285
+	{
1286
+		$this->_get_datetime($field_name, $dt_frmt, $tm_frmt, null, true);
1287
+	}
1288
+
1289
+
1290
+
1291
+	/**
1292
+	 * Get the i8ln value for a date using the WordPress @see date_i18n function.
1293
+	 *
1294
+	 * @param string $field_name The EE_Datetime_Field reference for the date being retrieved.
1295
+	 * @param string $format     PHP valid date/time string format.  If none is provided then the internal set format
1296
+	 *                           on the object will be used.
1297
+	 * @return string Date and time string in set locale or false if no field exists for the given
1298
+	 * @throws \EE_Error
1299
+	 *                           field name.
1300
+	 */
1301
+	public function get_i18n_datetime($field_name, $format = '')
1302
+	{
1303
+		$format = empty($format) ? $this->_dt_frmt . ' ' . $this->_tm_frmt : $format;
1304
+		return date_i18n(
1305
+			$format,
1306
+			EEH_DTT_Helper::get_timestamp_with_offset($this->get_raw($field_name), $this->_timezone)
1307
+		);
1308
+	}
1309
+
1310
+
1311
+
1312
+	/**
1313
+	 * This method validates whether the given field name is a valid field on the model object as well as it is of a
1314
+	 * type EE_Datetime_Field.  On success there will be returned the field settings.  On fail an EE_Error exception is
1315
+	 * thrown.
1316
+	 *
1317
+	 * @param  string $field_name The field name being checked
1318
+	 * @throws EE_Error
1319
+	 * @return EE_Datetime_Field
1320
+	 */
1321
+	protected function _get_dtt_field_settings($field_name)
1322
+	{
1323
+		$field = $this->get_model()->field_settings_for($field_name);
1324
+		//check if field is dtt
1325
+		if ($field instanceof EE_Datetime_Field) {
1326
+			return $field;
1327
+		} else {
1328
+			throw new EE_Error(sprintf(__('The field name "%s" has been requested for the EE_Base_Class datetime functions and it is not a valid EE_Datetime_Field.  Please check the spelling of the field and make sure it has been setup as a EE_Datetime_Field in the %s model constructor',
1329
+				'event_espresso'), $field_name, self::_get_model_classname(get_class($this))));
1330
+		}
1331
+	}
1332
+
1333
+
1334
+
1335
+
1336
+	/**
1337
+	 * NOTE ABOUT BELOW:
1338
+	 * These convenience date and time setters are for setting date and time independently.  In other words you might
1339
+	 * want to change the time on a datetime_field but leave the date the same (or vice versa). IF on the other hand
1340
+	 * you want to set both date and time at the same time, you can just use the models default set($fieldname,$value)
1341
+	 * method and make sure you send the entire datetime value for setting.
1342
+	 */
1343
+	/**
1344
+	 * sets the time on a datetime property
1345
+	 *
1346
+	 * @access protected
1347
+	 * @param string|Datetime $time      a valid time string for php datetime functions (or DateTime object)
1348
+	 * @param string          $fieldname the name of the field the time is being set on (must match a EE_Datetime_Field)
1349
+	 * @throws \EE_Error
1350
+	 */
1351
+	protected function _set_time_for($time, $fieldname)
1352
+	{
1353
+		$this->_set_date_time('T', $time, $fieldname);
1354
+	}
1355
+
1356
+
1357
+
1358
+	/**
1359
+	 * sets the date on a datetime property
1360
+	 *
1361
+	 * @access protected
1362
+	 * @param string|DateTime $date      a valid date string for php datetime functions ( or DateTime object)
1363
+	 * @param string          $fieldname the name of the field the date is being set on (must match a EE_Datetime_Field)
1364
+	 * @throws \EE_Error
1365
+	 */
1366
+	protected function _set_date_for($date, $fieldname)
1367
+	{
1368
+		$this->_set_date_time('D', $date, $fieldname);
1369
+	}
1370
+
1371
+
1372
+
1373
+	/**
1374
+	 * This takes care of setting a date or time independently on a given model object property. This method also
1375
+	 * verifies that the given fieldname matches a model object property and is for a EE_Datetime_Field field
1376
+	 *
1377
+	 * @access protected
1378
+	 * @param string          $what           "T" for time, 'B' for both, 'D' for Date.
1379
+	 * @param string|DateTime $datetime_value A valid Date or Time string (or DateTime object)
1380
+	 * @param string          $fieldname      the name of the field the date OR time is being set on (must match a
1381
+	 *                                        EE_Datetime_Field property)
1382
+	 * @throws \EE_Error
1383
+	 */
1384
+	protected function _set_date_time($what = 'T', $datetime_value, $fieldname)
1385
+	{
1386
+		$field = $this->_get_dtt_field_settings($fieldname);
1387
+		$field->set_timezone($this->_timezone);
1388
+		$field->set_date_format($this->_dt_frmt);
1389
+		$field->set_time_format($this->_tm_frmt);
1390
+		switch ($what) {
1391
+			case 'T' :
1392
+				$this->_fields[$fieldname] = $field->prepare_for_set_with_new_time(
1393
+					$datetime_value,
1394
+					$this->_fields[$fieldname]
1395
+				);
1396
+				break;
1397
+			case 'D' :
1398
+				$this->_fields[$fieldname] = $field->prepare_for_set_with_new_date(
1399
+					$datetime_value,
1400
+					$this->_fields[$fieldname]
1401
+				);
1402
+				break;
1403
+			case 'B' :
1404
+				$this->_fields[$fieldname] = $field->prepare_for_set($datetime_value);
1405
+				break;
1406
+		}
1407
+		$this->_clear_cached_property($fieldname);
1408
+	}
1409
+
1410
+
1411
+
1412
+	/**
1413
+	 * This will return a timestamp for the website timezone but ONLY when the current website timezone is different
1414
+	 * than the timezone set for the website. NOTE, this currently only works well with methods that return values.  If
1415
+	 * you use it with methods that echo values the $_timestamp property may not get reset to its original value and
1416
+	 * that could lead to some unexpected results!
1417
+	 *
1418
+	 * @access public
1419
+	 * @param string               $field_name This is the name of the field on the object that contains the date/time
1420
+	 *                                         value being returned.
1421
+	 * @param string               $callback   must match a valid method in this class (defaults to get_datetime)
1422
+	 * @param mixed (array|string) $args       This is the arguments that will be passed to the callback.
1423
+	 * @param string               $prepend    You can include something to prepend on the timestamp
1424
+	 * @param string               $append     You can include something to append on the timestamp
1425
+	 * @throws EE_Error
1426
+	 * @return string timestamp
1427
+	 */
1428
+	public function display_in_my_timezone(
1429
+		$field_name,
1430
+		$callback = 'get_datetime',
1431
+		$args = null,
1432
+		$prepend = '',
1433
+		$append = ''
1434
+	) {
1435
+		$timezone = EEH_DTT_Helper::get_timezone();
1436
+		if ($timezone === $this->_timezone) {
1437
+			return '';
1438
+		}
1439
+		$original_timezone = $this->_timezone;
1440
+		$this->set_timezone($timezone);
1441
+		$fn = (array)$field_name;
1442
+		$args = array_merge($fn, (array)$args);
1443
+		if ( ! method_exists($this, $callback)) {
1444
+			throw new EE_Error(
1445
+				sprintf(
1446
+					__(
1447
+						'The method named "%s" given as the callback param in "display_in_my_timezone" does not exist.  Please check your spelling',
1448
+						'event_espresso'
1449
+					),
1450
+					$callback
1451
+				)
1452
+			);
1453
+		}
1454
+		$args = (array)$args;
1455
+		$return = $prepend . call_user_func_array(array($this, $callback), $args) . $append;
1456
+		$this->set_timezone($original_timezone);
1457
+		return $return;
1458
+	}
1459
+
1460
+
1461
+
1462
+	/**
1463
+	 * Deletes this model object.
1464
+	 * This calls the `EE_Base_Class::_delete` method.  Child classes wishing to change default behaviour should
1465
+	 * override
1466
+	 * `EE_Base_Class::_delete` NOT this class.
1467
+	 *
1468
+	 * @return boolean | int
1469
+	 * @throws \EE_Error
1470
+	 */
1471
+	public function delete()
1472
+	{
1473
+		/**
1474
+		 * Called just before the `EE_Base_Class::_delete` method call.
1475
+		 * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1476
+		 * should be aware that `_delete` may not always result in a permanent delete.  For example, `EE_Soft_Delete_Base_Class::_delete`
1477
+		 * soft deletes (trash) the object and does not permanently delete it.
1478
+		 *
1479
+		 * @param EE_Base_Class $model_object about to be 'deleted'
1480
+		 */
1481
+		do_action('AHEE__EE_Base_Class__delete__before', $this);
1482
+		$result = $this->_delete();
1483
+		/**
1484
+		 * Called just after the `EE_Base_Class::_delete` method call.
1485
+		 * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1486
+		 * should be aware that `_delete` may not always result in a permanent delete.  For example `EE_Soft_Base_Class::_delete`
1487
+		 * soft deletes (trash) the object and does not permanently delete it.
1488
+		 *
1489
+		 * @param EE_Base_Class $model_object that was just 'deleted'
1490
+		 * @param boolean       $result
1491
+		 */
1492
+		do_action('AHEE__EE_Base_Class__delete__end', $this, $result);
1493
+		return $result;
1494
+	}
1495
+
1496
+
1497
+
1498
+	/**
1499
+	 * Calls the specific delete method for the instantiated class.
1500
+	 * This method is called by the public `EE_Base_Class::delete` method.  Any child classes desiring to override
1501
+	 * default functionality for "delete" (which is to call `permanently_delete`) should override this method NOT
1502
+	 * `EE_Base_Class::delete`
1503
+	 *
1504
+	 * @return bool|int
1505
+	 * @throws \EE_Error
1506
+	 */
1507
+	protected function _delete()
1508
+	{
1509
+		return $this->delete_permanently();
1510
+	}
1511
+
1512
+
1513
+
1514
+	/**
1515
+	 * Deletes this model object permanently from db (but keep in mind related models my block the delete and return an
1516
+	 * error)
1517
+	 *
1518
+	 * @return bool | int
1519
+	 * @throws \EE_Error
1520
+	 */
1521
+	public function delete_permanently()
1522
+	{
1523
+		/**
1524
+		 * Called just before HARD deleting a model object
1525
+		 *
1526
+		 * @param EE_Base_Class $model_object about to be 'deleted'
1527
+		 */
1528
+		do_action('AHEE__EE_Base_Class__delete_permanently__before', $this);
1529
+		$model = $this->get_model();
1530
+		$result = $model->delete_permanently_by_ID($this->ID());
1531
+		$this->refresh_cache_of_related_objects();
1532
+		/**
1533
+		 * Called just after HARD deleting a model object
1534
+		 *
1535
+		 * @param EE_Base_Class $model_object that was just 'deleted'
1536
+		 * @param boolean       $result
1537
+		 */
1538
+		do_action('AHEE__EE_Base_Class__delete_permanently__end', $this, $result);
1539
+		return $result;
1540
+	}
1541
+
1542
+
1543
+
1544
+	/**
1545
+	 * When this model object is deleted, it may still be cached on related model objects. This clears the cache of
1546
+	 * related model objects
1547
+	 *
1548
+	 * @throws \EE_Error
1549
+	 */
1550
+	public function refresh_cache_of_related_objects()
1551
+	{
1552
+		$model = $this->get_model();
1553
+		foreach ($model->relation_settings() as $relation_name => $relation_obj) {
1554
+			if ( ! empty($this->_model_relations[$relation_name])) {
1555
+				$related_objects = $this->_model_relations[$relation_name];
1556
+				if ($relation_obj instanceof EE_Belongs_To_Relation) {
1557
+					//this relation only stores a single model object, not an array
1558
+					//but let's make it consistent
1559
+					$related_objects = array($related_objects);
1560
+				}
1561
+				foreach ($related_objects as $related_object) {
1562
+					//only refresh their cache if they're in memory
1563
+					if ($related_object instanceof EE_Base_Class) {
1564
+						$related_object->clear_cache($model->get_this_model_name(), $this);
1565
+					}
1566
+				}
1567
+			}
1568
+		}
1569
+	}
1570
+
1571
+
1572
+
1573
+	/**
1574
+	 *        Saves this object to the database. An array may be supplied to set some values on this
1575
+	 * object just before saving.
1576
+	 *
1577
+	 * @access public
1578
+	 * @param array $set_cols_n_values keys are field names, values are their new values,
1579
+	 *                                 if provided during the save() method (often client code will change the fields'
1580
+	 *                                 values before calling save)
1581
+	 * @throws \EE_Error
1582
+	 * @return int , 1 on a successful update, the ID of the new entry on insert; 0 on failure or if the model object
1583
+	 *                                 isn't allowed to persist (as determined by EE_Base_Class::allow_persist())
1584
+	 */
1585
+	public function save($set_cols_n_values = array())
1586
+	{
1587
+		$model = $this->get_model();
1588
+		/**
1589
+		 * Filters the fields we're about to save on the model object
1590
+		 *
1591
+		 * @param array         $set_cols_n_values
1592
+		 * @param EE_Base_Class $model_object
1593
+		 */
1594
+		$set_cols_n_values = (array)apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values,
1595
+			$this);
1596
+		//set attributes as provided in $set_cols_n_values
1597
+		foreach ($set_cols_n_values as $column => $value) {
1598
+			$this->set($column, $value);
1599
+		}
1600
+		// no changes ? then don't do anything
1601
+		if (! $this->_has_changes && $this->ID() && $model->get_primary_key_field()->is_auto_increment()) {
1602
+			return 0;
1603
+		}
1604
+		/**
1605
+		 * Saving a model object.
1606
+		 * Before we perform a save, this action is fired.
1607
+		 *
1608
+		 * @param EE_Base_Class $model_object the model object about to be saved.
1609
+		 */
1610
+		do_action('AHEE__EE_Base_Class__save__begin', $this);
1611
+		if ( ! $this->allow_persist()) {
1612
+			return 0;
1613
+		}
1614
+		//now get current attribute values
1615
+		$save_cols_n_values = $this->_fields;
1616
+		//if the object already has an ID, update it. Otherwise, insert it
1617
+		//also: change the assumption about values passed to the model NOT being prepare dby the model object. They have been
1618
+		$old_assumption_concerning_value_preparation = $model
1619
+															->get_assumption_concerning_values_already_prepared_by_model_object();
1620
+		$model->assume_values_already_prepared_by_model_object(true);
1621
+		//does this model have an autoincrement PK?
1622
+		if ($model->has_primary_key_field()) {
1623
+			if ($model->get_primary_key_field()->is_auto_increment()) {
1624
+				//ok check if it's set, if so: update; if not, insert
1625
+				if ( ! empty($save_cols_n_values[$model->primary_key_name()])) {
1626
+					$results = $model->update_by_ID($save_cols_n_values, $this->ID());
1627
+				} else {
1628
+					unset($save_cols_n_values[$model->primary_key_name()]);
1629
+					$results = $model->insert($save_cols_n_values);
1630
+					if ($results) {
1631
+						//if successful, set the primary key
1632
+						//but don't use the normal SET method, because it will check if
1633
+						//an item with the same ID exists in the mapper & db, then
1634
+						//will find it in the db (because we just added it) and THAT object
1635
+						//will get added to the mapper before we can add this one!
1636
+						//but if we just avoid using the SET method, all that headache can be avoided
1637
+						$pk_field_name = $model->primary_key_name();
1638
+						$this->_fields[$pk_field_name] = $results;
1639
+						$this->_clear_cached_property($pk_field_name);
1640
+						$model->add_to_entity_map($this);
1641
+						$this->_update_cached_related_model_objs_fks();
1642
+					}
1643
+				}
1644
+			} else {//PK is NOT auto-increment
1645
+				//so check if one like it already exists in the db
1646
+				if ($model->exists_by_ID($this->ID())) {
1647
+					if (WP_DEBUG && ! $this->in_entity_map()) {
1648
+						throw new EE_Error(
1649
+							sprintf(
1650
+								__('Using a model object %1$s that is NOT in the entity map, can lead to unexpected errors. You should either: %4$s 1. Put it in the entity mapper by calling %2$s %4$s 2. Discard this model object and use what is in the entity mapper %4$s 3. Fetch from the database using %3$s',
1651
+									'event_espresso'),
1652
+								get_class($this),
1653
+								get_class($model) . '::instance()->add_to_entity_map()',
1654
+								get_class($model) . '::instance()->get_one_by_ID()',
1655
+								'<br />'
1656
+							)
1657
+						);
1658
+					}
1659
+					$results = $model->update_by_ID($save_cols_n_values, $this->ID());
1660
+				} else {
1661
+					$results = $model->insert($save_cols_n_values);
1662
+					$this->_update_cached_related_model_objs_fks();
1663
+				}
1664
+			}
1665
+		} else {//there is NO primary key
1666
+			$already_in_db = false;
1667
+			foreach ($model->unique_indexes() as $index) {
1668
+				$uniqueness_where_params = array_intersect_key($save_cols_n_values, $index->fields());
1669
+				if ($model->exists(array($uniqueness_where_params))) {
1670
+					$already_in_db = true;
1671
+				}
1672
+			}
1673
+			if ($already_in_db) {
1674
+				$combined_pk_fields_n_values = array_intersect_key($save_cols_n_values,
1675
+					$model->get_combined_primary_key_fields());
1676
+				$results = $model->update($save_cols_n_values, $combined_pk_fields_n_values);
1677
+			} else {
1678
+				$results = $model->insert($save_cols_n_values);
1679
+			}
1680
+		}
1681
+		//restore the old assumption about values being prepared by the model object
1682
+		$model
1683
+			 ->assume_values_already_prepared_by_model_object($old_assumption_concerning_value_preparation);
1684
+		/**
1685
+		 * After saving the model object this action is called
1686
+		 *
1687
+		 * @param EE_Base_Class $model_object which was just saved
1688
+		 * @param boolean|int   $results      if it were updated, TRUE or FALSE; if it were newly inserted
1689
+		 *                                    the new ID (or 0 if an error occurred and it wasn't updated)
1690
+		 */
1691
+		do_action('AHEE__EE_Base_Class__save__end', $this, $results);
1692
+		$this->_has_changes = false;
1693
+		return $results;
1694
+	}
1695
+
1696
+
1697
+
1698
+	/**
1699
+	 * Updates the foreign key on related models objects pointing to this to have this model object's ID
1700
+	 * as their foreign key.  If the cached related model objects already exist in the db, saves them (so that the DB
1701
+	 * is consistent) Especially useful in case we JUST added this model object ot the database and we want to let its
1702
+	 * cached relations with foreign keys to it know about that change. Eg: we've created a transaction but haven't
1703
+	 * saved it to the db. We also create a registration and don't save it to the DB, but we DO cache it on the
1704
+	 * transaction. Now, when we save the transaction, the registration's TXN_ID will be automatically updated, whether
1705
+	 * or not they exist in the DB (if they do, their DB records will be automatically updated)
1706
+	 *
1707
+	 * @return void
1708
+	 * @throws \EE_Error
1709
+	 */
1710
+	protected function _update_cached_related_model_objs_fks()
1711
+	{
1712
+		$model = $this->get_model();
1713
+		foreach ($model->relation_settings() as $relation_name => $relation_obj) {
1714
+			if ($relation_obj instanceof EE_Has_Many_Relation) {
1715
+				foreach ($this->get_all_from_cache($relation_name) as $related_model_obj_in_cache) {
1716
+					$fk_to_this = $related_model_obj_in_cache->get_model()->get_foreign_key_to(
1717
+						$model->get_this_model_name()
1718
+					);
1719
+					$related_model_obj_in_cache->set($fk_to_this->get_name(), $this->ID());
1720
+					if ($related_model_obj_in_cache->ID()) {
1721
+						$related_model_obj_in_cache->save();
1722
+					}
1723
+				}
1724
+			}
1725
+		}
1726
+	}
1727
+
1728
+
1729
+
1730
+	/**
1731
+	 * Saves this model object and its NEW cached relations to the database.
1732
+	 * (Meaning, for now, IT DOES NOT WORK if the cached items already exist in the DB.
1733
+	 * In order for that to work, we would need to mark model objects as dirty/clean...
1734
+	 * because otherwise, there's a potential for infinite looping of saving
1735
+	 * Saves the cached related model objects, and ensures the relation between them
1736
+	 * and this object and properly setup
1737
+	 *
1738
+	 * @return int ID of new model object on save; 0 on failure+
1739
+	 * @throws \EE_Error
1740
+	 */
1741
+	public function save_new_cached_related_model_objs()
1742
+	{
1743
+		//make sure this has been saved
1744
+		if ( ! $this->ID()) {
1745
+			$id = $this->save();
1746
+		} else {
1747
+			$id = $this->ID();
1748
+		}
1749
+		//now save all the NEW cached model objects  (ie they don't exist in the DB)
1750
+		foreach ($this->get_model()->relation_settings() as $relationName => $relationObj) {
1751
+			if ($this->_model_relations[$relationName]) {
1752
+				//is this a relation where we should expect just ONE related object (ie, EE_Belongs_To_relation)
1753
+				//or MANY related objects (ie, EE_HABTM_Relation or EE_Has_Many_Relation)?
1754
+				if ($relationObj instanceof EE_Belongs_To_Relation) {
1755
+					//add a relation to that relation type (which saves the appropriate thing in the process)
1756
+					//but ONLY if it DOES NOT exist in the DB
1757
+					/* @var $related_model_obj EE_Base_Class */
1758
+					$related_model_obj = $this->_model_relations[$relationName];
1759
+					//					if( ! $related_model_obj->ID()){
1760
+					$this->_add_relation_to($related_model_obj, $relationName);
1761
+					$related_model_obj->save_new_cached_related_model_objs();
1762
+					//					}
1763
+				} else {
1764
+					foreach ($this->_model_relations[$relationName] as $related_model_obj) {
1765
+						//add a relation to that relation type (which saves the appropriate thing in the process)
1766
+						//but ONLY if it DOES NOT exist in the DB
1767
+						//						if( ! $related_model_obj->ID()){
1768
+						$this->_add_relation_to($related_model_obj, $relationName);
1769
+						$related_model_obj->save_new_cached_related_model_objs();
1770
+						//						}
1771
+					}
1772
+				}
1773
+			}
1774
+		}
1775
+		return $id;
1776
+	}
1777
+
1778
+
1779
+
1780
+	/**
1781
+	 * for getting a model while instantiated.
1782
+	 *
1783
+	 * @return \EEM_Base | \EEM_CPT_Base
1784
+	 */
1785
+	public function get_model()
1786
+	{
1787
+		if( ! $this->_model){
1788
+			$modelName = self::_get_model_classname(get_class($this));
1789
+			$this->_model = self::_get_model_instance_with_name($modelName, $this->_timezone);
1790
+		} else {
1791
+			$this->_model->set_timezone($this->_timezone);
1792
+		}
1793
+
1794
+		return $this->_model;
1795
+	}
1796
+
1797
+
1798
+
1799
+	/**
1800
+	 * @param $props_n_values
1801
+	 * @param $classname
1802
+	 * @return mixed bool|EE_Base_Class|EEM_CPT_Base
1803
+	 * @throws \EE_Error
1804
+	 */
1805
+	protected static function _get_object_from_entity_mapper($props_n_values, $classname)
1806
+	{
1807
+		//TODO: will not work for Term_Relationships because they have no PK!
1808
+		$primary_id_ref = self::_get_primary_key_name($classname);
1809
+		if (array_key_exists($primary_id_ref, $props_n_values) && ! empty($props_n_values[$primary_id_ref])) {
1810
+			$id = $props_n_values[$primary_id_ref];
1811
+			return self::_get_model($classname)->get_from_entity_map($id);
1812
+		}
1813
+		return false;
1814
+	}
1815
+
1816
+
1817
+
1818
+	/**
1819
+	 * This is called by child static "new_instance" method and we'll check to see if there is an existing db entry for
1820
+	 * the primary key (if present in incoming values). If there is a key in the incoming array that matches the
1821
+	 * primary key for the model AND it is not null, then we check the db. If there's a an object we return it.  If not
1822
+	 * we return false.
1823
+	 *
1824
+	 * @param  array  $props_n_values   incoming array of properties and their values
1825
+	 * @param  string $classname        the classname of the child class
1826
+	 * @param null    $timezone
1827
+	 * @param array   $date_formats     incoming date_formats in an array where the first value is the
1828
+	 *                                  date_format and the second value is the time format
1829
+	 * @return mixed (EE_Base_Class|bool)
1830
+	 * @throws \EE_Error
1831
+	 */
1832
+	protected static function _check_for_object($props_n_values, $classname, $timezone = null, $date_formats = array())
1833
+	{
1834
+		$existing = null;
1835
+		$model = self::_get_model($classname, $timezone);
1836
+		if ($model->has_primary_key_field()) {
1837
+			$primary_id_ref = self::_get_primary_key_name($classname);
1838
+			if (array_key_exists($primary_id_ref, $props_n_values)
1839
+				&& ! empty($props_n_values[$primary_id_ref])
1840
+			) {
1841
+				$existing = $model->get_one_by_ID(
1842
+					$props_n_values[$primary_id_ref]
1843
+				);
1844
+			}
1845
+		} elseif ($model->has_all_combined_primary_key_fields($props_n_values)) {
1846
+			//no primary key on this model, but there's still a matching item in the DB
1847
+			$existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1848
+				self::_get_model($classname, $timezone)->get_index_primary_key_string($props_n_values)
1849
+			);
1850
+		}
1851
+		if ($existing) {
1852
+			//set date formats if present before setting values
1853
+			if ( ! empty($date_formats) && is_array($date_formats)) {
1854
+				$existing->set_date_format($date_formats[0]);
1855
+				$existing->set_time_format($date_formats[1]);
1856
+			} else {
1857
+				//set default formats for date and time
1858
+				$existing->set_date_format(get_option('date_format'));
1859
+				$existing->set_time_format(get_option('time_format'));
1860
+			}
1861
+			foreach ($props_n_values as $property => $field_value) {
1862
+				$existing->set($property, $field_value);
1863
+			}
1864
+			return $existing;
1865
+		} else {
1866
+			return false;
1867
+		}
1868
+	}
1869
+
1870
+
1871
+
1872
+	/**
1873
+	 * Gets the EEM_*_Model for this class
1874
+	 *
1875
+	 * @access public now, as this is more convenient
1876
+	 * @param      $classname
1877
+	 * @param null $timezone
1878
+	 * @throws EE_Error
1879
+	 * @return EEM_Base
1880
+	 */
1881
+	protected static function _get_model($classname, $timezone = null)
1882
+	{
1883
+		//find model for this class
1884
+		if ( ! $classname) {
1885
+			throw new EE_Error(
1886
+				sprintf(
1887
+					__(
1888
+						"What were you thinking calling _get_model(%s)?? You need to specify the class name",
1889
+						"event_espresso"
1890
+					),
1891
+					$classname
1892
+				)
1893
+			);
1894
+		}
1895
+		$modelName = self::_get_model_classname($classname);
1896
+		return self::_get_model_instance_with_name($modelName, $timezone);
1897
+	}
1898
+
1899
+
1900
+
1901
+	/**
1902
+	 * Gets the model instance (eg instance of EEM_Attendee) given its classname (eg EE_Attendee)
1903
+	 *
1904
+	 * @param string $model_classname
1905
+	 * @param null   $timezone
1906
+	 * @return EEM_Base
1907
+	 */
1908
+	protected static function _get_model_instance_with_name($model_classname, $timezone = null)
1909
+	{
1910
+		$model_classname = str_replace('EEM_', '', $model_classname);
1911
+		$model = EE_Registry::instance()->load_model($model_classname);
1912
+		$model->set_timezone($timezone);
1913
+		return $model;
1914
+	}
1915
+
1916
+
1917
+
1918
+	/**
1919
+	 * If a model name is provided (eg Registration), gets the model classname for that model.
1920
+	 * Also works if a model class's classname is provided (eg EE_Registration).
1921
+	 *
1922
+	 * @param null $model_name
1923
+	 * @return string like EEM_Attendee
1924
+	 */
1925
+	private static function _get_model_classname($model_name = null)
1926
+	{
1927
+		if (strpos($model_name, "EE_") === 0) {
1928
+			$model_classname = str_replace("EE_", "EEM_", $model_name);
1929
+		} else {
1930
+			$model_classname = "EEM_" . $model_name;
1931
+		}
1932
+		return $model_classname;
1933
+	}
1934
+
1935
+
1936
+
1937
+	/**
1938
+	 * returns the name of the primary key attribute
1939
+	 *
1940
+	 * @param null $classname
1941
+	 * @throws EE_Error
1942
+	 * @return string
1943
+	 */
1944
+	protected static function _get_primary_key_name($classname = null)
1945
+	{
1946
+		if ( ! $classname) {
1947
+			throw new EE_Error(
1948
+				sprintf(
1949
+					__("What were you thinking calling _get_primary_key_name(%s)", "event_espresso"),
1950
+					$classname
1951
+				)
1952
+			);
1953
+		}
1954
+		return self::_get_model($classname)->get_primary_key_field()->get_name();
1955
+	}
1956
+
1957
+
1958
+
1959
+	/**
1960
+	 * Gets the value of the primary key.
1961
+	 * If the object hasn't yet been saved, it should be whatever the model field's default was
1962
+	 * (eg, if this were the EE_Event class, look at the primary key field on EEM_Event and see what its default value
1963
+	 * is. Usually defaults for integer primary keys are 0; string primary keys are usually NULL).
1964
+	 *
1965
+	 * @return mixed, if the primary key is of type INT it'll be an int. Otherwise it could be a string
1966
+	 * @throws \EE_Error
1967
+	 */
1968
+	public function ID()
1969
+	{
1970
+		$model = $this->get_model();
1971
+		//now that we know the name of the variable, use a variable variable to get its value and return its
1972
+		if ($model->has_primary_key_field()) {
1973
+			return $this->_fields[$model->primary_key_name()];
1974
+		} else {
1975
+			return $model->get_index_primary_key_string($this->_fields);
1976
+		}
1977
+	}
1978
+
1979
+
1980
+
1981
+	/**
1982
+	 * Adds a relationship to the specified EE_Base_Class object, given the relationship's name. Eg, if the current
1983
+	 * model is related to a group of events, the $relationName should be 'Event', and should be a key in the EE
1984
+	 * Model's $_model_relations array. If this model object doesn't exist in the DB, just caches the related thing
1985
+	 *
1986
+	 * @param mixed  $otherObjectModelObjectOrID       EE_Base_Class or the ID of the other object
1987
+	 * @param string $relationName                     eg 'Events','Question',etc.
1988
+	 *                                                 an attendee to a group, you also want to specify which role they
1989
+	 *                                                 will have in that group. So you would use this parameter to
1990
+	 *                                                 specify array('role-column-name'=>'role-id')
1991
+	 * @param array  $extra_join_model_fields_n_values You can optionally include an array of key=>value pairs that
1992
+	 *                                                 allow you to further constrict the relation to being added.
1993
+	 *                                                 However, keep in mind that the columns (keys) given must match a
1994
+	 *                                                 column on the JOIN table and currently only the HABTM models
1995
+	 *                                                 accept these additional conditions.  Also remember that if an
1996
+	 *                                                 exact match isn't found for these extra cols/val pairs, then a
1997
+	 *                                                 NEW row is created in the join table.
1998
+	 * @param null   $cache_id
1999
+	 * @throws EE_Error
2000
+	 * @return EE_Base_Class the object the relation was added to
2001
+	 */
2002
+	public function _add_relation_to(
2003
+		$otherObjectModelObjectOrID,
2004
+		$relationName,
2005
+		$extra_join_model_fields_n_values = array(),
2006
+		$cache_id = null
2007
+	) {
2008
+		$model = $this->get_model();
2009
+		//if this thing exists in the DB, save the relation to the DB
2010
+		if ($this->ID()) {
2011
+			$otherObject = $model
2012
+								->add_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
2013
+									$extra_join_model_fields_n_values);
2014
+			//clear cache so future get_many_related and get_first_related() return new results.
2015
+			$this->clear_cache($relationName, $otherObject, true);
2016
+			if ($otherObject instanceof EE_Base_Class) {
2017
+				$otherObject->clear_cache($model->get_this_model_name(), $this);
2018
+			}
2019
+		} else {
2020
+			//this thing doesn't exist in the DB,  so just cache it
2021
+			if ( ! $otherObjectModelObjectOrID instanceof EE_Base_Class) {
2022
+				throw new EE_Error(sprintf(
2023
+					__('Before a model object is saved to the database, calls to _add_relation_to must be passed an actual object, not just an ID. You provided %s as the model object to a %s',
2024
+						'event_espresso'),
2025
+					$otherObjectModelObjectOrID,
2026
+					get_class($this)
2027
+				));
2028
+			} else {
2029
+				$otherObject = $otherObjectModelObjectOrID;
2030
+			}
2031
+			$this->cache($relationName, $otherObjectModelObjectOrID, $cache_id);
2032
+		}
2033
+		if ($otherObject instanceof EE_Base_Class) {
2034
+			//fix the reciprocal relation too
2035
+			if ($otherObject->ID()) {
2036
+				//its saved so assumed relations exist in the DB, so we can just
2037
+				//clear the cache so future queries use the updated info in the DB
2038
+				$otherObject->clear_cache($model->get_this_model_name(), null, true);
2039
+			} else {
2040
+				//it's not saved, so it caches relations like this
2041
+				$otherObject->cache($model->get_this_model_name(), $this);
2042
+			}
2043
+		}
2044
+		return $otherObject;
2045
+	}
2046
+
2047
+
2048
+
2049
+	/**
2050
+	 * Removes a relationship to the specified EE_Base_Class object, given the relationships' name. Eg, if the current
2051
+	 * model is related to a group of events, the $relationName should be 'Events', and should be a key in the EE
2052
+	 * Model's $_model_relations array. If this model object doesn't exist in the DB, just removes the related thing
2053
+	 * from the cache
2054
+	 *
2055
+	 * @param mixed  $otherObjectModelObjectOrID
2056
+	 *                EE_Base_Class or the ID of the other object, OR an array key into the cache if this isn't saved
2057
+	 *                to the DB yet
2058
+	 * @param string $relationName
2059
+	 * @param array  $where_query
2060
+	 *                You can optionally include an array of key=>value pairs that allow you to further constrict the
2061
+	 *                relation to being added. However, keep in mind that the columns (keys) given must match a column
2062
+	 *                on the JOIN table and currently only the HABTM models accept these additional conditions. Also
2063
+	 *                remember that if an exact match isn't found for these extra cols/val pairs, then a NEW row is
2064
+	 *                created in the join table.
2065
+	 * @return EE_Base_Class the relation was removed from
2066
+	 * @throws \EE_Error
2067
+	 */
2068
+	public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = array())
2069
+	{
2070
+		if ($this->ID()) {
2071
+			//if this exists in the DB, save the relation change to the DB too
2072
+			$otherObject = $this->get_model()
2073
+								->remove_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
2074
+									$where_query);
2075
+			$this->clear_cache($relationName, $otherObject);
2076
+		} else {
2077
+			//this doesn't exist in the DB, just remove it from the cache
2078
+			$otherObject = $this->clear_cache($relationName, $otherObjectModelObjectOrID);
2079
+		}
2080
+		if ($otherObject instanceof EE_Base_Class) {
2081
+			$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2082
+		}
2083
+		return $otherObject;
2084
+	}
2085
+
2086
+
2087
+
2088
+	/**
2089
+	 * Removes ALL the related things for the $relationName.
2090
+	 *
2091
+	 * @param string $relationName
2092
+	 * @param array  $where_query_params like EEM_Base::get_all's $query_params[0] (where conditions)
2093
+	 * @return EE_Base_Class
2094
+	 * @throws \EE_Error
2095
+	 */
2096
+	public function _remove_relations($relationName, $where_query_params = array())
2097
+	{
2098
+		if ($this->ID()) {
2099
+			//if this exists in the DB, save the relation change to the DB too
2100
+			$otherObjects = $this->get_model()->remove_relations($this, $relationName, $where_query_params);
2101
+			$this->clear_cache($relationName, null, true);
2102
+		} else {
2103
+			//this doesn't exist in the DB, just remove it from the cache
2104
+			$otherObjects = $this->clear_cache($relationName, null, true);
2105
+		}
2106
+		if (is_array($otherObjects)) {
2107
+			foreach ($otherObjects as $otherObject) {
2108
+				$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2109
+			}
2110
+		}
2111
+		return $otherObjects;
2112
+	}
2113
+
2114
+
2115
+
2116
+	/**
2117
+	 * Gets all the related model objects of the specified type. Eg, if the current class if
2118
+	 * EE_Event, you could call $this->get_many_related('Registration') to get an array of all the
2119
+	 * EE_Registration objects which related to this event. Note: by default, we remove the "default query params"
2120
+	 * because we want to get even deleted items etc.
2121
+	 *
2122
+	 * @param string $relationName key in the model's _model_relations array
2123
+	 * @param array  $query_params like EEM_Base::get_all
2124
+	 * @return EE_Base_Class[] Results not necessarily indexed by IDs, because some results might not have primary keys
2125
+	 * @throws \EE_Error
2126
+	 *                             or might not be saved yet. Consider using EEM_Base::get_IDs() on these results if
2127
+	 *                             you want IDs
2128
+	 */
2129
+	public function get_many_related($relationName, $query_params = array())
2130
+	{
2131
+		if ($this->ID()) {
2132
+			//this exists in the DB, so get the related things from either the cache or the DB
2133
+			//if there are query parameters, forget about caching the related model objects.
2134
+			if ($query_params) {
2135
+				$related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2136
+			} else {
2137
+				//did we already cache the result of this query?
2138
+				$cached_results = $this->get_all_from_cache($relationName);
2139
+				if ( ! $cached_results) {
2140
+					$related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2141
+					//if no query parameters were passed, then we got all the related model objects
2142
+					//for that relation. We can cache them then.
2143
+					foreach ($related_model_objects as $related_model_object) {
2144
+						$this->cache($relationName, $related_model_object);
2145
+					}
2146
+				} else {
2147
+					$related_model_objects = $cached_results;
2148
+				}
2149
+			}
2150
+		} else {
2151
+			//this doesn't exist in the DB, so just get the related things from the cache
2152
+			$related_model_objects = $this->get_all_from_cache($relationName);
2153
+		}
2154
+		return $related_model_objects;
2155
+	}
2156
+
2157
+
2158
+
2159
+	/**
2160
+	 * Instead of getting the related model objects, simply counts them. Ignores default_where_conditions by default,
2161
+	 * unless otherwise specified in the $query_params
2162
+	 *
2163
+	 * @param string $relation_name  model_name like 'Event', or 'Registration'
2164
+	 * @param array  $query_params   like EEM_Base::get_all's
2165
+	 * @param string $field_to_count name of field to count by. By default, uses primary key
2166
+	 * @param bool   $distinct       if we want to only count the distinct values for the column then you can trigger
2167
+	 *                               that by the setting $distinct to TRUE;
2168
+	 * @return int
2169
+	 */
2170
+	public function count_related($relation_name, $query_params = array(), $field_to_count = null, $distinct = false)
2171
+	{
2172
+		return $this->get_model()->count_related($this, $relation_name, $query_params, $field_to_count, $distinct);
2173
+	}
2174
+
2175
+
2176
+
2177
+	/**
2178
+	 * Instead of getting the related model objects, simply sums up the values of the specified field.
2179
+	 * Note: ignores default_where_conditions by default, unless otherwise specified in the $query_params
2180
+	 *
2181
+	 * @param string $relation_name model_name like 'Event', or 'Registration'
2182
+	 * @param array  $query_params  like EEM_Base::get_all's
2183
+	 * @param string $field_to_sum  name of field to count by.
2184
+	 *                              By default, uses primary key (which doesn't make much sense, so you should probably
2185
+	 *                              change it)
2186
+	 * @return int
2187
+	 */
2188
+	public function sum_related($relation_name, $query_params = array(), $field_to_sum = null)
2189
+	{
2190
+		return $this->get_model()->sum_related($this, $relation_name, $query_params, $field_to_sum);
2191
+	}
2192
+
2193
+
2194
+
2195
+	/**
2196
+	 * Gets the first (ie, one) related model object of the specified type.
2197
+	 *
2198
+	 * @param string $relationName key in the model's _model_relations array
2199
+	 * @param array  $query_params like EEM_Base::get_all
2200
+	 * @return EE_Base_Class (not an array, a single object)
2201
+	 * @throws \EE_Error
2202
+	 */
2203
+	public function get_first_related($relationName, $query_params = array())
2204
+	{
2205
+		$model = $this->get_model();
2206
+		if ($this->ID()) {//this exists in the DB, get from the cache OR the DB
2207
+			//if they've provided some query parameters, don't bother trying to cache the result
2208
+			//also make sure we're not caching the result of get_first_related
2209
+			//on a relation which should have an array of objects (because the cache might have an array of objects)
2210
+			if ($query_params
2211
+				|| ! $model->related_settings_for($relationName)
2212
+					 instanceof
2213
+					 EE_Belongs_To_Relation
2214
+			) {
2215
+				$related_model_object = $model->get_first_related($this, $relationName, $query_params);
2216
+			} else {
2217
+				//first, check if we've already cached the result of this query
2218
+				$cached_result = $this->get_one_from_cache($relationName);
2219
+				if ( ! $cached_result) {
2220
+					$related_model_object = $model->get_first_related($this, $relationName, $query_params);
2221
+					$this->cache($relationName, $related_model_object);
2222
+				} else {
2223
+					$related_model_object = $cached_result;
2224
+				}
2225
+			}
2226
+		} else {
2227
+			$related_model_object = null;
2228
+			//this doesn't exist in the Db, but maybe the relation is of type belongs to, and so the related thing might
2229
+			if ($model->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2230
+				$related_model_object = $model->get_first_related($this, $relationName, $query_params);
2231
+			}
2232
+			//this doesn't exist in the DB and apparently the thing it belongs to doesn't either, just get what's cached on this object
2233
+			if ( ! $related_model_object) {
2234
+				$related_model_object = $this->get_one_from_cache($relationName);
2235
+			}
2236
+		}
2237
+		return $related_model_object;
2238
+	}
2239
+
2240
+
2241
+
2242
+	/**
2243
+	 * Does a delete on all related objects of type $relationName and removes
2244
+	 * the current model object's relation to them. If they can't be deleted (because
2245
+	 * of blocking related model objects) does nothing. If the related model objects are
2246
+	 * soft-deletable, they will be soft-deleted regardless of related blocking model objects.
2247
+	 * If this model object doesn't exist yet in the DB, just removes its related things
2248
+	 *
2249
+	 * @param string $relationName
2250
+	 * @param array  $query_params like EEM_Base::get_all's
2251
+	 * @return int how many deleted
2252
+	 * @throws \EE_Error
2253
+	 */
2254
+	public function delete_related($relationName, $query_params = array())
2255
+	{
2256
+		if ($this->ID()) {
2257
+			$count = $this->get_model()->delete_related($this, $relationName, $query_params);
2258
+		} else {
2259
+			$count = count($this->get_all_from_cache($relationName));
2260
+			$this->clear_cache($relationName, null, true);
2261
+		}
2262
+		return $count;
2263
+	}
2264
+
2265
+
2266
+
2267
+	/**
2268
+	 * Does a hard delete (ie, removes the DB row) on all related objects of type $relationName and removes
2269
+	 * the current model object's relation to them. If they can't be deleted (because
2270
+	 * of blocking related model objects) just does a soft delete on it instead, if possible.
2271
+	 * If the related thing isn't a soft-deletable model object, this function is identical
2272
+	 * to delete_related(). If this model object doesn't exist in the DB, just remove its related things
2273
+	 *
2274
+	 * @param string $relationName
2275
+	 * @param array  $query_params like EEM_Base::get_all's
2276
+	 * @return int how many deleted (including those soft deleted)
2277
+	 * @throws \EE_Error
2278
+	 */
2279
+	public function delete_related_permanently($relationName, $query_params = array())
2280
+	{
2281
+		if ($this->ID()) {
2282
+			$count = $this->get_model()->delete_related_permanently($this, $relationName, $query_params);
2283
+		} else {
2284
+			$count = count($this->get_all_from_cache($relationName));
2285
+		}
2286
+		$this->clear_cache($relationName, null, true);
2287
+		return $count;
2288
+	}
2289
+
2290
+
2291
+
2292
+	/**
2293
+	 * is_set
2294
+	 * Just a simple utility function children can use for checking if property exists
2295
+	 *
2296
+	 * @access  public
2297
+	 * @param  string $field_name property to check
2298
+	 * @return bool                              TRUE if existing,FALSE if not.
2299
+	 */
2300
+	public function is_set($field_name)
2301
+	{
2302
+		return isset($this->_fields[$field_name]);
2303
+	}
2304
+
2305
+
2306
+
2307
+	/**
2308
+	 * Just a simple utility function children can use for checking if property (or properties) exists and throwing an
2309
+	 * EE_Error exception if they don't
2310
+	 *
2311
+	 * @param  mixed (string|array) $properties properties to check
2312
+	 * @throws EE_Error
2313
+	 * @return bool                              TRUE if existing, throw EE_Error if not.
2314
+	 */
2315
+	protected function _property_exists($properties)
2316
+	{
2317
+		foreach ((array)$properties as $property_name) {
2318
+			//first make sure this property exists
2319
+			if ( ! $this->_fields[$property_name]) {
2320
+				throw new EE_Error(
2321
+					sprintf(
2322
+						__(
2323
+							'Trying to retrieve a non-existent property (%s).  Double check the spelling please',
2324
+							'event_espresso'
2325
+						),
2326
+						$property_name
2327
+					)
2328
+				);
2329
+			}
2330
+		}
2331
+		return true;
2332
+	}
2333
+
2334
+
2335
+
2336
+	/**
2337
+	 * This simply returns an array of model fields for this object
2338
+	 *
2339
+	 * @return array
2340
+	 * @throws \EE_Error
2341
+	 */
2342
+	public function model_field_array()
2343
+	{
2344
+		$fields = $this->get_model()->field_settings(false);
2345
+		$properties = array();
2346
+		//remove prepended underscore
2347
+		foreach ($fields as $field_name => $settings) {
2348
+			$properties[$field_name] = $this->get($field_name);
2349
+		}
2350
+		return $properties;
2351
+	}
2352
+
2353
+
2354
+
2355
+	/**
2356
+	 * Very handy general function to allow for plugins to extend any child of EE_Base_Class.
2357
+	 * If a method is called on a child of EE_Base_Class that doesn't exist, this function is called
2358
+	 * (http://www.garfieldtech.com/blog/php-magic-call) and passed the method's name and arguments. Instead of
2359
+	 * requiring a plugin to extend the EE_Base_Class (which works fine is there's only 1 plugin, but when will that
2360
+	 * happen?) they can add a hook onto 'filters_hook_espresso__{className}__{methodName}' (eg,
2361
+	 * filters_hook_espresso__EE_Answer__my_great_function) and accepts 2 arguments: the object on which the function
2362
+	 * was called, and an array of the original arguments passed to the function. Whatever their callback function
2363
+	 * returns will be returned by this function. Example: in functions.php (or in a plugin):
2364
+	 * add_filter('FHEE__EE_Answer__my_callback','my_callback',10,3); function
2365
+	 * my_callback($previousReturnValue,EE_Base_Class $object,$argsArray){
2366
+	 * $returnString= "you called my_callback! and passed args:".implode(",",$argsArray);
2367
+	 *        return $previousReturnValue.$returnString;
2368
+	 * }
2369
+	 * require('EE_Answer.class.php');
2370
+	 * $answer= EE_Answer::new_instance(array('REG_ID' => 2,'QST_ID' => 3,'ANS_value' => The answer is 42'));
2371
+	 * echo $answer->my_callback('monkeys',100);
2372
+	 * //will output "you called my_callback! and passed args:monkeys,100"
2373
+	 *
2374
+	 * @param string $methodName name of method which was called on a child of EE_Base_Class, but which
2375
+	 * @param array  $args       array of original arguments passed to the function
2376
+	 * @throws EE_Error
2377
+	 * @return mixed whatever the plugin which calls add_filter decides
2378
+	 */
2379
+	public function __call($methodName, $args)
2380
+	{
2381
+		$className = get_class($this);
2382
+		$tagName = "FHEE__{$className}__{$methodName}";
2383
+		if ( ! has_filter($tagName)) {
2384
+			throw new EE_Error(
2385
+				sprintf(
2386
+					__(
2387
+						"Method %s on class %s does not exist! You can create one with the following code in functions.php or in a plugin: add_filter('%s','my_callback',10,3);function my_callback(\$previousReturnValue,EE_Base_Class \$object, \$argsArray){/*function body*/return \$whatever;}",
2388
+						"event_espresso"
2389
+					),
2390
+					$methodName,
2391
+					$className,
2392
+					$tagName
2393
+				)
2394
+			);
2395
+		}
2396
+		return apply_filters($tagName, null, $this, $args);
2397
+	}
2398
+
2399
+
2400
+
2401
+	/**
2402
+	 * Similar to insert_post_meta, adds a record in the Extra_Meta model's table with the given key and value.
2403
+	 * A $previous_value can be specified in case there are many meta rows with the same key
2404
+	 *
2405
+	 * @param string $meta_key
2406
+	 * @param mixed  $meta_value
2407
+	 * @param mixed  $previous_value
2408
+	 * @return bool|int # of records updated (or BOOLEAN if we actually ended up inserting the extra meta row)
2409
+	 * @throws \EE_Error
2410
+	 * NOTE: if the values haven't changed, returns 0
2411
+	 */
2412
+	public function update_extra_meta($meta_key, $meta_value, $previous_value = null)
2413
+	{
2414
+		$query_params = array(
2415
+			array(
2416
+				'EXM_key'  => $meta_key,
2417
+				'OBJ_ID'   => $this->ID(),
2418
+				'EXM_type' => $this->get_model()->get_this_model_name(),
2419
+			),
2420
+		);
2421
+		if ($previous_value !== null) {
2422
+			$query_params[0]['EXM_value'] = $meta_value;
2423
+		}
2424
+		$existing_rows_like_that = EEM_Extra_Meta::instance()->get_all($query_params);
2425
+		if ( ! $existing_rows_like_that) {
2426
+			return $this->add_extra_meta($meta_key, $meta_value);
2427
+		}
2428
+		foreach ($existing_rows_like_that as $existing_row) {
2429
+			$existing_row->save(array('EXM_value' => $meta_value));
2430
+		}
2431
+		return count($existing_rows_like_that);
2432
+	}
2433
+
2434
+
2435
+
2436
+	/**
2437
+	 * Adds a new extra meta record. If $unique is set to TRUE, we'll first double-check
2438
+	 * no other extra meta for this model object have the same key. Returns TRUE if the
2439
+	 * extra meta row was entered, false if not
2440
+	 *
2441
+	 * @param string  $meta_key
2442
+	 * @param string  $meta_value
2443
+	 * @param boolean $unique
2444
+	 * @return boolean
2445
+	 * @throws \EE_Error
2446
+	 */
2447
+	public function add_extra_meta($meta_key, $meta_value, $unique = false)
2448
+	{
2449
+		if ($unique) {
2450
+			$existing_extra_meta = EEM_Extra_Meta::instance()->get_one(
2451
+				array(
2452
+					array(
2453
+						'EXM_key'  => $meta_key,
2454
+						'OBJ_ID'   => $this->ID(),
2455
+						'EXM_type' => $this->get_model()->get_this_model_name(),
2456
+					),
2457
+				)
2458
+			);
2459
+			if ($existing_extra_meta) {
2460
+				return false;
2461
+			}
2462
+		}
2463
+		$new_extra_meta = EE_Extra_Meta::new_instance(
2464
+			array(
2465
+				'EXM_key'   => $meta_key,
2466
+				'EXM_value' => $meta_value,
2467
+				'OBJ_ID'    => $this->ID(),
2468
+				'EXM_type'  => $this->get_model()->get_this_model_name(),
2469
+			)
2470
+		);
2471
+		$new_extra_meta->save();
2472
+		return true;
2473
+	}
2474
+
2475
+
2476
+
2477
+	/**
2478
+	 * Deletes all the extra meta rows for this record as specified by key. If $meta_value
2479
+	 * is specified, only deletes extra meta records with that value.
2480
+	 *
2481
+	 * @param string $meta_key
2482
+	 * @param string $meta_value
2483
+	 * @return int number of extra meta rows deleted
2484
+	 * @throws \EE_Error
2485
+	 */
2486
+	public function delete_extra_meta($meta_key, $meta_value = null)
2487
+	{
2488
+		$query_params = array(
2489
+			array(
2490
+				'EXM_key'  => $meta_key,
2491
+				'OBJ_ID'   => $this->ID(),
2492
+				'EXM_type' => $this->get_model()->get_this_model_name(),
2493
+			),
2494
+		);
2495
+		if ($meta_value !== null) {
2496
+			$query_params[0]['EXM_value'] = $meta_value;
2497
+		}
2498
+		return EEM_Extra_Meta::instance()->delete($query_params);
2499
+	}
2500
+
2501
+
2502
+
2503
+	/**
2504
+	 * Gets the extra meta with the given meta key. If you specify "single" we just return 1, otherwise
2505
+	 * an array of everything found. Requires that this model actually have a relation of type EE_Has_Many_Any_Relation.
2506
+	 * You can specify $default is case you haven't found the extra meta
2507
+	 *
2508
+	 * @param string  $meta_key
2509
+	 * @param boolean $single
2510
+	 * @param mixed   $default if we don't find anything, what should we return?
2511
+	 * @return mixed single value if $single; array if ! $single
2512
+	 * @throws \EE_Error
2513
+	 */
2514
+	public function get_extra_meta($meta_key, $single = false, $default = null)
2515
+	{
2516
+		if ($single) {
2517
+			$result = $this->get_first_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2518
+			if ($result instanceof EE_Extra_Meta) {
2519
+				return $result->value();
2520
+			} else {
2521
+				return $default;
2522
+			}
2523
+		} else {
2524
+			$results = $this->get_many_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2525
+			if ($results) {
2526
+				$values = array();
2527
+				foreach ($results as $result) {
2528
+					if ($result instanceof EE_Extra_Meta) {
2529
+						$values[$result->ID()] = $result->value();
2530
+					}
2531
+				}
2532
+				return $values;
2533
+			} else {
2534
+				return $default;
2535
+			}
2536
+		}
2537
+	}
2538
+
2539
+
2540
+
2541
+	/**
2542
+	 * Returns a simple array of all the extra meta associated with this model object.
2543
+	 * If $one_of_each_key is true (Default), it will be an array of simple key-value pairs, keys being the
2544
+	 * extra meta's key, and teh value being its value. However, if there are duplicate extra meta rows with
2545
+	 * the same key, only one will be used. (eg array('foo'=>'bar','monkey'=>123))
2546
+	 * If $one_of_each_key is false, it will return an array with the top-level keys being
2547
+	 * the extra meta keys, but their values are also arrays, which have the extra-meta's ID as their sub-key, and
2548
+	 * finally the extra meta's value as each sub-value. (eg
2549
+	 * array('foo'=>array(1=>'bar',2=>'bill'),'monkey'=>array(3=>123)))
2550
+	 *
2551
+	 * @param boolean $one_of_each_key
2552
+	 * @return array
2553
+	 * @throws \EE_Error
2554
+	 */
2555
+	public function all_extra_meta_array($one_of_each_key = true)
2556
+	{
2557
+		$return_array = array();
2558
+		if ($one_of_each_key) {
2559
+			$extra_meta_objs = $this->get_many_related('Extra_Meta', array('group_by' => 'EXM_key'));
2560
+			foreach ($extra_meta_objs as $extra_meta_obj) {
2561
+				if ($extra_meta_obj instanceof EE_Extra_Meta) {
2562
+					$return_array[$extra_meta_obj->key()] = $extra_meta_obj->value();
2563
+				}
2564
+			}
2565
+		} else {
2566
+			$extra_meta_objs = $this->get_many_related('Extra_Meta');
2567
+			foreach ($extra_meta_objs as $extra_meta_obj) {
2568
+				if ($extra_meta_obj instanceof EE_Extra_Meta) {
2569
+					if ( ! isset($return_array[$extra_meta_obj->key()])) {
2570
+						$return_array[$extra_meta_obj->key()] = array();
2571
+					}
2572
+					$return_array[$extra_meta_obj->key()][$extra_meta_obj->ID()] = $extra_meta_obj->value();
2573
+				}
2574
+			}
2575
+		}
2576
+		return $return_array;
2577
+	}
2578
+
2579
+
2580
+
2581
+	/**
2582
+	 * Gets a pretty nice displayable nice for this model object. Often overridden
2583
+	 *
2584
+	 * @return string
2585
+	 * @throws \EE_Error
2586
+	 */
2587
+	public function name()
2588
+	{
2589
+		//find a field that's not a text field
2590
+		$field_we_can_use = $this->get_model()->get_a_field_of_type('EE_Text_Field_Base');
2591
+		if ($field_we_can_use) {
2592
+			return $this->get($field_we_can_use->get_name());
2593
+		} else {
2594
+			$first_few_properties = $this->model_field_array();
2595
+			$first_few_properties = array_slice($first_few_properties, 0, 3);
2596
+			$name_parts = array();
2597
+			foreach ($first_few_properties as $name => $value) {
2598
+				$name_parts[] = "$name:$value";
2599
+			}
2600
+			return implode(",", $name_parts);
2601
+		}
2602
+	}
2603
+
2604
+
2605
+
2606
+	/**
2607
+	 * in_entity_map
2608
+	 * Checks if this model object has been proven to already be in the entity map
2609
+	 *
2610
+	 * @return boolean
2611
+	 * @throws \EE_Error
2612
+	 */
2613
+	public function in_entity_map()
2614
+	{
2615
+		if ($this->ID() && $this->get_model()->get_from_entity_map($this->ID()) === $this) {
2616
+			//well, if we looked, did we find it in the entity map?
2617
+			return true;
2618
+		} else {
2619
+			return false;
2620
+		}
2621
+	}
2622
+
2623
+
2624
+
2625
+	/**
2626
+	 * refresh_from_db
2627
+	 * Makes sure the fields and values on this model object are in-sync with what's in the database.
2628
+	 *
2629
+	 * @throws EE_Error if this model object isn't in the entity mapper (because then you should
2630
+	 * just use what's in the entity mapper and refresh it) and WP_DEBUG is TRUE
2631
+	 */
2632
+	public function refresh_from_db()
2633
+	{
2634
+		if ($this->ID() && $this->in_entity_map()) {
2635
+			$this->get_model()->refresh_entity_map_from_db($this->ID());
2636
+		} else {
2637
+			//if it doesn't have ID, you shouldn't be asking to refresh it from teh database (because its not in the database)
2638
+			//if it has an ID but it's not in the map, and you're asking me to refresh it
2639
+			//that's kinda dangerous. You should just use what's in the entity map, or add this to the entity map if there's
2640
+			//absolutely nothing in it for this ID
2641
+			if (WP_DEBUG) {
2642
+				throw new EE_Error(
2643
+					sprintf(
2644
+						__('Trying to refresh a model object with ID "%1$s" that\'s not in the entity map? First off: you should put it in the entity map by calling %2$s. Second off, if you want what\'s in the database right now, you should just call %3$s yourself and discard this model object.',
2645
+							'event_espresso'),
2646
+						$this->ID(),
2647
+						get_class($this->get_model()) . '::instance()->add_to_entity_map()',
2648
+						get_class($this->get_model()) . '::instance()->refresh_entity_map()'
2649
+					)
2650
+				);
2651
+			}
2652
+		}
2653
+	}
2654
+
2655
+
2656
+
2657
+	/**
2658
+	 * Because some other plugins, like Advanced Cron Manager, expect all objects to have this method
2659
+	 * (probably a bad assumption they have made, oh well)
2660
+	 *
2661
+	 * @return string
2662
+	 */
2663
+	public function __toString()
2664
+	{
2665
+		try {
2666
+			return sprintf('%s (%s)', $this->name(), $this->ID());
2667
+		} catch (Exception $e) {
2668
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2669
+			return '';
2670
+		}
2671
+	}
2672
+
2673
+
2674
+
2675
+	/**
2676
+	 * Clear related model objects if they're already in the DB, because otherwise when we
2677
+	 * UN-serialize this model object we'll need to be careful to add them to the entity map.
2678
+	 * This means if we have made changes to those related model objects, and want to unserialize
2679
+	 * the this model object on a subsequent request, changes to those related model objects will be lost.
2680
+	 * Instead, those related model objects should be directly serialized and stored.
2681
+	 * Eg, the following won't work:
2682
+	 * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2683
+	 * $att = $reg->attendee();
2684
+	 * $att->set( 'ATT_fname', 'Dirk' );
2685
+	 * update_option( 'my_option', serialize( $reg ) );
2686
+	 * //END REQUEST
2687
+	 * //START NEXT REQUEST
2688
+	 * $reg = get_option( 'my_option' );
2689
+	 * $reg->attendee()->save();
2690
+	 * And would need to be replace with:
2691
+	 * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2692
+	 * $att = $reg->attendee();
2693
+	 * $att->set( 'ATT_fname', 'Dirk' );
2694
+	 * update_option( 'my_option', serialize( $reg ) );
2695
+	 * //END REQUEST
2696
+	 * //START NEXT REQUEST
2697
+	 * $att = get_option( 'my_option' );
2698
+	 * $att->save();
2699
+	 *
2700
+	 * @return array
2701
+	 * @throws \EE_Error
2702
+	 */
2703
+	public function __sleep()
2704
+	{
2705
+		$model = $this->get_model();
2706
+		foreach ($model->relation_settings() as $relation_name => $relation_obj) {
2707
+			if ($relation_obj instanceof EE_Belongs_To_Relation) {
2708
+				$classname = 'EE_' . $model->get_this_model_name();
2709
+				if (
2710
+					$this->get_one_from_cache($relation_name) instanceof $classname
2711
+					&& $this->get_one_from_cache($relation_name)->ID()
2712
+				) {
2713
+					$this->clear_cache($relation_name, $this->get_one_from_cache($relation_name)->ID());
2714
+				}
2715
+			}
2716
+		}
2717
+		$this->_props_n_values_provided_in_constructor = array();
2718
+		$properties_to_serialize = get_object_vars($this);
2719
+		//don't serialize the model. It's big and that risks recursion
2720
+		unset($properties_to_serialize['_model']);
2721
+		return array_keys($properties_to_serialize);
2722
+	}
2723
+
2724
+
2725
+
2726
+	/**
2727
+	 * restore _props_n_values_provided_in_constructor
2728
+	 * PLZ NOTE: this will reset the array to whatever fields values were present prior to serialization,
2729
+	 * and therefore should NOT be used to determine if state change has occurred since initial construction.
2730
+	 * At best, you would only be able to detect if state change has occurred during THIS request.
2731
+	 */
2732
+	public function __wakeup()
2733
+	{
2734
+		$this->_props_n_values_provided_in_constructor = $this->_fields;
2735
+	}
2736 2736
 
2737 2737
 
2738 2738
 
Please login to merge, or discard this patch.
core/db_models/EEM_Change_Log.model.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -106,7 +106,7 @@  discard block
 block discarded – undo
106 106
                 ),
107 107
             ),
108 108
         );
109
-        $this->_model_relations    = array();
109
+        $this->_model_relations = array();
110 110
         foreach ($models_this_can_attach_to as $model) {
111 111
             if ($model == 'WP_User') {
112 112
                 $this->_model_relations[$model] = new EE_Belongs_To_Relation();
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
      */
164 164
     public function gateway_log($message, $related_obj_id, $related_obj_type)
165 165
     {
166
-        if (! EE_Registry::instance()->is_model_name($related_obj_type)) {
166
+        if ( ! EE_Registry::instance()->is_model_name($related_obj_type)) {
167 167
             throw new EE_Error(
168 168
                 sprintf(
169 169
                     esc_html__(
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
         global $wpdb;
213 213
         return $wpdb->query(
214 214
             $wpdb->prepare(
215
-                'DELETE FROM ' . $this->table() . ' WHERE LOG_type = %s AND LOG_time < %s',
215
+                'DELETE FROM '.$this->table().' WHERE LOG_type = %s AND LOG_time < %s',
216 216
                 EEM_Change_Log::type_gateway,
217 217
                 $datetime->format(EE_Datetime_Field::mysql_timestamp_format)
218 218
             )
Please login to merge, or discard this patch.
Indentation   +228 added lines, -228 removed lines patch added patch discarded remove patch
@@ -13,246 +13,246 @@
 block discarded – undo
13 13
 class EEM_Change_Log extends EEM_Base
14 14
 {
15 15
 
16
-    /**
17
-     * the related object was created log type
18
-     */
19
-    const type_create = 'create';
20
-    /**
21
-     * the related object was updated (changed, or soft-deleted)
22
-     */
23
-    const type_update = 'update';
24
-    /**
25
-     * the related object was deleted permanently
26
-     */
27
-    const type_delete = 'delete';
28
-    /**
29
-     * the related item had something worth noting happen on it, but
30
-     * only for the purposes of debugging problems
31
-     */
32
-    const type_debug = 'debug';
33
-    /**
34
-     * the related item had an error occur on it
35
-     */
36
-    const type_error = 'error';
37
-    /**
38
-     * the related item is regarding some gateway interaction, like an IPN
39
-     * or request to process a payment
40
-     */
41
-    const type_gateway = 'gateway';
16
+	/**
17
+	 * the related object was created log type
18
+	 */
19
+	const type_create = 'create';
20
+	/**
21
+	 * the related object was updated (changed, or soft-deleted)
22
+	 */
23
+	const type_update = 'update';
24
+	/**
25
+	 * the related object was deleted permanently
26
+	 */
27
+	const type_delete = 'delete';
28
+	/**
29
+	 * the related item had something worth noting happen on it, but
30
+	 * only for the purposes of debugging problems
31
+	 */
32
+	const type_debug = 'debug';
33
+	/**
34
+	 * the related item had an error occur on it
35
+	 */
36
+	const type_error = 'error';
37
+	/**
38
+	 * the related item is regarding some gateway interaction, like an IPN
39
+	 * or request to process a payment
40
+	 */
41
+	const type_gateway = 'gateway';
42 42
 
43
-    /**
44
-     * private instance of the EEM_Change_Log object
45
-     *
46
-     * @access private
47
-     * @var EEM_Change_Log $_instance
48
-     */
49
-    protected static $_instance = null;
43
+	/**
44
+	 * private instance of the EEM_Change_Log object
45
+	 *
46
+	 * @access private
47
+	 * @var EEM_Change_Log $_instance
48
+	 */
49
+	protected static $_instance = null;
50 50
 
51 51
 
52
-    /**
53
-     * constructor
54
-     *
55
-     * @access protected
56
-     * @param null $timezone
57
-     * @throws EE_Error
58
-     */
59
-    protected function __construct($timezone = null)
60
-    {
61
-        global $current_user;
62
-        $this->singular_item       = esc_html__('Log', 'event_espresso');
63
-        $this->plural_item         = esc_html__('Logs', 'event_espresso');
64
-        $this->_tables             = array(
65
-            'Log' => new EE_Primary_Table('esp_log', 'LOG_ID'),
66
-        );
67
-        $models_this_can_attach_to = array_keys(EE_Registry::instance()->non_abstract_db_models);
68
-        $this->_fields             = array(
69
-            'Log' => array(
70
-                'LOG_ID'      => new EE_Primary_Key_Int_Field('LOG_ID', esc_html__('Log ID', 'event_espresso')),
71
-                'LOG_time'    => new EE_Datetime_Field(
72
-                    'LOG_time',
73
-                    esc_html__("Log Time", 'event_espresso'),
74
-                    false,
75
-                    EE_Datetime_Field::now
76
-                ),
77
-                'OBJ_ID'      => new EE_Foreign_Key_String_Field(
78
-                    'OBJ_ID',
79
-                    esc_html__("Object ID (int or string)", 'event_espresso'),
80
-                    true,
81
-                    null,
82
-                    $models_this_can_attach_to
83
-                ),
84
-                'OBJ_type'    => new EE_Any_Foreign_Model_Name_Field(
85
-                    'OBJ_type',
86
-                    esc_html__("Object Type", 'event_espresso'),
87
-                    true,
88
-                    null,
89
-                    $models_this_can_attach_to
90
-                ),
91
-                'LOG_type'    => new EE_Plain_Text_Field(
92
-                    'LOG_type',
93
-                    esc_html__("Type of log entry", "event_espresso"),
94
-                    false,
95
-                    self::type_debug
96
-                ),
97
-                'LOG_message' => new EE_Maybe_Serialized_Text_Field(
98
-                    'LOG_message',
99
-                    esc_html__("Log Message (body)", 'event_espresso'),
100
-                    true
101
-                ),
102
-                'LOG_wp_user' => new EE_WP_User_Field(
103
-                    'LOG_wp_user',
104
-                    esc_html__("User who was logged in while this occurred", 'event_espresso'),
105
-                    true
106
-                ),
107
-            ),
108
-        );
109
-        $this->_model_relations    = array();
110
-        foreach ($models_this_can_attach_to as $model) {
111
-            if ($model == 'WP_User') {
112
-                $this->_model_relations[$model] = new EE_Belongs_To_Relation();
113
-            } elseif ($model != 'Change_Log') {
114
-                $this->_model_relations[$model] = new EE_Belongs_To_Any_Relation();
115
-            }
116
-        }
117
-        //use completely custom caps for this
118
-        $this->_cap_restriction_generators = false;
119
-        //caps-wise this is all-or-nothing: if you have the default role you can access anything, otherwise nothing
120
-        foreach ($this->_cap_contexts_to_cap_action_map as $cap_context => $action) {
121
-            $this->_cap_restrictions[$cap_context][EE_Restriction_Generator_Base::get_default_restrictions_cap()]
122
-                = new EE_Return_None_Where_Conditions();
123
-        }
124
-        parent::__construct($timezone);
125
-    }
52
+	/**
53
+	 * constructor
54
+	 *
55
+	 * @access protected
56
+	 * @param null $timezone
57
+	 * @throws EE_Error
58
+	 */
59
+	protected function __construct($timezone = null)
60
+	{
61
+		global $current_user;
62
+		$this->singular_item       = esc_html__('Log', 'event_espresso');
63
+		$this->plural_item         = esc_html__('Logs', 'event_espresso');
64
+		$this->_tables             = array(
65
+			'Log' => new EE_Primary_Table('esp_log', 'LOG_ID'),
66
+		);
67
+		$models_this_can_attach_to = array_keys(EE_Registry::instance()->non_abstract_db_models);
68
+		$this->_fields             = array(
69
+			'Log' => array(
70
+				'LOG_ID'      => new EE_Primary_Key_Int_Field('LOG_ID', esc_html__('Log ID', 'event_espresso')),
71
+				'LOG_time'    => new EE_Datetime_Field(
72
+					'LOG_time',
73
+					esc_html__("Log Time", 'event_espresso'),
74
+					false,
75
+					EE_Datetime_Field::now
76
+				),
77
+				'OBJ_ID'      => new EE_Foreign_Key_String_Field(
78
+					'OBJ_ID',
79
+					esc_html__("Object ID (int or string)", 'event_espresso'),
80
+					true,
81
+					null,
82
+					$models_this_can_attach_to
83
+				),
84
+				'OBJ_type'    => new EE_Any_Foreign_Model_Name_Field(
85
+					'OBJ_type',
86
+					esc_html__("Object Type", 'event_espresso'),
87
+					true,
88
+					null,
89
+					$models_this_can_attach_to
90
+				),
91
+				'LOG_type'    => new EE_Plain_Text_Field(
92
+					'LOG_type',
93
+					esc_html__("Type of log entry", "event_espresso"),
94
+					false,
95
+					self::type_debug
96
+				),
97
+				'LOG_message' => new EE_Maybe_Serialized_Text_Field(
98
+					'LOG_message',
99
+					esc_html__("Log Message (body)", 'event_espresso'),
100
+					true
101
+				),
102
+				'LOG_wp_user' => new EE_WP_User_Field(
103
+					'LOG_wp_user',
104
+					esc_html__("User who was logged in while this occurred", 'event_espresso'),
105
+					true
106
+				),
107
+			),
108
+		);
109
+		$this->_model_relations    = array();
110
+		foreach ($models_this_can_attach_to as $model) {
111
+			if ($model == 'WP_User') {
112
+				$this->_model_relations[$model] = new EE_Belongs_To_Relation();
113
+			} elseif ($model != 'Change_Log') {
114
+				$this->_model_relations[$model] = new EE_Belongs_To_Any_Relation();
115
+			}
116
+		}
117
+		//use completely custom caps for this
118
+		$this->_cap_restriction_generators = false;
119
+		//caps-wise this is all-or-nothing: if you have the default role you can access anything, otherwise nothing
120
+		foreach ($this->_cap_contexts_to_cap_action_map as $cap_context => $action) {
121
+			$this->_cap_restrictions[$cap_context][EE_Restriction_Generator_Base::get_default_restrictions_cap()]
122
+				= new EE_Return_None_Where_Conditions();
123
+		}
124
+		parent::__construct($timezone);
125
+	}
126 126
 
127
-    /**
128
-     * @param string        $log_type !see the acceptable values of LOG_type in EEM__Change_Log::__construct
129
-     * @param mixed         $message  array|string of the message you want to record
130
-     * @param EE_Base_Class $related_model_obj
131
-     * @return EE_Change_Log
132
-     * @throws EE_Error
133
-     */
134
-    public function log($log_type, $message, $related_model_obj)
135
-    {
136
-        if ($related_model_obj instanceof EE_Base_Class) {
137
-            $obj_id   = $related_model_obj->ID();
138
-            $obj_type = $related_model_obj->get_model()->get_this_model_name();
139
-        } else {
140
-            $obj_id   = null;
141
-            $obj_type = null;
142
-        }
143
-        /** @var EE_Change_Log $log */
144
-        $log = EE_Change_Log::new_instance(array(
145
-            'LOG_type'    => $log_type,
146
-            'LOG_message' => $message,
147
-            'OBJ_ID'      => $obj_id,
148
-            'OBJ_type'    => $obj_type,
149
-        ));
150
-        $log->save();
151
-        return $log;
152
-    }
127
+	/**
128
+	 * @param string        $log_type !see the acceptable values of LOG_type in EEM__Change_Log::__construct
129
+	 * @param mixed         $message  array|string of the message you want to record
130
+	 * @param EE_Base_Class $related_model_obj
131
+	 * @return EE_Change_Log
132
+	 * @throws EE_Error
133
+	 */
134
+	public function log($log_type, $message, $related_model_obj)
135
+	{
136
+		if ($related_model_obj instanceof EE_Base_Class) {
137
+			$obj_id   = $related_model_obj->ID();
138
+			$obj_type = $related_model_obj->get_model()->get_this_model_name();
139
+		} else {
140
+			$obj_id   = null;
141
+			$obj_type = null;
142
+		}
143
+		/** @var EE_Change_Log $log */
144
+		$log = EE_Change_Log::new_instance(array(
145
+			'LOG_type'    => $log_type,
146
+			'LOG_message' => $message,
147
+			'OBJ_ID'      => $obj_id,
148
+			'OBJ_type'    => $obj_type,
149
+		));
150
+		$log->save();
151
+		return $log;
152
+	}
153 153
 
154 154
 
155
-    /**
156
-     * Adds a gateway log for the specified object, given its ID and type
157
-     *
158
-     * @param string $message
159
-     * @param mixed  $related_obj_id
160
-     * @param string $related_obj_type
161
-     * @throws EE_Error
162
-     * @return EE_Change_Log
163
-     */
164
-    public function gateway_log($message, $related_obj_id, $related_obj_type)
165
-    {
166
-        if (! EE_Registry::instance()->is_model_name($related_obj_type)) {
167
-            throw new EE_Error(
168
-                sprintf(
169
-                    esc_html__(
170
-                        "'%s' is not a model name. A model name must be provided when making a gateway log. Eg, 'Payment', 'Payment_Method', etc",
171
-                        "event_espresso"
172
-                    ),
173
-                    $related_obj_type
174
-                )
175
-            );
176
-        }
177
-        /** @var EE_Change_Log $log */
178
-        $log = EE_Change_Log::new_instance(array(
179
-            'LOG_type'    => EEM_Change_Log::type_gateway,
180
-            'LOG_message' => $message,
181
-            'OBJ_ID'      => $related_obj_id,
182
-            'OBJ_type'    => $related_obj_type,
183
-        ));
184
-        $log->save();
185
-        return $log;
186
-    }
155
+	/**
156
+	 * Adds a gateway log for the specified object, given its ID and type
157
+	 *
158
+	 * @param string $message
159
+	 * @param mixed  $related_obj_id
160
+	 * @param string $related_obj_type
161
+	 * @throws EE_Error
162
+	 * @return EE_Change_Log
163
+	 */
164
+	public function gateway_log($message, $related_obj_id, $related_obj_type)
165
+	{
166
+		if (! EE_Registry::instance()->is_model_name($related_obj_type)) {
167
+			throw new EE_Error(
168
+				sprintf(
169
+					esc_html__(
170
+						"'%s' is not a model name. A model name must be provided when making a gateway log. Eg, 'Payment', 'Payment_Method', etc",
171
+						"event_espresso"
172
+					),
173
+					$related_obj_type
174
+				)
175
+			);
176
+		}
177
+		/** @var EE_Change_Log $log */
178
+		$log = EE_Change_Log::new_instance(array(
179
+			'LOG_type'    => EEM_Change_Log::type_gateway,
180
+			'LOG_message' => $message,
181
+			'OBJ_ID'      => $related_obj_id,
182
+			'OBJ_type'    => $related_obj_type,
183
+		));
184
+		$log->save();
185
+		return $log;
186
+	}
187 187
 
188 188
 
189
-    /**
190
-     * Just gets the bare-bones wpdb results as an array in cases where efficiency is essential
191
-     *
192
-     * @param array $query_params @see EEM_Base::get_all
193
-     * @return array of arrays
194
-     * @throws EE_Error
195
-     */
196
-    public function get_all_efficiently($query_params)
197
-    {
198
-        return $this->_get_all_wpdb_results($query_params);
199
-    }
189
+	/**
190
+	 * Just gets the bare-bones wpdb results as an array in cases where efficiency is essential
191
+	 *
192
+	 * @param array $query_params @see EEM_Base::get_all
193
+	 * @return array of arrays
194
+	 * @throws EE_Error
195
+	 */
196
+	public function get_all_efficiently($query_params)
197
+	{
198
+		return $this->_get_all_wpdb_results($query_params);
199
+	}
200 200
 
201 201
 
202
-    /**
203
-     * Executes a database query to delete gateway logs. Does not affect model objects, so if you attempt to use
204
-     * models after this, they may be out-of-sync with the database
205
-     *
206
-     * @param DateTime $datetime
207
-     * @return false|int
208
-     * @throws EE_Error
209
-     */
210
-    public function delete_gateway_logs_older_than(DateTime $datetime)
211
-    {
212
-        global $wpdb;
213
-        return $wpdb->query(
214
-            $wpdb->prepare(
215
-                'DELETE FROM ' . $this->table() . ' WHERE LOG_type = %s AND LOG_time < %s',
216
-                EEM_Change_Log::type_gateway,
217
-                $datetime->format(EE_Datetime_Field::mysql_timestamp_format)
218
-            )
219
-        );
220
-    }
202
+	/**
203
+	 * Executes a database query to delete gateway logs. Does not affect model objects, so if you attempt to use
204
+	 * models after this, they may be out-of-sync with the database
205
+	 *
206
+	 * @param DateTime $datetime
207
+	 * @return false|int
208
+	 * @throws EE_Error
209
+	 */
210
+	public function delete_gateway_logs_older_than(DateTime $datetime)
211
+	{
212
+		global $wpdb;
213
+		return $wpdb->query(
214
+			$wpdb->prepare(
215
+				'DELETE FROM ' . $this->table() . ' WHERE LOG_type = %s AND LOG_time < %s',
216
+				EEM_Change_Log::type_gateway,
217
+				$datetime->format(EE_Datetime_Field::mysql_timestamp_format)
218
+			)
219
+		);
220
+	}
221 221
 
222 222
 
223
-    /**
224
-     * Returns the map of type to pretty label for identifiers used for `LOG_type`.  Client code can register their own
225
-     * map vai the given filter.
226
-     *
227
-     * @return array
228
-     */
229
-    public static function get_pretty_label_map_for_registered_types()
230
-    {
231
-        return apply_filters(
232
-            'FHEE__EEM_Change_Log__get_pretty_label_map_for_registered_types',
233
-            array(
234
-                self::type_create=>  esc_html__("Create", "event_espresso"),
235
-                self::type_update=>  esc_html__("Update", "event_espresso"),
236
-                self::type_delete => esc_html__("Delete", "event_espresso"),
237
-                self::type_debug=>  esc_html__("Debug", "event_espresso"),
238
-                self::type_error=>  esc_html__("Error", "event_espresso"),
239
-                self::type_gateway=> esc_html__("Gateway Interaction (IPN or Direct Payment)", 'event_espresso')
240
-            )
241
-        );
242
-    }
223
+	/**
224
+	 * Returns the map of type to pretty label for identifiers used for `LOG_type`.  Client code can register their own
225
+	 * map vai the given filter.
226
+	 *
227
+	 * @return array
228
+	 */
229
+	public static function get_pretty_label_map_for_registered_types()
230
+	{
231
+		return apply_filters(
232
+			'FHEE__EEM_Change_Log__get_pretty_label_map_for_registered_types',
233
+			array(
234
+				self::type_create=>  esc_html__("Create", "event_espresso"),
235
+				self::type_update=>  esc_html__("Update", "event_espresso"),
236
+				self::type_delete => esc_html__("Delete", "event_espresso"),
237
+				self::type_debug=>  esc_html__("Debug", "event_espresso"),
238
+				self::type_error=>  esc_html__("Error", "event_espresso"),
239
+				self::type_gateway=> esc_html__("Gateway Interaction (IPN or Direct Payment)", 'event_espresso')
240
+			)
241
+		);
242
+	}
243 243
 
244 244
 
245
-    /**
246
-     * Return the pretty (localized) label for the given log type identifier.
247
-     * @param string $type_identifier
248
-     * @return string
249
-     */
250
-    public static function get_pretty_label_for_type($type_identifier)
251
-    {
252
-        $type_identifier_map = self::get_pretty_label_map_for_registered_types();
253
-        //we fallback to the incoming type identifier if there is no localized label for it.
254
-        return isset($type_identifier_map[$type_identifier])
255
-            ? $type_identifier_map[$type_identifier]
256
-            : $type_identifier;
257
-    }
245
+	/**
246
+	 * Return the pretty (localized) label for the given log type identifier.
247
+	 * @param string $type_identifier
248
+	 * @return string
249
+	 */
250
+	public static function get_pretty_label_for_type($type_identifier)
251
+	{
252
+		$type_identifier_map = self::get_pretty_label_map_for_registered_types();
253
+		//we fallback to the incoming type identifier if there is no localized label for it.
254
+		return isset($type_identifier_map[$type_identifier])
255
+			? $type_identifier_map[$type_identifier]
256
+			: $type_identifier;
257
+	}
258 258
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Change_Log.class.php 2 patches
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -13,216 +13,216 @@
 block discarded – undo
13 13
 class EE_Change_Log extends EE_Base_Class
14 14
 {
15 15
 
16
-    /**
17
-     * @param array  $props_n_values          incoming values
18
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
19
-     *                                        used.)
20
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
21
-     *                                        date_format and the second value is the time format
22
-     * @return EE_Change_Log
23
-     * @throws EE_Error
24
-     */
25
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
26
-    {
27
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
28
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
29
-    }
30
-
31
-
32
-    /**
33
-     * @param array  $props_n_values  incoming values from the database
34
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
35
-     *                                the website will be used.
36
-     * @return EE_Change_Log
37
-     */
38
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
39
-    {
40
-        return new self($props_n_values, true, $timezone);
41
-    }
42
-
43
-    /**
44
-     * Gets message
45
-     *
46
-     * @return mixed
47
-     * @throws EE_Error
48
-     */
49
-    public function message()
50
-    {
51
-        return $this->get('LOG_message');
52
-    }
53
-
54
-    /**
55
-     * Sets message
56
-     *
57
-     * @param mixed $message
58
-     * @throws EE_Error
59
-     */
60
-    public function set_message($message)
61
-    {
62
-        $this->set('LOG_message', $message);
63
-    }
64
-
65
-    /**
66
-     * Gets time
67
-     *
68
-     * @return string
69
-     * @throws EE_Error
70
-     */
71
-    public function time()
72
-    {
73
-        return $this->get('LOG_time');
74
-    }
75
-
76
-    /**
77
-     * Sets time
78
-     *
79
-     * @param string $time
80
-     * @throws EE_Error
81
-     */
82
-    public function set_time($time)
83
-    {
84
-        $this->set('LOG_time', $time);
85
-    }
86
-
87
-    /**
88
-     * Gets log_type
89
-     *
90
-     * @return string
91
-     * @throws EE_Error
92
-     */
93
-    public function log_type()
94
-    {
95
-        return $this->get('LOG_type');
96
-    }
97
-
98
-
99
-    /**
100
-     * Return the localized log type label.
101
-     * @return string
102
-     * @throws EE_Error
103
-     */
104
-    public function log_type_label()
105
-    {
106
-        return EEM_Change_Log::get_pretty_label_for_type($this->log_type());
107
-    }
108
-
109
-    /**
110
-     * Sets log_type
111
-     *
112
-     * @param string $log_type
113
-     * @throws EE_Error
114
-     */
115
-    public function set_log_type($log_type)
116
-    {
117
-        $this->set('LOG_type', $log_type);
118
-    }
119
-
120
-    /**
121
-     * Gets type of the model object related to this log
122
-     *
123
-     * @return string
124
-     * @throws EE_Error
125
-     */
126
-    public function OBJ_type()
127
-    {
128
-        return $this->get('OBJ_type');
129
-    }
130
-
131
-    /**
132
-     * Sets type
133
-     *
134
-     * @param string $type
135
-     * @throws EE_Error
136
-     */
137
-    public function set_OBJ_type($type)
138
-    {
139
-        $this->set('OBJ_type', $type);
140
-    }
141
-
142
-    /**
143
-     * Gets OBJ_ID (the ID of the item related to this log)
144
-     *
145
-     * @return mixed
146
-     * @throws EE_Error
147
-     */
148
-    public function OBJ_ID()
149
-    {
150
-        return $this->get('OBJ_ID');
151
-    }
152
-
153
-    /**
154
-     * Sets OBJ_ID
155
-     *
156
-     * @param mixed $OBJ_ID
157
-     * @throws EE_Error
158
-     */
159
-    public function set_OBJ_ID($OBJ_ID)
160
-    {
161
-        $this->set('OBJ_ID', $OBJ_ID);
162
-    }
163
-
164
-    /**
165
-     * Gets wp_user
166
-     *
167
-     * @return int
168
-     * @throws EE_Error
169
-     */
170
-    public function wp_user()
171
-    {
172
-        return $this->get('LOG_wp_user');
173
-    }
174
-
175
-    /**
176
-     * Sets wp_user
177
-     *
178
-     * @param int $wp_user_id
179
-     * @throws EE_Error
180
-     */
181
-    public function set_wp_user($wp_user_id)
182
-    {
183
-        $this->set('LOG_wp_user', $wp_user_id);
184
-    }
185
-
186
-    /**
187
-     * Gets the model object attached to this log
188
-     *
189
-     * @return EE_Base_Class
190
-     * @throws EE_Error
191
-     */
192
-    public function object()
193
-    {
194
-        $model_name_of_related_obj = $this->OBJ_type();
195
-        $is_model_name             = EE_Registry::instance()->is_model_name($model_name_of_related_obj);
196
-        if (! $is_model_name) {
197
-            return null;
198
-        } else {
199
-            return $this->get_first_related($model_name_of_related_obj);
200
-        }
201
-    }
202
-
203
-    /**
204
-     * Shorthand for setting the OBJ_ID and OBJ_type. Slightly handier than using
205
-     * _add_relation_to because you don't have to specify what type of model you're
206
-     * associating it with
207
-     *
208
-     * @param EE_Base_Class $object
209
-     * @param boolean       $save
210
-     * @return bool if $save=true, NULL is $save=false
211
-     * @throws EE_Error
212
-     */
213
-    public function set_object($object, $save = true)
214
-    {
215
-        if ($object instanceof EE_Base_Class) {
216
-            $this->set_OBJ_type($object->get_model()->get_this_model_name());
217
-            $this->set_OBJ_ID($object->ID());
218
-        } else {
219
-            $this->set_OBJ_type(null);
220
-            $this->set_OBJ_ID(null);
221
-        }
222
-        if ($save) {
223
-            return $this->save();
224
-        } else {
225
-            return null;
226
-        }
227
-    }
16
+	/**
17
+	 * @param array  $props_n_values          incoming values
18
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
19
+	 *                                        used.)
20
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
21
+	 *                                        date_format and the second value is the time format
22
+	 * @return EE_Change_Log
23
+	 * @throws EE_Error
24
+	 */
25
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
26
+	{
27
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
28
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
29
+	}
30
+
31
+
32
+	/**
33
+	 * @param array  $props_n_values  incoming values from the database
34
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
35
+	 *                                the website will be used.
36
+	 * @return EE_Change_Log
37
+	 */
38
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
39
+	{
40
+		return new self($props_n_values, true, $timezone);
41
+	}
42
+
43
+	/**
44
+	 * Gets message
45
+	 *
46
+	 * @return mixed
47
+	 * @throws EE_Error
48
+	 */
49
+	public function message()
50
+	{
51
+		return $this->get('LOG_message');
52
+	}
53
+
54
+	/**
55
+	 * Sets message
56
+	 *
57
+	 * @param mixed $message
58
+	 * @throws EE_Error
59
+	 */
60
+	public function set_message($message)
61
+	{
62
+		$this->set('LOG_message', $message);
63
+	}
64
+
65
+	/**
66
+	 * Gets time
67
+	 *
68
+	 * @return string
69
+	 * @throws EE_Error
70
+	 */
71
+	public function time()
72
+	{
73
+		return $this->get('LOG_time');
74
+	}
75
+
76
+	/**
77
+	 * Sets time
78
+	 *
79
+	 * @param string $time
80
+	 * @throws EE_Error
81
+	 */
82
+	public function set_time($time)
83
+	{
84
+		$this->set('LOG_time', $time);
85
+	}
86
+
87
+	/**
88
+	 * Gets log_type
89
+	 *
90
+	 * @return string
91
+	 * @throws EE_Error
92
+	 */
93
+	public function log_type()
94
+	{
95
+		return $this->get('LOG_type');
96
+	}
97
+
98
+
99
+	/**
100
+	 * Return the localized log type label.
101
+	 * @return string
102
+	 * @throws EE_Error
103
+	 */
104
+	public function log_type_label()
105
+	{
106
+		return EEM_Change_Log::get_pretty_label_for_type($this->log_type());
107
+	}
108
+
109
+	/**
110
+	 * Sets log_type
111
+	 *
112
+	 * @param string $log_type
113
+	 * @throws EE_Error
114
+	 */
115
+	public function set_log_type($log_type)
116
+	{
117
+		$this->set('LOG_type', $log_type);
118
+	}
119
+
120
+	/**
121
+	 * Gets type of the model object related to this log
122
+	 *
123
+	 * @return string
124
+	 * @throws EE_Error
125
+	 */
126
+	public function OBJ_type()
127
+	{
128
+		return $this->get('OBJ_type');
129
+	}
130
+
131
+	/**
132
+	 * Sets type
133
+	 *
134
+	 * @param string $type
135
+	 * @throws EE_Error
136
+	 */
137
+	public function set_OBJ_type($type)
138
+	{
139
+		$this->set('OBJ_type', $type);
140
+	}
141
+
142
+	/**
143
+	 * Gets OBJ_ID (the ID of the item related to this log)
144
+	 *
145
+	 * @return mixed
146
+	 * @throws EE_Error
147
+	 */
148
+	public function OBJ_ID()
149
+	{
150
+		return $this->get('OBJ_ID');
151
+	}
152
+
153
+	/**
154
+	 * Sets OBJ_ID
155
+	 *
156
+	 * @param mixed $OBJ_ID
157
+	 * @throws EE_Error
158
+	 */
159
+	public function set_OBJ_ID($OBJ_ID)
160
+	{
161
+		$this->set('OBJ_ID', $OBJ_ID);
162
+	}
163
+
164
+	/**
165
+	 * Gets wp_user
166
+	 *
167
+	 * @return int
168
+	 * @throws EE_Error
169
+	 */
170
+	public function wp_user()
171
+	{
172
+		return $this->get('LOG_wp_user');
173
+	}
174
+
175
+	/**
176
+	 * Sets wp_user
177
+	 *
178
+	 * @param int $wp_user_id
179
+	 * @throws EE_Error
180
+	 */
181
+	public function set_wp_user($wp_user_id)
182
+	{
183
+		$this->set('LOG_wp_user', $wp_user_id);
184
+	}
185
+
186
+	/**
187
+	 * Gets the model object attached to this log
188
+	 *
189
+	 * @return EE_Base_Class
190
+	 * @throws EE_Error
191
+	 */
192
+	public function object()
193
+	{
194
+		$model_name_of_related_obj = $this->OBJ_type();
195
+		$is_model_name             = EE_Registry::instance()->is_model_name($model_name_of_related_obj);
196
+		if (! $is_model_name) {
197
+			return null;
198
+		} else {
199
+			return $this->get_first_related($model_name_of_related_obj);
200
+		}
201
+	}
202
+
203
+	/**
204
+	 * Shorthand for setting the OBJ_ID and OBJ_type. Slightly handier than using
205
+	 * _add_relation_to because you don't have to specify what type of model you're
206
+	 * associating it with
207
+	 *
208
+	 * @param EE_Base_Class $object
209
+	 * @param boolean       $save
210
+	 * @return bool if $save=true, NULL is $save=false
211
+	 * @throws EE_Error
212
+	 */
213
+	public function set_object($object, $save = true)
214
+	{
215
+		if ($object instanceof EE_Base_Class) {
216
+			$this->set_OBJ_type($object->get_model()->get_this_model_name());
217
+			$this->set_OBJ_ID($object->ID());
218
+		} else {
219
+			$this->set_OBJ_type(null);
220
+			$this->set_OBJ_ID(null);
221
+		}
222
+		if ($save) {
223
+			return $this->save();
224
+		} else {
225
+			return null;
226
+		}
227
+	}
228 228
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -193,7 +193,7 @@
 block discarded – undo
193 193
     {
194 194
         $model_name_of_related_obj = $this->OBJ_type();
195 195
         $is_model_name             = EE_Registry::instance()->is_model_name($model_name_of_related_obj);
196
-        if (! $is_model_name) {
196
+        if ( ! $is_model_name) {
197 197
             return null;
198 198
         } else {
199 199
             return $this->get_first_related($model_name_of_related_obj);
Please login to merge, or discard this patch.
core/admin/EE_Admin.core.php 2 patches
Indentation   +733 added lines, -733 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\interfaces\InterminableInterface;
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
 /**
@@ -26,336 +26,336 @@  discard block
 block discarded – undo
26 26
 final class EE_Admin implements InterminableInterface
27 27
 {
28 28
 
29
-    /**
30
-     * @access private
31
-     * @var EE_Admin $_instance
32
-     */
33
-    private static $_instance;
34
-
35
-
36
-    /**
37
-     *@ singleton method used to instantiate class object
38
-     *@ access public
39
-     *@ return class instance
40
-     *
41
-     * @throws \EE_Error
42
-     */
43
-    public static function instance()
44
-    {
45
-        // check if class object is instantiated
46
-        if (! self::$_instance instanceof EE_Admin) {
47
-            self::$_instance = new self();
48
-        }
49
-        return self::$_instance;
50
-    }
51
-
52
-
53
-    /**
54
-     * @return EE_Admin
55
-     */
56
-    public static function reset()
57
-    {
58
-        self::$_instance = null;
59
-        return self::instance();
60
-    }
61
-
62
-
63
-    /**
64
-     * class constructor
65
-     *
66
-     * @throws \EE_Error
67
-     */
68
-    protected function __construct()
69
-    {
70
-        // define global EE_Admin constants
71
-        $this->_define_all_constants();
72
-        // set autoloaders for our admin page classes based on included path information
73
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
74
-        // admin hooks
75
-        add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
76
-        // load EE_Request_Handler early
77
-        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
78
-        add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
79
-        add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
80
-        add_action('wp_loaded', array($this, 'wp_loaded'), 100);
81
-        add_action('admin_init', array($this, 'admin_init'), 100);
82
-        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
83
-        add_action('admin_notices', array($this, 'display_admin_notices'), 10);
84
-        add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
85
-        add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
86
-        add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
87
-
88
-        //reset Environment config (we only do this on admin page loads);
89
-        EE_Registry::instance()->CFG->environment->recheck_values();
90
-
91
-        do_action('AHEE__EE_Admin__loaded');
92
-    }
93
-
94
-
95
-    /**
96
-     * _define_all_constants
97
-     * define constants that are set globally for all admin pages
98
-     *
99
-     * @access private
100
-     * @return void
101
-     */
102
-    private function _define_all_constants()
103
-    {
104
-        if (! defined('EE_ADMIN_URL')) {
105
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
106
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
107
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
108
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
109
-            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
110
-        }
111
-    }
112
-
113
-
114
-    /**
115
-     *    filter_plugin_actions - adds links to the Plugins page listing
116
-     *
117
-     * @access    public
118
-     * @param    array  $links
119
-     * @param    string $plugin
120
-     * @return    array
121
-     */
122
-    public function filter_plugin_actions($links, $plugin)
123
-    {
124
-        // set $main_file in stone
125
-        static $main_file;
126
-        // if $main_file is not set yet
127
-        if (! $main_file) {
128
-            $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
129
-        }
130
-        if ($plugin === $main_file) {
131
-            // compare current plugin to this one
132
-            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
133
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings" title="Event Espresso is in maintenance mode.  Click this link to learn why.">' . __('Maintenance Mode Active',
134
-                        'event_espresso') . '</a>';
135
-                array_unshift($links, $maintenance_link);
136
-            } else {
137
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">' . __('Settings',
138
-                        'event_espresso') . '</a>';
139
-                $events_link       = '<a href="admin.php?page=espresso_events">' . __('Events',
140
-                        'event_espresso') . '</a>';
141
-                // add before other links
142
-                array_unshift($links, $org_settings_link, $events_link);
143
-            }
144
-        }
145
-        return $links;
146
-    }
147
-
148
-
149
-    /**
150
-     *    _get_request
151
-     *
152
-     * @access public
153
-     * @return void
154
-     */
155
-    public function get_request()
156
-    {
157
-        EE_Registry::instance()->load_core('Request_Handler');
158
-        EE_Registry::instance()->load_core('CPT_Strategy');
159
-    }
160
-
161
-
162
-    /**
163
-     *    hide_admin_pages_except_maintenance_mode
164
-     *
165
-     * @access public
166
-     * @param array $admin_page_folder_names
167
-     * @return array
168
-     */
169
-    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
170
-    {
171
-        return array(
172
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
173
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
174
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
175
-        );
176
-    }
177
-
178
-
179
-    /**
180
-     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
181
-     * EE_Front_Controller's init phases have run
182
-     *
183
-     * @access public
184
-     * @return void
185
-     */
186
-    public function init()
187
-    {
188
-        //only enable most of the EE_Admin IF we're not in full maintenance mode
189
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
190
-            //ok so we want to enable the entire admin
191
-            add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismiss_ee_nag_notice_callback'));
192
-            add_action('admin_notices', array($this, 'get_persistent_admin_notices'), 9);
193
-            add_action('network_admin_notices', array($this, 'get_persistent_admin_notices'), 9);
194
-            //at a glance dashboard widget
195
-            add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
196
-            //filter for get_edit_post_link used on comments for custom post types
197
-            add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
198
-        }
199
-        // run the admin page factory but ONLY if we are doing an ee admin ajax request
200
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
201
-            try {
202
-                //this loads the controller for the admin pages which will setup routing etc
203
-                EE_Registry::instance()->load_core('Admin_Page_Loader');
204
-            } catch (EE_Error $e) {
205
-                $e->get_error();
206
-            }
207
-        }
208
-        add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
209
-        //make sure our CPTs and custom taxonomy metaboxes get shown for first time users
210
-        add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
211
-        add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
212
-        //exclude EE critical pages from all nav menus and wp_list_pages
213
-        add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
214
-    }
215
-
216
-
217
-    /**
218
-     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
219
-     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
220
-     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
221
-     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
222
-     * normal property on the post_type object.  It's found ONLY in this particular context.
223
-     *
224
-     * @param  object $post_type WP post type object
225
-     * @return object            WP post type object
226
-     */
227
-    public function remove_pages_from_nav_menu($post_type)
228
-    {
229
-        //if this isn't the "pages" post type let's get out
230
-        if ($post_type->name !== 'page') {
231
-            return $post_type;
232
-        }
233
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
234
-
235
-        $post_type->_default_query = array(
236
-            'post__not_in' => $critical_pages,
237
-        );
238
-        return $post_type;
239
-    }
240
-
241
-
242
-    /**
243
-     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
244
-     * metaboxes get shown as well
245
-     *
246
-     * @access public
247
-     * @return void
248
-     */
249
-    public function enable_hidden_ee_nav_menu_metaboxes()
250
-    {
251
-        global $wp_meta_boxes, $pagenow;
252
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
253
-            return;
254
-        }
255
-        $user = wp_get_current_user();
256
-        //has this been done yet?
257
-        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
258
-            return;
259
-        }
260
-
261
-        $hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
262
-        $initial_meta_boxes = apply_filters('FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
263
-            array(
264
-                'nav-menu-theme-locations',
265
-                'add-page',
266
-                'add-custom-links',
267
-                'add-category',
268
-                'add-espresso_events',
269
-                'add-espresso_venues',
270
-                'add-espresso_event_categories',
271
-                'add-espresso_venue_categories',
272
-                'add-post-type-post',
273
-                'add-post-type-page',
274
-            ));
275
-
276
-        if (is_array($hidden_meta_boxes)) {
277
-            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
278
-                if (in_array($meta_box_id, $initial_meta_boxes)) {
279
-                    unset($hidden_meta_boxes[$key]);
280
-                }
281
-            }
282
-        }
283
-
284
-        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
285
-        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
286
-    }
287
-
288
-
289
-    /**
290
-     * This method simply registers custom nav menu boxes for "nav_menus.php route"
291
-     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
292
-     *
293
-     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
294
-     *         addons etc.
295
-     * @access public
296
-     * @return void
297
-     */
298
-    public function register_custom_nav_menu_boxes()
299
-    {
300
-        add_meta_box('add-extra-nav-menu-pages', __('Event Espresso Pages', 'event_espresso'),
301
-            array($this, 'ee_cpt_archive_pages'), 'nav-menus', 'side', 'core');
302
-    }
303
-
304
-
305
-    /**
306
-     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
307
-     *
308
-     * @since   4.3.0
309
-     * @param string $link the original link generated by wp
310
-     * @param int    $id   post id
311
-     * @return string  the (maybe) modified link
312
-     */
313
-    public function modify_edit_post_link($link, $id)
314
-    {
315
-        if (! $post = get_post($id)) {
316
-            return $link;
317
-        }
318
-        if ($post->post_type === 'espresso_attendees') {
319
-            $query_args = array(
320
-                'action' => 'edit_attendee',
321
-                'post'   => $id,
322
-            );
323
-            return EEH_URL::add_query_args_and_nonce($query_args, admin_url('admin.php?page=espresso_registrations'));
324
-        }
325
-        return $link;
326
-    }
327
-
328
-
329
-    public function ee_cpt_archive_pages()
330
-    {
331
-        global $nav_menu_selected_id;
332
-
333
-        $db_fields   = false;
334
-        $walker      = new Walker_Nav_Menu_Checklist($db_fields);
335
-        $current_tab = 'event-archives';
336
-
337
-        /*if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
29
+	/**
30
+	 * @access private
31
+	 * @var EE_Admin $_instance
32
+	 */
33
+	private static $_instance;
34
+
35
+
36
+	/**
37
+	 *@ singleton method used to instantiate class object
38
+	 *@ access public
39
+	 *@ return class instance
40
+	 *
41
+	 * @throws \EE_Error
42
+	 */
43
+	public static function instance()
44
+	{
45
+		// check if class object is instantiated
46
+		if (! self::$_instance instanceof EE_Admin) {
47
+			self::$_instance = new self();
48
+		}
49
+		return self::$_instance;
50
+	}
51
+
52
+
53
+	/**
54
+	 * @return EE_Admin
55
+	 */
56
+	public static function reset()
57
+	{
58
+		self::$_instance = null;
59
+		return self::instance();
60
+	}
61
+
62
+
63
+	/**
64
+	 * class constructor
65
+	 *
66
+	 * @throws \EE_Error
67
+	 */
68
+	protected function __construct()
69
+	{
70
+		// define global EE_Admin constants
71
+		$this->_define_all_constants();
72
+		// set autoloaders for our admin page classes based on included path information
73
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
74
+		// admin hooks
75
+		add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
76
+		// load EE_Request_Handler early
77
+		add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
78
+		add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
79
+		add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
80
+		add_action('wp_loaded', array($this, 'wp_loaded'), 100);
81
+		add_action('admin_init', array($this, 'admin_init'), 100);
82
+		add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
83
+		add_action('admin_notices', array($this, 'display_admin_notices'), 10);
84
+		add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
85
+		add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
86
+		add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
87
+
88
+		//reset Environment config (we only do this on admin page loads);
89
+		EE_Registry::instance()->CFG->environment->recheck_values();
90
+
91
+		do_action('AHEE__EE_Admin__loaded');
92
+	}
93
+
94
+
95
+	/**
96
+	 * _define_all_constants
97
+	 * define constants that are set globally for all admin pages
98
+	 *
99
+	 * @access private
100
+	 * @return void
101
+	 */
102
+	private function _define_all_constants()
103
+	{
104
+		if (! defined('EE_ADMIN_URL')) {
105
+			define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
106
+			define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
107
+			define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
108
+			define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
109
+			define('WP_AJAX_URL', admin_url('admin-ajax.php'));
110
+		}
111
+	}
112
+
113
+
114
+	/**
115
+	 *    filter_plugin_actions - adds links to the Plugins page listing
116
+	 *
117
+	 * @access    public
118
+	 * @param    array  $links
119
+	 * @param    string $plugin
120
+	 * @return    array
121
+	 */
122
+	public function filter_plugin_actions($links, $plugin)
123
+	{
124
+		// set $main_file in stone
125
+		static $main_file;
126
+		// if $main_file is not set yet
127
+		if (! $main_file) {
128
+			$main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
129
+		}
130
+		if ($plugin === $main_file) {
131
+			// compare current plugin to this one
132
+			if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
133
+				$maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings" title="Event Espresso is in maintenance mode.  Click this link to learn why.">' . __('Maintenance Mode Active',
134
+						'event_espresso') . '</a>';
135
+				array_unshift($links, $maintenance_link);
136
+			} else {
137
+				$org_settings_link = '<a href="admin.php?page=espresso_general_settings">' . __('Settings',
138
+						'event_espresso') . '</a>';
139
+				$events_link       = '<a href="admin.php?page=espresso_events">' . __('Events',
140
+						'event_espresso') . '</a>';
141
+				// add before other links
142
+				array_unshift($links, $org_settings_link, $events_link);
143
+			}
144
+		}
145
+		return $links;
146
+	}
147
+
148
+
149
+	/**
150
+	 *    _get_request
151
+	 *
152
+	 * @access public
153
+	 * @return void
154
+	 */
155
+	public function get_request()
156
+	{
157
+		EE_Registry::instance()->load_core('Request_Handler');
158
+		EE_Registry::instance()->load_core('CPT_Strategy');
159
+	}
160
+
161
+
162
+	/**
163
+	 *    hide_admin_pages_except_maintenance_mode
164
+	 *
165
+	 * @access public
166
+	 * @param array $admin_page_folder_names
167
+	 * @return array
168
+	 */
169
+	public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
170
+	{
171
+		return array(
172
+			'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
173
+			'about'       => EE_ADMIN_PAGES . 'about' . DS,
174
+			'support'     => EE_ADMIN_PAGES . 'support' . DS,
175
+		);
176
+	}
177
+
178
+
179
+	/**
180
+	 * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
181
+	 * EE_Front_Controller's init phases have run
182
+	 *
183
+	 * @access public
184
+	 * @return void
185
+	 */
186
+	public function init()
187
+	{
188
+		//only enable most of the EE_Admin IF we're not in full maintenance mode
189
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
190
+			//ok so we want to enable the entire admin
191
+			add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismiss_ee_nag_notice_callback'));
192
+			add_action('admin_notices', array($this, 'get_persistent_admin_notices'), 9);
193
+			add_action('network_admin_notices', array($this, 'get_persistent_admin_notices'), 9);
194
+			//at a glance dashboard widget
195
+			add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
196
+			//filter for get_edit_post_link used on comments for custom post types
197
+			add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
198
+		}
199
+		// run the admin page factory but ONLY if we are doing an ee admin ajax request
200
+		if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
201
+			try {
202
+				//this loads the controller for the admin pages which will setup routing etc
203
+				EE_Registry::instance()->load_core('Admin_Page_Loader');
204
+			} catch (EE_Error $e) {
205
+				$e->get_error();
206
+			}
207
+		}
208
+		add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
209
+		//make sure our CPTs and custom taxonomy metaboxes get shown for first time users
210
+		add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
211
+		add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
212
+		//exclude EE critical pages from all nav menus and wp_list_pages
213
+		add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
214
+	}
215
+
216
+
217
+	/**
218
+	 * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
219
+	 * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
220
+	 * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
221
+	 * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
222
+	 * normal property on the post_type object.  It's found ONLY in this particular context.
223
+	 *
224
+	 * @param  object $post_type WP post type object
225
+	 * @return object            WP post type object
226
+	 */
227
+	public function remove_pages_from_nav_menu($post_type)
228
+	{
229
+		//if this isn't the "pages" post type let's get out
230
+		if ($post_type->name !== 'page') {
231
+			return $post_type;
232
+		}
233
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
234
+
235
+		$post_type->_default_query = array(
236
+			'post__not_in' => $critical_pages,
237
+		);
238
+		return $post_type;
239
+	}
240
+
241
+
242
+	/**
243
+	 * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
244
+	 * metaboxes get shown as well
245
+	 *
246
+	 * @access public
247
+	 * @return void
248
+	 */
249
+	public function enable_hidden_ee_nav_menu_metaboxes()
250
+	{
251
+		global $wp_meta_boxes, $pagenow;
252
+		if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
253
+			return;
254
+		}
255
+		$user = wp_get_current_user();
256
+		//has this been done yet?
257
+		if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
258
+			return;
259
+		}
260
+
261
+		$hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
262
+		$initial_meta_boxes = apply_filters('FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
263
+			array(
264
+				'nav-menu-theme-locations',
265
+				'add-page',
266
+				'add-custom-links',
267
+				'add-category',
268
+				'add-espresso_events',
269
+				'add-espresso_venues',
270
+				'add-espresso_event_categories',
271
+				'add-espresso_venue_categories',
272
+				'add-post-type-post',
273
+				'add-post-type-page',
274
+			));
275
+
276
+		if (is_array($hidden_meta_boxes)) {
277
+			foreach ($hidden_meta_boxes as $key => $meta_box_id) {
278
+				if (in_array($meta_box_id, $initial_meta_boxes)) {
279
+					unset($hidden_meta_boxes[$key]);
280
+				}
281
+			}
282
+		}
283
+
284
+		update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
285
+		update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
286
+	}
287
+
288
+
289
+	/**
290
+	 * This method simply registers custom nav menu boxes for "nav_menus.php route"
291
+	 * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
292
+	 *
293
+	 * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
294
+	 *         addons etc.
295
+	 * @access public
296
+	 * @return void
297
+	 */
298
+	public function register_custom_nav_menu_boxes()
299
+	{
300
+		add_meta_box('add-extra-nav-menu-pages', __('Event Espresso Pages', 'event_espresso'),
301
+			array($this, 'ee_cpt_archive_pages'), 'nav-menus', 'side', 'core');
302
+	}
303
+
304
+
305
+	/**
306
+	 * Use this to edit the post link for our cpts so that the edit link points to the correct page.
307
+	 *
308
+	 * @since   4.3.0
309
+	 * @param string $link the original link generated by wp
310
+	 * @param int    $id   post id
311
+	 * @return string  the (maybe) modified link
312
+	 */
313
+	public function modify_edit_post_link($link, $id)
314
+	{
315
+		if (! $post = get_post($id)) {
316
+			return $link;
317
+		}
318
+		if ($post->post_type === 'espresso_attendees') {
319
+			$query_args = array(
320
+				'action' => 'edit_attendee',
321
+				'post'   => $id,
322
+			);
323
+			return EEH_URL::add_query_args_and_nonce($query_args, admin_url('admin.php?page=espresso_registrations'));
324
+		}
325
+		return $link;
326
+	}
327
+
328
+
329
+	public function ee_cpt_archive_pages()
330
+	{
331
+		global $nav_menu_selected_id;
332
+
333
+		$db_fields   = false;
334
+		$walker      = new Walker_Nav_Menu_Checklist($db_fields);
335
+		$current_tab = 'event-archives';
336
+
337
+		/*if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
338 338
             $current_tab = 'search';
339 339
         }/**/
340 340
 
341
-        $removed_args = array(
342
-            'action',
343
-            'customlink-tab',
344
-            'edit-menu-item',
345
-            'menu-item',
346
-            'page-tab',
347
-            '_wpnonce',
348
-        );
341
+		$removed_args = array(
342
+			'action',
343
+			'customlink-tab',
344
+			'edit-menu-item',
345
+			'menu-item',
346
+			'page-tab',
347
+			'_wpnonce',
348
+		);
349 349
 
350
-        ?>
350
+		?>
351 351
         <div id="posttype-extra-nav-menu-pages" class="posttypediv">
352 352
             <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs">
353 353
                 <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>>
354 354
                     <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives"
355 355
                        href="<?php if ($nav_menu_selected_id) {
356
-                           echo esc_url(add_query_arg('extra-nav-menu-pages-tab', 'event-archives',
357
-                               remove_query_arg($removed_args)));
358
-                       } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
356
+						   echo esc_url(add_query_arg('extra-nav-menu-pages-tab', 'event-archives',
357
+							   remove_query_arg($removed_args)));
358
+					   } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
359 359
                         <?php _e('Event Archive Pages', 'event_espresso'); ?>
360 360
                     </a>
361 361
                 </li>
@@ -374,29 +374,29 @@  discard block
 block discarded – undo
374 374
  			<?php */ ?>
375 375
 
376 376
                 <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php
377
-                echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
378
-                ?>">
377
+				echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
378
+				?>">
379 379
                     <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear">
380 380
                         <?php
381
-                        $pages          = $this->_get_extra_nav_menu_pages_items();
382
-                        $args['walker'] = $walker;
383
-                        echo walk_nav_menu_tree(array_map(array($this, '_setup_extra_nav_menu_pages_items'), $pages), 0,
384
-                            (object)$args);
385
-                        ?>
381
+						$pages          = $this->_get_extra_nav_menu_pages_items();
382
+						$args['walker'] = $walker;
383
+						echo walk_nav_menu_tree(array_map(array($this, '_setup_extra_nav_menu_pages_items'), $pages), 0,
384
+							(object)$args);
385
+						?>
386 386
                     </ul>
387 387
                 </div><!-- /.tabs-panel -->
388 388
 
389 389
                 <p class="button-controls">
390 390
 				<span class="list-controls">
391 391
 					<a href="<?php
392
-                    echo esc_url(add_query_arg(
393
-                        array(
394
-                            'extra-nav-menu-pages-tab' => 'event-archives',
395
-                            'selectall'                => 1,
396
-                        ),
397
-                        remove_query_arg($removed_args)
398
-                    ));
399
-                    ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
392
+					echo esc_url(add_query_arg(
393
+						array(
394
+							'extra-nav-menu-pages-tab' => 'event-archives',
395
+							'selectall'                => 1,
396
+						),
397
+						remove_query_arg($removed_args)
398
+					));
399
+					?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
400 400
 				</span>
401 401
 
402 402
                     <span class="add-to-menu">
@@ -411,402 +411,402 @@  discard block
 block discarded – undo
411 411
         </div><!-- /.posttypediv -->
412 412
 
413 413
         <?php
414
-    }
415
-
416
-
417
-    /**
418
-     * Returns an array of event archive nav items.
419
-     *
420
-     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
421
-     *        method we use for getting the extra nav menu items
422
-     * @return array
423
-     */
424
-    private function _get_extra_nav_menu_pages_items()
425
-    {
426
-        $menuitems[] = array(
427
-            'title'       => __('Event List', 'event_espresso'),
428
-            'url'         => get_post_type_archive_link('espresso_events'),
429
-            'description' => __('Archive page for all events.', 'event_espresso'),
430
-        );
431
-        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
432
-    }
433
-
434
-
435
-    /**
436
-     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
437
-     * the properties and converts it to the menu item object.
438
-     *
439
-     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
440
-     * @param $menu_item_values
441
-     * @return stdClass
442
-     */
443
-    private function _setup_extra_nav_menu_pages_items($menu_item_values)
444
-    {
445
-        $menu_item = new stdClass();
446
-        $keys      = array(
447
-            'ID'               => 0,
448
-            'db_id'            => 0,
449
-            'menu_item_parent' => 0,
450
-            'object_id'        => -1,
451
-            'post_parent'      => 0,
452
-            'type'             => 'custom',
453
-            'object'           => '',
454
-            'type_label'       => __('Extra Nav Menu Item', 'event_espresso'),
455
-            'title'            => '',
456
-            'url'              => '',
457
-            'target'           => '',
458
-            'attr_title'       => '',
459
-            'description'      => '',
460
-            'classes'          => array(),
461
-            'xfn'              => '',
462
-        );
463
-
464
-        foreach ($keys as $key => $value) {
465
-            $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
466
-        }
467
-        return $menu_item;
468
-    }
469
-
470
-
471
-    /**
472
-     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
473
-     * EE_Admin_Page route is called.
474
-     *
475
-     * @return void
476
-     */
477
-    public function route_admin_request()
478
-    {
479
-    }
480
-
481
-
482
-    /**
483
-     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
484
-     *
485
-     * @return void
486
-     */
487
-    public function wp_loaded()
488
-    {
489
-    }
490
-
491
-
492
-    /**
493
-     * admin_init
494
-     *
495
-     * @access public
496
-     * @return void
497
-     */
498
-    public function admin_init()
499
-    {
500
-
501
-        /**
502
-         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
503
-         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
504
-         * - check if doing post processing.
505
-         * - check if doing post processing of one of EE CPTs
506
-         * - instantiate the corresponding EE CPT model for the post_type being processed.
507
-         */
508
-        if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
509
-            EE_Registry::instance()->load_core('Register_CPTs');
510
-            EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
511
-        }
512
-
513
-
514
-        /**
515
-         * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
516
-         * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical Pages"
517
-         * tab in the EE General Settings Admin page.
518
-         * This is for user-proofing.
519
-         */
520
-        add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
521
-
522
-    }
523
-
524
-
525
-    /**
526
-     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
527
-     *
528
-     * @param string $output Current output.
529
-     * @return string
530
-     */
531
-    public function modify_dropdown_pages($output)
532
-    {
533
-        //get critical pages
534
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
535
-
536
-        //split current output by line break for easier parsing.
537
-        $split_output = explode("\n", $output);
538
-
539
-        //loop through to remove any critical pages from the array.
540
-        foreach ($critical_pages as $page_id) {
541
-            $needle = 'value="' . $page_id . '"';
542
-            foreach ($split_output as $key => $haystack) {
543
-                if (strpos($haystack, $needle) !== false) {
544
-                    unset($split_output[$key]);
545
-                }
546
-            }
547
-        }
548
-
549
-        //replace output with the new contents
550
-        return implode("\n", $split_output);
551
-    }
552
-
553
-
554
-    /**
555
-     * enqueue all admin scripts that need loaded for admin pages
556
-     *
557
-     * @access public
558
-     * @return void
559
-     */
560
-    public function enqueue_admin_scripts()
561
-    {
562
-        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
563
-        // Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script calls.
564
-        wp_enqueue_script('ee-inject-wp', EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js', array('jquery'),
565
-            EVENT_ESPRESSO_VERSION, true);
566
-        // register cookie script for future dependencies
567
-        wp_register_script('jquery-cookie', EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js', array('jquery'), '2.1',
568
-            true);
569
-        //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again vai: add_filter('FHEE_load_joyride', '__return_true' );
570
-        if (apply_filters('FHEE_load_joyride', false)) {
571
-            //joyride style
572
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
573
-            wp_register_style('ee-joyride-css', EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
574
-                array('joyride-css'), EVENT_ESPRESSO_VERSION);
575
-            wp_register_script('joyride-modernizr', EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js', array(), '2.1',
576
-                true);
577
-            //joyride JS
578
-            wp_register_script('jquery-joyride', EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
579
-                array('jquery-cookie', 'joyride-modernizr'), '2.1', true);
580
-            // wanna go for a joyride?
581
-            wp_enqueue_style('ee-joyride-css');
582
-            wp_enqueue_script('jquery-joyride');
583
-        }
584
-    }
585
-
586
-
587
-    /**
588
-     *    display_admin_notices
589
-     *
590
-     * @access    public
591
-     * @return    string
592
-     */
593
-    public function display_admin_notices()
594
-    {
595
-        echo EE_Error::get_notices();
596
-    }
597
-
598
-
599
-    /**
600
-     *    get_persistent_admin_notices
601
-     *
602
-     * @access    public
603
-     * @return        void
604
-     */
605
-    public function get_persistent_admin_notices()
606
-    {
607
-        // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
608
-        $args       = array(
609
-            'page'   => EE_Registry::instance()->REQ->is_set('page') ? EE_Registry::instance()->REQ->get('page') : '',
610
-            'action' => EE_Registry::instance()->REQ->is_set('action') ? EE_Registry::instance()->REQ->get('action') : '',
611
-        );
612
-        $return_url = EE_Admin_Page::add_query_args_and_nonce($args, EE_ADMIN_URL);
613
-        echo EE_Error::get_persistent_admin_notices($return_url);
614
-    }
615
-
616
-
617
-    /**
618
-     *    dismiss_persistent_admin_notice
619
-     *
620
-     * @access    public
621
-     * @return        void
622
-     */
623
-    public function dismiss_ee_nag_notice_callback()
624
-    {
625
-        EE_Error::dismiss_persistent_admin_notice();
626
-    }
627
-
628
-
629
-    /**
630
-     * @param array $elements
631
-     * @return array
632
-     * @throws \EE_Error
633
-     */
634
-    public function dashboard_glance_items($elements)
635
-    {
636
-        $elements                        = is_array($elements) ? $elements : array($elements);
637
-        $events                          = EEM_Event::instance()->count();
638
-        $items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(array('page' => 'espresso_events'),
639
-            admin_url('admin.php'));
640
-        $items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
641
-        $items['events']['title']        = __('Click to view all Events', 'event_espresso');
642
-        $registrations                   = EEM_Registration::instance()->count(
643
-            array(
644
-                array(
645
-                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
646
-                ),
647
-            )
648
-        );
649
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(array('page' => 'espresso_registrations'),
650
-            admin_url('admin.php'));
651
-        $items['registrations']['text']  = sprintf(_n('%s Registration', '%s Registrations', $registrations),
652
-            number_format_i18n($registrations));
653
-        $items['registrations']['title'] = __('Click to view all registrations', 'event_espresso');
654
-
655
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
656
-
657
-        foreach ($items as $type => $item_properties) {
658
-            $elements[] = sprintf('<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
659
-                $item_properties['url'], $item_properties['title'], $item_properties['text']);
660
-        }
661
-        return $elements;
662
-    }
663
-
664
-
665
-    /**
666
-     *    check_for_invalid_datetime_formats
667
-     *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
668
-     *    their selected format can be parsed by PHP
669
-     *
670
-     * @access    public
671
-     * @param    $value
672
-     * @param    $option
673
-     * @throws EE_Error
674
-     * @return    string
675
-     */
676
-    public function check_for_invalid_datetime_formats($value, $option)
677
-    {
678
-        // check for date_format or time_format
679
-        switch ($option) {
680
-            case 'date_format' :
681
-                $date_time_format = $value . ' ' . get_option('time_format');
682
-                break;
683
-            case 'time_format' :
684
-                $date_time_format = get_option('date_format') . ' ' . $value;
685
-                break;
686
-            default :
687
-                $date_time_format = false;
688
-        }
689
-        // do we have a date_time format to check ?
690
-        if ($date_time_format) {
691
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
692
-
693
-            if (is_array($error_msg)) {
694
-                $msg = '<p>' . sprintf(__('The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
695
-                        'event_espresso'), date($date_time_format), $date_time_format) . '</p><p><ul>';
696
-
697
-
698
-                foreach ($error_msg as $error) {
699
-                    $msg .= '<li>' . $error . '</li>';
700
-                }
701
-
702
-                $msg .= '</ul></p><p>' . sprintf(__('%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
703
-                        'event_espresso'), '<span style="color:#D54E21;">', '</span>') . '</p>';
704
-
705
-                // trigger WP settings error
706
-                add_settings_error(
707
-                    'date_format',
708
-                    'date_format',
709
-                    $msg
710
-                );
711
-
712
-                // set format to something valid
713
-                switch ($option) {
714
-                    case 'date_format' :
715
-                        $value = 'F j, Y';
716
-                        break;
717
-                    case 'time_format' :
718
-                        $value = 'g:i a';
719
-                        break;
720
-                }
721
-            }
722
-        }
723
-        return $value;
724
-    }
725
-
726
-
727
-    /**
728
-     *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
729
-     *
730
-     * @access    public
731
-     * @param $content
732
-     * @return    string
733
-     */
734
-    public function its_eSpresso($content)
735
-    {
736
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
737
-    }
738
-
739
-
740
-    /**
741
-     *    espresso_admin_footer
742
-     *
743
-     * @access    public
744
-     * @return    string
745
-     */
746
-    public function espresso_admin_footer()
747
-    {
748
-        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
749
-    }
750
-
751
-
752
-    /**
753
-     * static method for registering ee admin page.
754
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
755
-     *
756
-     * @since      4.3.0
757
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
758
-     * @see        EE_Register_Admin_Page::register()
759
-     * @param       $page_basename
760
-     * @param       $page_path
761
-     * @param array $config
762
-     * @return void
763
-     */
764
-    public static function register_ee_admin_page($page_basename, $page_path, $config = array())
765
-    {
766
-        EE_Error::doing_it_wrong(__METHOD__,
767
-            sprintf(__('Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
768
-                'event_espresso'), $page_basename), '4.3');
769
-        if (class_exists('EE_Register_Admin_Page')) {
770
-            $config['page_path'] = $page_path;
771
-        }
772
-        EE_Register_Admin_Page::register($page_basename, $config);
773
-
774
-    }
775
-
776
-
777
-    /**
778
-     * @deprecated 4.8.41
779
-     * @access     public
780
-     * @param  int      $post_ID
781
-     * @param  \WP_Post $post
782
-     * @return void
783
-     */
784
-    public static function parse_post_content_on_save($post_ID, $post)
785
-    {
786
-        EE_Error::doing_it_wrong(
787
-            __METHOD__,
788
-            __('Usage is deprecated', 'event_espresso'),
789
-            '4.8.41'
790
-        );
791
-    }
792
-
793
-
794
-    /**
795
-     * @deprecated 4.8.41
796
-     * @access     public
797
-     * @param  $option
798
-     * @param  $old_value
799
-     * @param  $value
800
-     * @return void
801
-     */
802
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
803
-    {
804
-        EE_Error::doing_it_wrong(
805
-            __METHOD__,
806
-            __('Usage is deprecated', 'event_espresso'),
807
-            '4.8.41'
808
-        );
809
-    }
414
+	}
415
+
416
+
417
+	/**
418
+	 * Returns an array of event archive nav items.
419
+	 *
420
+	 * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
421
+	 *        method we use for getting the extra nav menu items
422
+	 * @return array
423
+	 */
424
+	private function _get_extra_nav_menu_pages_items()
425
+	{
426
+		$menuitems[] = array(
427
+			'title'       => __('Event List', 'event_espresso'),
428
+			'url'         => get_post_type_archive_link('espresso_events'),
429
+			'description' => __('Archive page for all events.', 'event_espresso'),
430
+		);
431
+		return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
432
+	}
433
+
434
+
435
+	/**
436
+	 * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
437
+	 * the properties and converts it to the menu item object.
438
+	 *
439
+	 * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
440
+	 * @param $menu_item_values
441
+	 * @return stdClass
442
+	 */
443
+	private function _setup_extra_nav_menu_pages_items($menu_item_values)
444
+	{
445
+		$menu_item = new stdClass();
446
+		$keys      = array(
447
+			'ID'               => 0,
448
+			'db_id'            => 0,
449
+			'menu_item_parent' => 0,
450
+			'object_id'        => -1,
451
+			'post_parent'      => 0,
452
+			'type'             => 'custom',
453
+			'object'           => '',
454
+			'type_label'       => __('Extra Nav Menu Item', 'event_espresso'),
455
+			'title'            => '',
456
+			'url'              => '',
457
+			'target'           => '',
458
+			'attr_title'       => '',
459
+			'description'      => '',
460
+			'classes'          => array(),
461
+			'xfn'              => '',
462
+		);
463
+
464
+		foreach ($keys as $key => $value) {
465
+			$menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
466
+		}
467
+		return $menu_item;
468
+	}
469
+
470
+
471
+	/**
472
+	 * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
473
+	 * EE_Admin_Page route is called.
474
+	 *
475
+	 * @return void
476
+	 */
477
+	public function route_admin_request()
478
+	{
479
+	}
480
+
481
+
482
+	/**
483
+	 * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
484
+	 *
485
+	 * @return void
486
+	 */
487
+	public function wp_loaded()
488
+	{
489
+	}
490
+
491
+
492
+	/**
493
+	 * admin_init
494
+	 *
495
+	 * @access public
496
+	 * @return void
497
+	 */
498
+	public function admin_init()
499
+	{
500
+
501
+		/**
502
+		 * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
503
+		 * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
504
+		 * - check if doing post processing.
505
+		 * - check if doing post processing of one of EE CPTs
506
+		 * - instantiate the corresponding EE CPT model for the post_type being processed.
507
+		 */
508
+		if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
509
+			EE_Registry::instance()->load_core('Register_CPTs');
510
+			EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
511
+		}
512
+
513
+
514
+		/**
515
+		 * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
516
+		 * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical Pages"
517
+		 * tab in the EE General Settings Admin page.
518
+		 * This is for user-proofing.
519
+		 */
520
+		add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
521
+
522
+	}
523
+
524
+
525
+	/**
526
+	 * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
527
+	 *
528
+	 * @param string $output Current output.
529
+	 * @return string
530
+	 */
531
+	public function modify_dropdown_pages($output)
532
+	{
533
+		//get critical pages
534
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
535
+
536
+		//split current output by line break for easier parsing.
537
+		$split_output = explode("\n", $output);
538
+
539
+		//loop through to remove any critical pages from the array.
540
+		foreach ($critical_pages as $page_id) {
541
+			$needle = 'value="' . $page_id . '"';
542
+			foreach ($split_output as $key => $haystack) {
543
+				if (strpos($haystack, $needle) !== false) {
544
+					unset($split_output[$key]);
545
+				}
546
+			}
547
+		}
548
+
549
+		//replace output with the new contents
550
+		return implode("\n", $split_output);
551
+	}
552
+
553
+
554
+	/**
555
+	 * enqueue all admin scripts that need loaded for admin pages
556
+	 *
557
+	 * @access public
558
+	 * @return void
559
+	 */
560
+	public function enqueue_admin_scripts()
561
+	{
562
+		// this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
563
+		// Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script calls.
564
+		wp_enqueue_script('ee-inject-wp', EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js', array('jquery'),
565
+			EVENT_ESPRESSO_VERSION, true);
566
+		// register cookie script for future dependencies
567
+		wp_register_script('jquery-cookie', EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js', array('jquery'), '2.1',
568
+			true);
569
+		//joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again vai: add_filter('FHEE_load_joyride', '__return_true' );
570
+		if (apply_filters('FHEE_load_joyride', false)) {
571
+			//joyride style
572
+			wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
573
+			wp_register_style('ee-joyride-css', EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
574
+				array('joyride-css'), EVENT_ESPRESSO_VERSION);
575
+			wp_register_script('joyride-modernizr', EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js', array(), '2.1',
576
+				true);
577
+			//joyride JS
578
+			wp_register_script('jquery-joyride', EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
579
+				array('jquery-cookie', 'joyride-modernizr'), '2.1', true);
580
+			// wanna go for a joyride?
581
+			wp_enqueue_style('ee-joyride-css');
582
+			wp_enqueue_script('jquery-joyride');
583
+		}
584
+	}
585
+
586
+
587
+	/**
588
+	 *    display_admin_notices
589
+	 *
590
+	 * @access    public
591
+	 * @return    string
592
+	 */
593
+	public function display_admin_notices()
594
+	{
595
+		echo EE_Error::get_notices();
596
+	}
597
+
598
+
599
+	/**
600
+	 *    get_persistent_admin_notices
601
+	 *
602
+	 * @access    public
603
+	 * @return        void
604
+	 */
605
+	public function get_persistent_admin_notices()
606
+	{
607
+		// http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
608
+		$args       = array(
609
+			'page'   => EE_Registry::instance()->REQ->is_set('page') ? EE_Registry::instance()->REQ->get('page') : '',
610
+			'action' => EE_Registry::instance()->REQ->is_set('action') ? EE_Registry::instance()->REQ->get('action') : '',
611
+		);
612
+		$return_url = EE_Admin_Page::add_query_args_and_nonce($args, EE_ADMIN_URL);
613
+		echo EE_Error::get_persistent_admin_notices($return_url);
614
+	}
615
+
616
+
617
+	/**
618
+	 *    dismiss_persistent_admin_notice
619
+	 *
620
+	 * @access    public
621
+	 * @return        void
622
+	 */
623
+	public function dismiss_ee_nag_notice_callback()
624
+	{
625
+		EE_Error::dismiss_persistent_admin_notice();
626
+	}
627
+
628
+
629
+	/**
630
+	 * @param array $elements
631
+	 * @return array
632
+	 * @throws \EE_Error
633
+	 */
634
+	public function dashboard_glance_items($elements)
635
+	{
636
+		$elements                        = is_array($elements) ? $elements : array($elements);
637
+		$events                          = EEM_Event::instance()->count();
638
+		$items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(array('page' => 'espresso_events'),
639
+			admin_url('admin.php'));
640
+		$items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
641
+		$items['events']['title']        = __('Click to view all Events', 'event_espresso');
642
+		$registrations                   = EEM_Registration::instance()->count(
643
+			array(
644
+				array(
645
+					'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
646
+				),
647
+			)
648
+		);
649
+		$items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(array('page' => 'espresso_registrations'),
650
+			admin_url('admin.php'));
651
+		$items['registrations']['text']  = sprintf(_n('%s Registration', '%s Registrations', $registrations),
652
+			number_format_i18n($registrations));
653
+		$items['registrations']['title'] = __('Click to view all registrations', 'event_espresso');
654
+
655
+		$items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
656
+
657
+		foreach ($items as $type => $item_properties) {
658
+			$elements[] = sprintf('<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
659
+				$item_properties['url'], $item_properties['title'], $item_properties['text']);
660
+		}
661
+		return $elements;
662
+	}
663
+
664
+
665
+	/**
666
+	 *    check_for_invalid_datetime_formats
667
+	 *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
668
+	 *    their selected format can be parsed by PHP
669
+	 *
670
+	 * @access    public
671
+	 * @param    $value
672
+	 * @param    $option
673
+	 * @throws EE_Error
674
+	 * @return    string
675
+	 */
676
+	public function check_for_invalid_datetime_formats($value, $option)
677
+	{
678
+		// check for date_format or time_format
679
+		switch ($option) {
680
+			case 'date_format' :
681
+				$date_time_format = $value . ' ' . get_option('time_format');
682
+				break;
683
+			case 'time_format' :
684
+				$date_time_format = get_option('date_format') . ' ' . $value;
685
+				break;
686
+			default :
687
+				$date_time_format = false;
688
+		}
689
+		// do we have a date_time format to check ?
690
+		if ($date_time_format) {
691
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
692
+
693
+			if (is_array($error_msg)) {
694
+				$msg = '<p>' . sprintf(__('The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
695
+						'event_espresso'), date($date_time_format), $date_time_format) . '</p><p><ul>';
696
+
697
+
698
+				foreach ($error_msg as $error) {
699
+					$msg .= '<li>' . $error . '</li>';
700
+				}
701
+
702
+				$msg .= '</ul></p><p>' . sprintf(__('%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
703
+						'event_espresso'), '<span style="color:#D54E21;">', '</span>') . '</p>';
704
+
705
+				// trigger WP settings error
706
+				add_settings_error(
707
+					'date_format',
708
+					'date_format',
709
+					$msg
710
+				);
711
+
712
+				// set format to something valid
713
+				switch ($option) {
714
+					case 'date_format' :
715
+						$value = 'F j, Y';
716
+						break;
717
+					case 'time_format' :
718
+						$value = 'g:i a';
719
+						break;
720
+				}
721
+			}
722
+		}
723
+		return $value;
724
+	}
725
+
726
+
727
+	/**
728
+	 *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
729
+	 *
730
+	 * @access    public
731
+	 * @param $content
732
+	 * @return    string
733
+	 */
734
+	public function its_eSpresso($content)
735
+	{
736
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
737
+	}
738
+
739
+
740
+	/**
741
+	 *    espresso_admin_footer
742
+	 *
743
+	 * @access    public
744
+	 * @return    string
745
+	 */
746
+	public function espresso_admin_footer()
747
+	{
748
+		return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
749
+	}
750
+
751
+
752
+	/**
753
+	 * static method for registering ee admin page.
754
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
755
+	 *
756
+	 * @since      4.3.0
757
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
758
+	 * @see        EE_Register_Admin_Page::register()
759
+	 * @param       $page_basename
760
+	 * @param       $page_path
761
+	 * @param array $config
762
+	 * @return void
763
+	 */
764
+	public static function register_ee_admin_page($page_basename, $page_path, $config = array())
765
+	{
766
+		EE_Error::doing_it_wrong(__METHOD__,
767
+			sprintf(__('Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
768
+				'event_espresso'), $page_basename), '4.3');
769
+		if (class_exists('EE_Register_Admin_Page')) {
770
+			$config['page_path'] = $page_path;
771
+		}
772
+		EE_Register_Admin_Page::register($page_basename, $config);
773
+
774
+	}
775
+
776
+
777
+	/**
778
+	 * @deprecated 4.8.41
779
+	 * @access     public
780
+	 * @param  int      $post_ID
781
+	 * @param  \WP_Post $post
782
+	 * @return void
783
+	 */
784
+	public static function parse_post_content_on_save($post_ID, $post)
785
+	{
786
+		EE_Error::doing_it_wrong(
787
+			__METHOD__,
788
+			__('Usage is deprecated', 'event_espresso'),
789
+			'4.8.41'
790
+		);
791
+	}
792
+
793
+
794
+	/**
795
+	 * @deprecated 4.8.41
796
+	 * @access     public
797
+	 * @param  $option
798
+	 * @param  $old_value
799
+	 * @param  $value
800
+	 * @return void
801
+	 */
802
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
803
+	{
804
+		EE_Error::doing_it_wrong(
805
+			__METHOD__,
806
+			__('Usage is deprecated', 'event_espresso'),
807
+			'4.8.41'
808
+		);
809
+	}
810 810
 
811 811
 }
812 812
 // End of file EE_Admin.core.php
Please login to merge, or discard this patch.
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 
3 3
 use EventEspresso\core\interfaces\InterminableInterface;
4 4
 
5
-if (! defined('EVENT_ESPRESSO_VERSION')) {
5
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
6 6
     exit('No direct script access allowed');
7 7
 }
8 8
 
@@ -43,7 +43,7 @@  discard block
 block discarded – undo
43 43
     public static function instance()
44 44
     {
45 45
         // check if class object is instantiated
46
-        if (! self::$_instance instanceof EE_Admin) {
46
+        if ( ! self::$_instance instanceof EE_Admin) {
47 47
             self::$_instance = new self();
48 48
         }
49 49
         return self::$_instance;
@@ -101,11 +101,11 @@  discard block
 block discarded – undo
101 101
      */
102 102
     private function _define_all_constants()
103 103
     {
104
-        if (! defined('EE_ADMIN_URL')) {
105
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
106
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
107
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
108
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
104
+        if ( ! defined('EE_ADMIN_URL')) {
105
+            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL.'core/admin/');
106
+            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL.'admin_pages/');
107
+            define('EE_ADMIN_TEMPLATE', EE_ADMIN.'templates'.DS);
108
+            define('WP_ADMIN_PATH', ABSPATH.'wp-admin/');
109 109
             define('WP_AJAX_URL', admin_url('admin-ajax.php'));
110 110
         }
111 111
     }
@@ -124,20 +124,20 @@  discard block
 block discarded – undo
124 124
         // set $main_file in stone
125 125
         static $main_file;
126 126
         // if $main_file is not set yet
127
-        if (! $main_file) {
127
+        if ( ! $main_file) {
128 128
             $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
129 129
         }
130 130
         if ($plugin === $main_file) {
131 131
             // compare current plugin to this one
132 132
             if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
133
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings" title="Event Espresso is in maintenance mode.  Click this link to learn why.">' . __('Maintenance Mode Active',
134
-                        'event_espresso') . '</a>';
133
+                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings" title="Event Espresso is in maintenance mode.  Click this link to learn why.">'.__('Maintenance Mode Active',
134
+                        'event_espresso').'</a>';
135 135
                 array_unshift($links, $maintenance_link);
136 136
             } else {
137
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">' . __('Settings',
138
-                        'event_espresso') . '</a>';
139
-                $events_link       = '<a href="admin.php?page=espresso_events">' . __('Events',
140
-                        'event_espresso') . '</a>';
137
+                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'.__('Settings',
138
+                        'event_espresso').'</a>';
139
+                $events_link       = '<a href="admin.php?page=espresso_events">'.__('Events',
140
+                        'event_espresso').'</a>';
141 141
                 // add before other links
142 142
                 array_unshift($links, $org_settings_link, $events_link);
143 143
             }
@@ -169,9 +169,9 @@  discard block
 block discarded – undo
169 169
     public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
170 170
     {
171 171
         return array(
172
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
173
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
174
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
172
+            'maintenance' => EE_ADMIN_PAGES.'maintenance'.DS,
173
+            'about'       => EE_ADMIN_PAGES.'about'.DS,
174
+            'support'     => EE_ADMIN_PAGES.'support'.DS,
175 175
         );
176 176
     }
177 177
 
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
             add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
198 198
         }
199 199
         // run the admin page factory but ONLY if we are doing an ee admin ajax request
200
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
200
+        if ( ! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
201 201
             try {
202 202
                 //this loads the controller for the admin pages which will setup routing etc
203 203
                 EE_Registry::instance()->load_core('Admin_Page_Loader');
@@ -249,7 +249,7 @@  discard block
 block discarded – undo
249 249
     public function enable_hidden_ee_nav_menu_metaboxes()
250 250
     {
251 251
         global $wp_meta_boxes, $pagenow;
252
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
252
+        if ( ! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
253 253
             return;
254 254
         }
255 255
         $user = wp_get_current_user();
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
      */
313 313
     public function modify_edit_post_link($link, $id)
314 314
     {
315
-        if (! $post = get_post($id)) {
315
+        if ( ! $post = get_post($id)) {
316 316
             return $link;
317 317
         }
318 318
         if ($post->post_type === 'espresso_attendees') {
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
                         $pages          = $this->_get_extra_nav_menu_pages_items();
382 382
                         $args['walker'] = $walker;
383 383
                         echo walk_nav_menu_tree(array_map(array($this, '_setup_extra_nav_menu_pages_items'), $pages), 0,
384
-                            (object)$args);
384
+                            (object) $args);
385 385
                         ?>
386 386
                     </ul>
387 387
                 </div><!-- /.tabs-panel -->
@@ -538,7 +538,7 @@  discard block
 block discarded – undo
538 538
 
539 539
         //loop through to remove any critical pages from the array.
540 540
         foreach ($critical_pages as $page_id) {
541
-            $needle = 'value="' . $page_id . '"';
541
+            $needle = 'value="'.$page_id.'"';
542 542
             foreach ($split_output as $key => $haystack) {
543 543
                 if (strpos($haystack, $needle) !== false) {
544 544
                     unset($split_output[$key]);
@@ -561,21 +561,21 @@  discard block
 block discarded – undo
561 561
     {
562 562
         // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
563 563
         // Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script calls.
564
-        wp_enqueue_script('ee-inject-wp', EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js', array('jquery'),
564
+        wp_enqueue_script('ee-inject-wp', EE_ADMIN_URL.'assets/ee-cpt-wp-injects.js', array('jquery'),
565 565
             EVENT_ESPRESSO_VERSION, true);
566 566
         // register cookie script for future dependencies
567
-        wp_register_script('jquery-cookie', EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js', array('jquery'), '2.1',
567
+        wp_register_script('jquery-cookie', EE_THIRD_PARTY_URL.'joyride/jquery.cookie.js', array('jquery'), '2.1',
568 568
             true);
569 569
         //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again vai: add_filter('FHEE_load_joyride', '__return_true' );
570 570
         if (apply_filters('FHEE_load_joyride', false)) {
571 571
             //joyride style
572
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
573
-            wp_register_style('ee-joyride-css', EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
572
+            wp_register_style('joyride-css', EE_THIRD_PARTY_URL.'joyride/joyride-2.1.css', array(), '2.1');
573
+            wp_register_style('ee-joyride-css', EE_GLOBAL_ASSETS_URL.'css/ee-joyride-styles.css',
574 574
                 array('joyride-css'), EVENT_ESPRESSO_VERSION);
575
-            wp_register_script('joyride-modernizr', EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js', array(), '2.1',
575
+            wp_register_script('joyride-modernizr', EE_THIRD_PARTY_URL.'joyride/modernizr.mq.js', array(), '2.1',
576 576
                 true);
577 577
             //joyride JS
578
-            wp_register_script('jquery-joyride', EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
578
+            wp_register_script('jquery-joyride', EE_THIRD_PARTY_URL.'joyride/jquery.joyride-2.1.js',
579 579
                 array('jquery-cookie', 'joyride-modernizr'), '2.1', true);
580 580
             // wanna go for a joyride?
581 581
             wp_enqueue_style('ee-joyride-css');
@@ -605,7 +605,7 @@  discard block
 block discarded – undo
605 605
     public function get_persistent_admin_notices()
606 606
     {
607 607
         // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
608
-        $args       = array(
608
+        $args = array(
609 609
             'page'   => EE_Registry::instance()->REQ->is_set('page') ? EE_Registry::instance()->REQ->get('page') : '',
610 610
             'action' => EE_Registry::instance()->REQ->is_set('action') ? EE_Registry::instance()->REQ->get('action') : '',
611 611
         );
@@ -652,10 +652,10 @@  discard block
 block discarded – undo
652 652
             number_format_i18n($registrations));
653 653
         $items['registrations']['title'] = __('Click to view all registrations', 'event_espresso');
654 654
 
655
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
655
+        $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
656 656
 
657 657
         foreach ($items as $type => $item_properties) {
658
-            $elements[] = sprintf('<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
658
+            $elements[] = sprintf('<a class="ee-dashboard-link-'.$type.'" href="%s" title="%s">%s</a>',
659 659
                 $item_properties['url'], $item_properties['title'], $item_properties['text']);
660 660
         }
661 661
         return $elements;
@@ -678,10 +678,10 @@  discard block
 block discarded – undo
678 678
         // check for date_format or time_format
679 679
         switch ($option) {
680 680
             case 'date_format' :
681
-                $date_time_format = $value . ' ' . get_option('time_format');
681
+                $date_time_format = $value.' '.get_option('time_format');
682 682
                 break;
683 683
             case 'time_format' :
684
-                $date_time_format = get_option('date_format') . ' ' . $value;
684
+                $date_time_format = get_option('date_format').' '.$value;
685 685
                 break;
686 686
             default :
687 687
                 $date_time_format = false;
@@ -691,16 +691,16 @@  discard block
 block discarded – undo
691 691
             $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
692 692
 
693 693
             if (is_array($error_msg)) {
694
-                $msg = '<p>' . sprintf(__('The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
695
-                        'event_espresso'), date($date_time_format), $date_time_format) . '</p><p><ul>';
694
+                $msg = '<p>'.sprintf(__('The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
695
+                        'event_espresso'), date($date_time_format), $date_time_format).'</p><p><ul>';
696 696
 
697 697
 
698 698
                 foreach ($error_msg as $error) {
699
-                    $msg .= '<li>' . $error . '</li>';
699
+                    $msg .= '<li>'.$error.'</li>';
700 700
                 }
701 701
 
702
-                $msg .= '</ul></p><p>' . sprintf(__('%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
703
-                        'event_espresso'), '<span style="color:#D54E21;">', '</span>') . '</p>';
702
+                $msg .= '</ul></p><p>'.sprintf(__('%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
703
+                        'event_espresso'), '<span style="color:#D54E21;">', '</span>').'</p>';
704 704
 
705 705
                 // trigger WP settings error
706 706
                 add_settings_error(
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 1 patch
Indentation   +3435 added lines, -3435 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
 
@@ -23,2121 +23,2121 @@  discard block
 block discarded – undo
23 23
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Registration
28
-     */
29
-    private $_registration;
30
-
31
-    /**
32
-     * @var EE_Event
33
-     */
34
-    private $_reg_event;
35
-
36
-    /**
37
-     * @var EE_Session
38
-     */
39
-    private $_session;
40
-
41
-    private static $_reg_status;
42
-
43
-    /**
44
-     * Form for displaying the custom questions for this registration.
45
-     * This gets used a few times throughout the request so its best to cache it
46
-     *
47
-     * @var EE_Registration_Custom_Questions_Form
48
-     */
49
-    protected $_reg_custom_questions_form = null;
50
-
51
-
52
-    /**
53
-     *        constructor
54
-     *
55
-     * @Constructor
56
-     * @access public
57
-     * @param bool $routing
58
-     * @return Registrations_Admin_Page
59
-     */
60
-    public function __construct($routing = true)
61
-    {
62
-        parent::__construct($routing);
63
-        add_action('wp_loaded', array($this, 'wp_loaded'));
64
-    }
65
-
66
-
67
-    public function wp_loaded()
68
-    {
69
-        // when adding a new registration...
70
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
71
-            EE_System::do_not_cache();
72
-            if (! isset($this->_req_data['processing_registration'])
73
-                 || absint($this->_req_data['processing_registration']) !== 1
74
-            ) {
75
-                // and it's NOT the attendee information reg step
76
-                // force cookie expiration by setting time to last week
77
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
78
-                // and update the global
79
-                $_COOKIE['ee_registration_added'] = 0;
80
-            }
81
-        }
82
-    }
83
-
84
-
85
-    protected function _init_page_props()
86
-    {
87
-        $this->page_slug        = REG_PG_SLUG;
88
-        $this->_admin_base_url  = REG_ADMIN_URL;
89
-        $this->_admin_base_path = REG_ADMIN;
90
-        $this->page_label       = esc_html__('Registrations', 'event_espresso');
91
-        $this->_cpt_routes      = array(
92
-            'add_new_attendee' => 'espresso_attendees',
93
-            'edit_attendee'    => 'espresso_attendees',
94
-            'insert_attendee'  => 'espresso_attendees',
95
-            'update_attendee'  => 'espresso_attendees',
96
-        );
97
-        $this->_cpt_model_names = array(
98
-            'add_new_attendee' => 'EEM_Attendee',
99
-            'edit_attendee'    => 'EEM_Attendee',
100
-        );
101
-        $this->_cpt_edit_routes = array(
102
-            'espresso_attendees' => 'edit_attendee',
103
-        );
104
-        $this->_pagenow_map     = array(
105
-            'add_new_attendee' => 'post-new.php',
106
-            'edit_attendee'    => 'post.php',
107
-            'trash'            => 'post.php',
108
-        );
109
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
110
-        //add filters so that the comment urls don't take users to a confusing 404 page
111
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
112
-    }
113
-
114
-
115
-    public function clear_comment_link($link, $comment, $args)
116
-    {
117
-        //gotta make sure this only happens on this route
118
-        $post_type = get_post_type($comment->comment_post_ID);
119
-        if ($post_type === 'espresso_attendees') {
120
-            return '#commentsdiv';
121
-        }
122
-        return $link;
123
-    }
124
-
125
-
126
-    protected function _ajax_hooks()
127
-    {
128
-        //todo: all hooks for registrations ajax goes in here
129
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
130
-    }
131
-
132
-
133
-    protected function _define_page_props()
134
-    {
135
-        $this->_admin_page_title = $this->page_label;
136
-        $this->_labels           = array(
137
-            'buttons'                      => array(
138
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
139
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
140
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
141
-                'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
142
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
143
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
144
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
145
-                'contact_list_export' => esc_html__("Export Data", "event_espresso"),
146
-            ),
147
-            'publishbox'                   => array(
148
-                'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
149
-                'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
150
-            ),
151
-            'hide_add_button_on_cpt_route' => array(
152
-                'edit_attendee' => true,
153
-            ),
154
-        );
155
-    }
156
-
157
-
158
-    /**
159
-     *        grab url requests and route them
160
-     *
161
-     * @access private
162
-     * @return void
163
-     */
164
-    public function _set_page_routes()
165
-    {
166
-        $this->_get_registration_status_array();
167
-        $reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
168
-            ? $this->_req_data['_REG_ID'] : 0;
169
-        $att_id             = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
170
-            ? $this->_req_data['ATT_ID'] : 0;
171
-        $att_id             = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
172
-            ? $this->_req_data['post']
173
-            : $att_id;
174
-        $this->_page_routes = array(
175
-            'default'                            => array(
176
-                'func'       => '_registrations_overview_list_table',
177
-                'capability' => 'ee_read_registrations',
178
-            ),
179
-            'view_registration'                  => array(
180
-                'func'       => '_registration_details',
181
-                'capability' => 'ee_read_registration',
182
-                'obj_id'     => $reg_id,
183
-            ),
184
-            'edit_registration'                  => array(
185
-                'func'               => '_update_attendee_registration_form',
186
-                'noheader'           => true,
187
-                'headers_sent_route' => 'view_registration',
188
-                'capability'         => 'ee_edit_registration',
189
-                'obj_id'             => $reg_id,
190
-                '_REG_ID'            => $reg_id,
191
-            ),
192
-            'trash_registrations'                => array(
193
-                'func'       => '_trash_or_restore_registrations',
194
-                'args'       => array('trash' => true),
195
-                'noheader'   => true,
196
-                'capability' => 'ee_delete_registrations',
197
-            ),
198
-            'restore_registrations'              => array(
199
-                'func'       => '_trash_or_restore_registrations',
200
-                'args'       => array('trash' => false),
201
-                'noheader'   => true,
202
-                'capability' => 'ee_delete_registrations',
203
-            ),
204
-            'delete_registrations'               => array(
205
-                'func'       => '_delete_registrations',
206
-                'noheader'   => true,
207
-                'capability' => 'ee_delete_registrations',
208
-            ),
209
-            'new_registration'                   => array(
210
-                'func'       => 'new_registration',
211
-                'capability' => 'ee_edit_registrations',
212
-            ),
213
-            'process_reg_step'                   => array(
214
-                'func'       => 'process_reg_step',
215
-                'noheader'   => true,
216
-                'capability' => 'ee_edit_registrations',
217
-            ),
218
-            'redirect_to_txn'                    => array(
219
-                'func'       => 'redirect_to_txn',
220
-                'noheader'   => true,
221
-                'capability' => 'ee_edit_registrations',
222
-            ),
223
-            'change_reg_status'                  => array(
224
-                'func'       => '_change_reg_status',
225
-                'noheader'   => true,
226
-                'capability' => 'ee_edit_registration',
227
-                'obj_id'     => $reg_id,
228
-            ),
229
-            'approve_registration'               => array(
230
-                'func'       => 'approve_registration',
231
-                'noheader'   => true,
232
-                'capability' => 'ee_edit_registration',
233
-                'obj_id'     => $reg_id,
234
-            ),
235
-            'approve_and_notify_registration'    => array(
236
-                'func'       => 'approve_registration',
237
-                'noheader'   => true,
238
-                'args'       => array(true),
239
-                'capability' => 'ee_edit_registration',
240
-                'obj_id'     => $reg_id,
241
-            ),
242
-            'decline_registration'               => array(
243
-                'func'       => 'decline_registration',
244
-                'noheader'   => true,
245
-                'capability' => 'ee_edit_registration',
246
-                'obj_id'     => $reg_id,
247
-            ),
248
-            'decline_and_notify_registration'    => array(
249
-                'func'       => 'decline_registration',
250
-                'noheader'   => true,
251
-                'args'       => array(true),
252
-                'capability' => 'ee_edit_registration',
253
-                'obj_id'     => $reg_id,
254
-            ),
255
-            'pending_registration'               => array(
256
-                'func'       => 'pending_registration',
257
-                'noheader'   => true,
258
-                'capability' => 'ee_edit_registration',
259
-                'obj_id'     => $reg_id,
260
-            ),
261
-            'pending_and_notify_registration'    => array(
262
-                'func'       => 'pending_registration',
263
-                'noheader'   => true,
264
-                'args'       => array(true),
265
-                'capability' => 'ee_edit_registration',
266
-                'obj_id'     => $reg_id,
267
-            ),
268
-            'no_approve_registration'            => array(
269
-                'func'       => 'not_approve_registration',
270
-                'noheader'   => true,
271
-                'capability' => 'ee_edit_registration',
272
-                'obj_id'     => $reg_id,
273
-            ),
274
-            'no_approve_and_notify_registration' => array(
275
-                'func'       => 'not_approve_registration',
276
-                'noheader'   => true,
277
-                'args'       => array(true),
278
-                'capability' => 'ee_edit_registration',
279
-                'obj_id'     => $reg_id,
280
-            ),
281
-            'cancel_registration'                => array(
282
-                'func'       => 'cancel_registration',
283
-                'noheader'   => true,
284
-                'capability' => 'ee_edit_registration',
285
-                'obj_id'     => $reg_id,
286
-            ),
287
-            'cancel_and_notify_registration'     => array(
288
-                'func'       => 'cancel_registration',
289
-                'noheader'   => true,
290
-                'args'       => array(true),
291
-                'capability' => 'ee_edit_registration',
292
-                'obj_id'     => $reg_id,
293
-            ),
294
-            'wait_list_registration' => array(
295
-                'func'       => 'wait_list_registration',
296
-                'noheader'   => true,
297
-                'capability' => 'ee_edit_registration',
298
-                'obj_id'     => $reg_id,
299
-            ),
300
-            'contact_list'                       => array(
301
-                'func'       => '_attendee_contact_list_table',
302
-                'capability' => 'ee_read_contacts',
303
-            ),
304
-            'add_new_attendee'                   => array(
305
-                'func' => '_create_new_cpt_item',
306
-                'args' => array(
307
-                    'new_attendee' => true,
308
-                    'capability'   => 'ee_edit_contacts',
309
-                ),
310
-            ),
311
-            'edit_attendee'                      => array(
312
-                'func'       => '_edit_cpt_item',
313
-                'capability' => 'ee_edit_contacts',
314
-                'obj_id'     => $att_id,
315
-            ),
316
-            'duplicate_attendee'                 => array(
317
-                'func'       => '_duplicate_attendee',
318
-                'noheader'   => true,
319
-                'capability' => 'ee_edit_contacts',
320
-                'obj_id'     => $att_id,
321
-            ),
322
-            'insert_attendee'                    => array(
323
-                'func'       => '_insert_or_update_attendee',
324
-                'args'       => array(
325
-                    'new_attendee' => true,
326
-                ),
327
-                'noheader'   => true,
328
-                'capability' => 'ee_edit_contacts',
329
-            ),
330
-            'update_attendee'                    => array(
331
-                'func'       => '_insert_or_update_attendee',
332
-                'args'       => array(
333
-                    'new_attendee' => false,
334
-                ),
335
-                'noheader'   => true,
336
-                'capability' => 'ee_edit_contacts',
337
-                'obj_id'     => $att_id,
338
-            ),
339
-            'trash_attendees' => array(
340
-                'func' => '_trash_or_restore_attendees',
341
-                'args' => array(
342
-                    'trash' => 'true'
343
-                ),
344
-                'noheader' => true,
345
-                'capability' => 'ee_delete_contacts'
346
-            ),
347
-            'trash_attendee'                    => array(
348
-                'func'       => '_trash_or_restore_attendees',
349
-                'args'       => array(
350
-                    'trash' => true,
351
-                ),
352
-                'noheader'   => true,
353
-                'capability' => 'ee_delete_contacts',
354
-                'obj_id'     => $att_id,
355
-            ),
356
-            'restore_attendees'                  => array(
357
-                'func'       => '_trash_or_restore_attendees',
358
-                'args'       => array(
359
-                    'trash' => false,
360
-                ),
361
-                'noheader'   => true,
362
-                'capability' => 'ee_delete_contacts',
363
-                'obj_id'     => $att_id,
364
-            ),
365
-            'resend_registration'                => array(
366
-                'func'       => '_resend_registration',
367
-                'noheader'   => true,
368
-                'capability' => 'ee_send_message',
369
-            ),
370
-            'registrations_report'               => array(
371
-                'func'       => '_registrations_report',
372
-                'noheader'   => true,
373
-                'capability' => 'ee_read_registrations',
374
-            ),
375
-            'contact_list_export'                => array(
376
-                'func'       => '_contact_list_export',
377
-                'noheader'   => true,
378
-                'capability' => 'export',
379
-            ),
380
-            'contact_list_report'                => array(
381
-                'func'       => '_contact_list_report',
382
-                'noheader'   => true,
383
-                'capability' => 'ee_read_contacts',
384
-            ),
385
-        );
386
-    }
387
-
388
-
389
-    protected function _set_page_config()
390
-    {
391
-        $this->_page_config = array(
392
-            'default'           => array(
393
-                'nav'           => array(
394
-                    'label' => esc_html__('Overview', 'event_espresso'),
395
-                    'order' => 5,
396
-                ),
397
-                'help_tabs'     => array(
398
-                    'registrations_overview_help_tab'                       => array(
399
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
400
-                        'filename' => 'registrations_overview',
401
-                    ),
402
-                    'registrations_overview_table_column_headings_help_tab' => array(
403
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
404
-                        'filename' => 'registrations_overview_table_column_headings',
405
-                    ),
406
-                    'registrations_overview_filters_help_tab'               => array(
407
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
408
-                        'filename' => 'registrations_overview_filters',
409
-                    ),
410
-                    'registrations_overview_views_help_tab'                 => array(
411
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
412
-                        'filename' => 'registrations_overview_views',
413
-                    ),
414
-                    'registrations_regoverview_other_help_tab'              => array(
415
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
416
-                        'filename' => 'registrations_overview_other',
417
-                    ),
418
-                ),
419
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
420
-                'qtips'         => array('Registration_List_Table_Tips'),
421
-                'list_table'    => 'EE_Registrations_List_Table',
422
-                'require_nonce' => false,
423
-            ),
424
-            'view_registration' => array(
425
-                'nav'           => array(
426
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
427
-                    'order'      => 15,
428
-                    'url'        => isset($this->_req_data['_REG_ID'])
429
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
430
-                        : $this->_admin_base_url,
431
-                    'persistent' => false,
432
-                ),
433
-                'help_tabs'     => array(
434
-                    'registrations_details_help_tab'                    => array(
435
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
436
-                        'filename' => 'registrations_details',
437
-                    ),
438
-                    'registrations_details_table_help_tab'              => array(
439
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
440
-                        'filename' => 'registrations_details_table',
441
-                    ),
442
-                    'registrations_details_form_answers_help_tab'       => array(
443
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
444
-                        'filename' => 'registrations_details_form_answers',
445
-                    ),
446
-                    'registrations_details_registrant_details_help_tab' => array(
447
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
448
-                        'filename' => 'registrations_details_registrant_details',
449
-                    ),
450
-                ),
451
-                'help_tour'     => array('Registration_Details_Help_Tour'),
452
-                'metaboxes'     => array_merge(
453
-                    $this->_default_espresso_metaboxes,
454
-                    array('_registration_details_metaboxes')
455
-                ),
456
-                'require_nonce' => false,
457
-            ),
458
-            'new_registration'  => array(
459
-                'nav'           => array(
460
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
461
-                    'url'        => '#',
462
-                    'order'      => 15,
463
-                    'persistent' => false,
464
-                ),
465
-                'metaboxes'     => $this->_default_espresso_metaboxes,
466
-                'labels'        => array(
467
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
468
-                ),
469
-                'require_nonce' => false,
470
-            ),
471
-            'add_new_attendee'  => array(
472
-                'nav'           => array(
473
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
474
-                    'order'      => 15,
475
-                    'persistent' => false,
476
-                ),
477
-                'metaboxes'     => array_merge(
478
-                    $this->_default_espresso_metaboxes,
479
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
480
-                ),
481
-                'require_nonce' => false,
482
-            ),
483
-            'edit_attendee'     => array(
484
-                'nav'           => array(
485
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
486
-                    'order'      => 15,
487
-                    'persistent' => false,
488
-                    'url'        => isset($this->_req_data['ATT_ID'])
489
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
490
-                        : $this->_admin_base_url,
491
-                ),
492
-                'metaboxes'     => array('attendee_editor_metaboxes'),
493
-                'require_nonce' => false,
494
-            ),
495
-            'contact_list'      => array(
496
-                'nav'           => array(
497
-                    'label' => esc_html__('Contact List', 'event_espresso'),
498
-                    'order' => 20,
499
-                ),
500
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
501
-                'help_tabs'     => array(
502
-                    'registrations_contact_list_help_tab'                       => array(
503
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
504
-                        'filename' => 'registrations_contact_list',
505
-                    ),
506
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
507
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
508
-                        'filename' => 'registrations_contact_list_table_column_headings',
509
-                    ),
510
-                    'registrations_contact_list_views_help_tab'                 => array(
511
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
512
-                        'filename' => 'registrations_contact_list_views',
513
-                    ),
514
-                    'registrations_contact_list_other_help_tab'                 => array(
515
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
516
-                        'filename' => 'registrations_contact_list_other',
517
-                    ),
518
-                ),
519
-                'help_tour'     => array('Contact_List_Help_Tour'),
520
-                'metaboxes'     => array(),
521
-                'require_nonce' => false,
522
-            ),
523
-            //override default cpt routes
524
-            'create_new'        => '',
525
-            'edit'              => '',
526
-        );
527
-    }
528
-
529
-
530
-    /**
531
-     * The below methods aren't used by this class currently
532
-     */
533
-    protected function _add_screen_options()
534
-    {
535
-    }
536
-
537
-
538
-    protected function _add_feature_pointers()
539
-    {
540
-    }
541
-
542
-
543
-    public function admin_init()
544
-    {
545
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
546
-            'click "Update Registration Questions" to save your changes',
547
-            'event_espresso'
548
-        );
549
-    }
550
-
551
-
552
-    public function admin_notices()
553
-    {
554
-    }
555
-
556
-
557
-    public function admin_footer_scripts()
558
-    {
559
-    }
560
-
561
-
562
-    /**
563
-     *        get list of registration statuses
564
-     *
565
-     * @access private
566
-     * @return void
567
-     */
568
-    private function _get_registration_status_array()
569
-    {
570
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
571
-    }
572
-
573
-
574
-    protected function _add_screen_options_default()
575
-    {
576
-        $this->_per_page_screen_option();
577
-    }
578
-
579
-
580
-    protected function _add_screen_options_contact_list()
581
-    {
582
-        $page_title              = $this->_admin_page_title;
583
-        $this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
584
-        $this->_per_page_screen_option();
585
-        $this->_admin_page_title = $page_title;
586
-    }
587
-
588
-
589
-    public function load_scripts_styles()
590
-    {
591
-        //style
592
-        wp_register_style(
593
-            'espresso_reg',
594
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
595
-            array('ee-admin-css'),
596
-            EVENT_ESPRESSO_VERSION
597
-        );
598
-        wp_enqueue_style('espresso_reg');
599
-        //script
600
-        wp_register_script(
601
-            'espresso_reg',
602
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
603
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
604
-            EVENT_ESPRESSO_VERSION,
605
-            true
606
-        );
607
-        wp_enqueue_script('espresso_reg');
608
-    }
609
-
610
-
611
-    public function load_scripts_styles_edit_attendee()
612
-    {
613
-        //stuff to only show up on our attendee edit details page.
614
-        $attendee_details_translations = array(
615
-            'att_publish_text' => sprintf(
616
-                esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
617
-                $this->_cpt_model_obj->get_datetime('ATT_created')
618
-            ),
619
-        );
620
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
621
-        wp_enqueue_script('jquery-validate');
622
-    }
623
-
624
-
625
-    public function load_scripts_styles_view_registration()
626
-    {
627
-        //styles
628
-        wp_enqueue_style('espresso-ui-theme');
629
-        //scripts
630
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
631
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
632
-    }
633
-
634
-
635
-    public function load_scripts_styles_contact_list()
636
-    {
637
-        wp_deregister_style('espresso_reg');
638
-        wp_register_style(
639
-            'espresso_att',
640
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
641
-            array('ee-admin-css'),
642
-            EVENT_ESPRESSO_VERSION
643
-        );
644
-        wp_enqueue_style('espresso_att');
645
-    }
646
-
647
-
648
-    public function load_scripts_styles_new_registration()
649
-    {
650
-        wp_register_script(
651
-            'ee-spco-for-admin',
652
-            REG_ASSETS_URL . 'spco_for_admin.js',
653
-            array('underscore', 'jquery'),
654
-            EVENT_ESPRESSO_VERSION,
655
-            true
656
-        );
657
-        wp_enqueue_script('ee-spco-for-admin');
658
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
659
-        EE_Form_Section_Proper::wp_enqueue_scripts();
660
-        EED_Ticket_Selector::load_tckt_slctr_assets();
661
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
662
-    }
663
-
664
-
665
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
666
-    {
667
-        add_filter('FHEE_load_EE_messages', '__return_true');
668
-    }
669
-
670
-
671
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
672
-    {
673
-        add_filter('FHEE_load_EE_messages', '__return_true');
674
-    }
675
-
676
-
677
-    protected function _set_list_table_views_default()
678
-    {
679
-        //for notification related bulk actions we need to make sure only active messengers have an option.
680
-        EED_Messages::set_autoloaders();
681
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
682
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
683
-        $active_mts               = $message_resource_manager->list_of_active_message_types();
684
-        //key= bulk_action_slug, value= message type.
685
-        $match_array = array(
686
-            'approve_registration'    => 'registration',
687
-            'decline_registration'    => 'declined_registration',
688
-            'pending_registration'    => 'pending_approval',
689
-            'no_approve_registration' => 'not_approved_registration',
690
-            'cancel_registration'     => 'cancelled_registration',
691
-        );
692
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
693
-            'ee_send_message',
694
-            'batch_send_messages'
695
-        );
696
-        /** setup reg status bulk actions **/
697
-        $def_reg_status_actions['approve_registration'] = __('Approve Registrations', 'event_espresso');
698
-        if ($can_send && in_array($match_array['approve_registration'], $active_mts, true)) {
699
-                $def_reg_status_actions['approve_and_notify_registration'] = __('Approve and Notify Registrations',
700
-                    'event_espresso');
701
-        }
702
-        $def_reg_status_actions['decline_registration'] = __('Decline Registrations', 'event_espresso');
703
-        if ($can_send && in_array($match_array['decline_registration'], $active_mts, true)) {
704
-                $def_reg_status_actions['decline_and_notify_registration'] = __('Decline and Notify Registrations',
705
-                    'event_espresso');
706
-        }
707
-        $def_reg_status_actions['pending_registration'] = __('Set Registrations to Pending Payment', 'event_espresso');
708
-        if ($can_send && in_array($match_array['pending_registration'], $active_mts, true)) {
709
-                $def_reg_status_actions['pending_and_notify_registration'] = __(
710
-                    'Set Registrations to Pending Payment and Notify',
711
-                    'event_espresso'
712
-                );
713
-        }
714
-        $def_reg_status_actions['no_approve_registration'] = __('Set Registrations to Not Approved', 'event_espresso');
715
-        if ($can_send && in_array($match_array['no_approve_registration'], $active_mts, true)) {
716
-                $def_reg_status_actions['no_approve_and_notify_registration'] = __(
717
-                    'Set Registrations to Not Approved and Notify',
718
-                    'event_espresso'
719
-                );
720
-        }
721
-        $def_reg_status_actions['cancel_registration'] = __('Cancel Registrations', 'event_espresso');
722
-        if ($can_send && in_array($match_array['cancel_registration'], $active_mts, true)) {
723
-                $def_reg_status_actions['cancel_and_notify_registration'] = __(
724
-                    'Cancel Registrations and Notify',
725
-                    'event_espresso'
726
-                );
727
-        }
728
-        $def_reg_status_actions = apply_filters(
729
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
730
-            $def_reg_status_actions,
731
-            $active_mts
732
-        );
733
-
734
-        $this->_views = array(
735
-            'all'   => array(
736
-                'slug'        => 'all',
737
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
738
-                'count'       => 0,
739
-                'bulk_action' => array_merge($def_reg_status_actions, array(
740
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
741
-                )),
742
-            ),
743
-            'month' => array(
744
-                'slug'        => 'month',
745
-                'label'       => esc_html__('This Month', 'event_espresso'),
746
-                'count'       => 0,
747
-                'bulk_action' => array_merge($def_reg_status_actions, array(
748
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
749
-                )),
750
-            ),
751
-            'today' => array(
752
-                'slug'        => 'today',
753
-                'label'       => sprintf(
754
-                    esc_html__('Today - %s', 'event_espresso'),
755
-                    date('M d, Y', current_time('timestamp'))
756
-                ),
757
-                'count'       => 0,
758
-                'bulk_action' => array_merge($def_reg_status_actions, array(
759
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
760
-                )),
761
-            ),
762
-        );
763
-        if (EE_Registry::instance()->CAP->current_user_can(
764
-            'ee_delete_registrations',
765
-            'espresso_registrations_delete_registration'
766
-        )) {
767
-            $this->_views['incomplete'] = array(
768
-                'slug'        => 'incomplete',
769
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
770
-                'count'       => 0,
771
-                'bulk_action' => array(
772
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
773
-                ),
774
-            );
775
-            $this->_views['trash']      = array(
776
-                'slug'        => 'trash',
777
-                'label'       => esc_html__('Trash', 'event_espresso'),
778
-                'count'       => 0,
779
-                'bulk_action' => array(
780
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
781
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
782
-                ),
783
-            );
784
-        }
785
-    }
786
-
787
-
788
-    protected function _set_list_table_views_contact_list()
789
-    {
790
-        $this->_views = array(
791
-            'in_use' => array(
792
-                'slug'        => 'in_use',
793
-                'label'       => esc_html__('In Use', 'event_espresso'),
794
-                'count'       => 0,
795
-                'bulk_action' => array(
796
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
797
-                ),
798
-            ),
799
-        );
800
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_contacts',
801
-            'espresso_registrations_trash_attendees')
802
-        ) {
803
-            $this->_views['trash'] = array(
804
-                'slug'        => 'trash',
805
-                'label'       => esc_html__('Trash', 'event_espresso'),
806
-                'count'       => 0,
807
-                'bulk_action' => array(
808
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
809
-                ),
810
-            );
811
-        }
812
-    }
813
-
814
-
815
-    protected function _registration_legend_items()
816
-    {
817
-        $fc_items = array(
818
-            'star-icon'        => array(
819
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
820
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
821
-            ),
822
-            'view_details'     => array(
823
-                'class' => 'dashicons dashicons-clipboard',
824
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
825
-            ),
826
-            'edit_attendee'    => array(
827
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
828
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
829
-            ),
830
-            'view_transaction' => array(
831
-                'class' => 'dashicons dashicons-cart',
832
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
833
-            ),
834
-            'view_invoice'     => array(
835
-                'class' => 'dashicons dashicons-media-spreadsheet',
836
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
837
-            ),
838
-        );
839
-        if (EE_Registry::instance()->CAP->current_user_can(
840
-            'ee_send_message',
841
-            'espresso_registrations_resend_registration'
842
-        )) {
843
-            $fc_items['resend_registration'] = array(
844
-                'class' => 'dashicons dashicons-email-alt',
845
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
846
-            );
847
-        } else {
848
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
849
-        }
850
-        if (EE_Registry::instance()->CAP->current_user_can(
851
-            'ee_read_global_messages',
852
-            'view_filtered_messages'
853
-        )) {
854
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
855
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
856
-                $fc_items['view_related_messages'] = array(
857
-                    'class' => $related_for_icon['css_class'],
858
-                    'desc'  => $related_for_icon['label'],
859
-                );
860
-            }
861
-        }
862
-        $sc_items = array(
863
-            'approved_status'   => array(
864
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
865
-                'desc'  => EEH_Template::pretty_status(
866
-                    EEM_Registration::status_id_approved,
867
-                    false,
868
-                    'sentence'
869
-                ),
870
-            ),
871
-            'pending_status'    => array(
872
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
873
-                'desc'  => EEH_Template::pretty_status(
874
-                    EEM_Registration::status_id_pending_payment,
875
-                    false,
876
-                    'sentence'
877
-                ),
878
-            ),
879
-            'wait_list'         => array(
880
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
881
-                'desc'  => EEH_Template::pretty_status(
882
-                    EEM_Registration::status_id_wait_list,
883
-                    false,
884
-                    'sentence'
885
-                ),
886
-            ),
887
-            'incomplete_status' => array(
888
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
889
-                'desc'  => EEH_Template::pretty_status(
890
-                    EEM_Registration::status_id_incomplete,
891
-                    false,
892
-                    'sentence'
893
-                ),
894
-            ),
895
-            'not_approved'      => array(
896
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
897
-                'desc'  => EEH_Template::pretty_status(
898
-                    EEM_Registration::status_id_not_approved,
899
-                    false,
900
-                    'sentence'
901
-                ),
902
-            ),
903
-            'declined_status'   => array(
904
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
905
-                'desc'  => EEH_Template::pretty_status(
906
-                    EEM_Registration::status_id_declined,
907
-                    false,
908
-                    'sentence'
909
-                ),
910
-            ),
911
-            'cancelled_status'  => array(
912
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
913
-                'desc'  => EEH_Template::pretty_status(
914
-                    EEM_Registration::status_id_cancelled,
915
-                    false,
916
-                    'sentence'
917
-                ),
918
-            ),
919
-        );
920
-        return array_merge($fc_items, $sc_items);
921
-    }
922
-
923
-
924
-
925
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
926
-    /**
927
-     * @throws \EE_Error
928
-     */
929
-    protected function _registrations_overview_list_table()
930
-    {
931
-        $this->_template_args['admin_page_header'] = '';
932
-        $EVT_ID                                    = ! empty($this->_req_data['event_id'])
933
-            ? absint($this->_req_data['event_id'])
934
-            : 0;
935
-        if ($EVT_ID) {
936
-            if (EE_Registry::instance()->CAP->current_user_can(
937
-                'ee_edit_registrations',
938
-                'espresso_registrations_new_registration',
939
-                $EVT_ID
940
-            )) {
941
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
942
-                    'new_registration',
943
-                    'add-registrant',
944
-                    array('event_id' => $EVT_ID),
945
-                    'add-new-h2'
946
-                );
947
-            }
948
-            $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
949
-            if ($event instanceof EE_Event) {
950
-                $this->_template_args['admin_page_header'] = sprintf(
951
-                    esc_html__(
952
-                        '%s Viewing registrations for the event: %s%s',
953
-                        'event_espresso'
954
-                    ),
955
-                    '<h3 style="line-height:1.5em;">',
956
-                    '<br /><a href="'
957
-                        . EE_Admin_Page::add_query_args_and_nonce(
958
-                            array(
959
-                                'action' => 'edit',
960
-                                'post'   => $event->ID(),
961
-                            ),
962
-                            EVENTS_ADMIN_URL
963
-                        )
964
-                        . '">&nbsp;'
965
-                        . $event->get('EVT_name')
966
-                        . '&nbsp;</a>&nbsp;',
967
-                    '</h3>'
968
-                );
969
-            }
970
-            $DTT_ID   = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
971
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
972
-            if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
973
-                $this->_template_args['admin_page_header'] = substr(
974
-                    $this->_template_args['admin_page_header'],
975
-                    0,
976
-                    -5
977
-                );
978
-                $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
979
-                $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
980
-                $this->_template_args['admin_page_header'] .= $datetime->name();
981
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
982
-                $this->_template_args['admin_page_header'] .= '</span></h3>';
983
-            }
984
-        }
985
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
986
-        $this->display_admin_list_table_page_with_no_sidebar();
987
-    }
988
-
989
-
990
-    /**
991
-     * This sets the _registration property for the registration details screen
992
-     *
993
-     * @access private
994
-     * @return bool
995
-     */
996
-    private function _set_registration_object()
997
-    {
998
-        //get out if we've already set the object
999
-        if (is_object($this->_registration)) {
1000
-            return true;
1001
-        }
1002
-        $REG    = EEM_Registration::instance();
1003
-        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1004
-        if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1005
-            return true;
1006
-        } else {
1007
-            $error_msg = sprintf(
1008
-                esc_html__(
1009
-                    'An error occurred and the details for Registration ID #%s could not be retrieved.',
1010
-                    'event_espresso'
1011
-                ),
1012
-                $REG_ID
1013
-            );
1014
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1015
-            $this->_registration = null;
1016
-            return false;
1017
-        }
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * Used to retrieve registrations for the list table.
1023
-     *
1024
-     * @param int  $per_page
1025
-     * @param bool $count
1026
-     * @param bool $this_month
1027
-     * @param bool $today
1028
-     * @return EE_Registration[]|int
1029
-     * @throws EE_Error
1030
-     */
1031
-    public function get_registrations(
1032
-        $per_page = 10,
1033
-        $count = false,
1034
-        $this_month = false,
1035
-        $today = false
1036
-    ) {
1037
-        if ($this_month) {
1038
-            $this->_req_data['status'] = 'month';
1039
-        }
1040
-        if ($today) {
1041
-            $this->_req_data['status'] = 'today';
1042
-        }
1043
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1044
-        /**
1045
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1046
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1047
-         * @see EEM_Base::get_all()
1048
-         */
1049
-        $query_params['group_by'] = '';
1050
-
1051
-        return $count
1052
-            ? EEM_Registration::instance()->count($query_params)
1053
-            /** @type EE_Registration[] */
1054
-            : EEM_Registration::instance()->get_all($query_params);
1055
-    }
1056
-
1057
-
1058
-
1059
-    /**
1060
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1061
-     * Note: this listens to values on the request for some of the query parameters.
1062
-     *
1063
-     * @param array $request
1064
-     * @param int    $per_page
1065
-     * @param bool   $count
1066
-     * @return array
1067
-     */
1068
-    protected function _get_registration_query_parameters(
1069
-        $request = array(),
1070
-        $per_page = 10,
1071
-        $count = false
1072
-    ) {
1073
-
1074
-        $query_params = array(
1075
-            0                          => $this->_get_where_conditions_for_registrations_query(
1076
-                $request
1077
-            ),
1078
-            'caps'                     => EEM_Registration::caps_read_admin,
1079
-            'default_where_conditions' => 'this_model_only',
1080
-        );
1081
-        if (! $count) {
1082
-            $query_params = array_merge(
1083
-                $query_params,
1084
-                $this->_get_orderby_for_registrations_query(),
1085
-                $this->_get_limit($per_page)
1086
-            );
1087
-        }
1088
-
1089
-        return $query_params;
1090
-    }
1091
-
1092
-
1093
-    /**
1094
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1095
-     *
1096
-     * @param array $request usually the same as $this->_req_data but not necessarily
1097
-     * @return array
1098
-     */
1099
-    protected function _add_event_id_to_where_conditions(array $request)
1100
-    {
1101
-        $where = array();
1102
-        if (! empty($request['event_id'])) {
1103
-            $where['EVT_ID'] = absint($request['event_id']);
1104
-        }
1105
-        return $where;
1106
-    }
1107
-
1108
-
1109
-    /**
1110
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1111
-     *
1112
-     * @param array $request usually the same as $this->_req_data but not necessarily
1113
-     * @return array
1114
-     */
1115
-    protected function _add_category_id_to_where_conditions(array $request)
1116
-    {
1117
-        $where = array();
1118
-        if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1119
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1120
-        }
1121
-        return $where;
1122
-    }
1123
-
1124
-
1125
-    /**
1126
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1127
-     *
1128
-     * @param array $request usually the same as $this->_req_data but not necessarily
1129
-     * @return array
1130
-     */
1131
-    protected function _add_datetime_id_to_where_conditions(array $request)
1132
-    {
1133
-        $where = array();
1134
-        if (! empty($request['datetime_id'])) {
1135
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1136
-        }
1137
-        if (! empty($request['DTT_ID'])) {
1138
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1139
-        }
1140
-        return $where;
1141
-    }
1142
-
1143
-
1144
-    /**
1145
-     * Adds the correct registration status to the where conditions for the registrations query.
1146
-     *
1147
-     * @param array $request usually the same as $this->_req_data but not necessarily
1148
-     * @return array
1149
-     */
1150
-    protected function _add_registration_status_to_where_conditions(array $request)
1151
-    {
1152
-        $where = array();
1153
-        $view = EEH_Array::is_set($request, 'status', '');
1154
-        $registration_status = ! empty($request['_reg_status'])
1155
-            ? sanitize_text_field($request['_reg_status'])
1156
-            : '';
1157
-
1158
-        /*
26
+	/**
27
+	 * @var EE_Registration
28
+	 */
29
+	private $_registration;
30
+
31
+	/**
32
+	 * @var EE_Event
33
+	 */
34
+	private $_reg_event;
35
+
36
+	/**
37
+	 * @var EE_Session
38
+	 */
39
+	private $_session;
40
+
41
+	private static $_reg_status;
42
+
43
+	/**
44
+	 * Form for displaying the custom questions for this registration.
45
+	 * This gets used a few times throughout the request so its best to cache it
46
+	 *
47
+	 * @var EE_Registration_Custom_Questions_Form
48
+	 */
49
+	protected $_reg_custom_questions_form = null;
50
+
51
+
52
+	/**
53
+	 *        constructor
54
+	 *
55
+	 * @Constructor
56
+	 * @access public
57
+	 * @param bool $routing
58
+	 * @return Registrations_Admin_Page
59
+	 */
60
+	public function __construct($routing = true)
61
+	{
62
+		parent::__construct($routing);
63
+		add_action('wp_loaded', array($this, 'wp_loaded'));
64
+	}
65
+
66
+
67
+	public function wp_loaded()
68
+	{
69
+		// when adding a new registration...
70
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
71
+			EE_System::do_not_cache();
72
+			if (! isset($this->_req_data['processing_registration'])
73
+				 || absint($this->_req_data['processing_registration']) !== 1
74
+			) {
75
+				// and it's NOT the attendee information reg step
76
+				// force cookie expiration by setting time to last week
77
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
78
+				// and update the global
79
+				$_COOKIE['ee_registration_added'] = 0;
80
+			}
81
+		}
82
+	}
83
+
84
+
85
+	protected function _init_page_props()
86
+	{
87
+		$this->page_slug        = REG_PG_SLUG;
88
+		$this->_admin_base_url  = REG_ADMIN_URL;
89
+		$this->_admin_base_path = REG_ADMIN;
90
+		$this->page_label       = esc_html__('Registrations', 'event_espresso');
91
+		$this->_cpt_routes      = array(
92
+			'add_new_attendee' => 'espresso_attendees',
93
+			'edit_attendee'    => 'espresso_attendees',
94
+			'insert_attendee'  => 'espresso_attendees',
95
+			'update_attendee'  => 'espresso_attendees',
96
+		);
97
+		$this->_cpt_model_names = array(
98
+			'add_new_attendee' => 'EEM_Attendee',
99
+			'edit_attendee'    => 'EEM_Attendee',
100
+		);
101
+		$this->_cpt_edit_routes = array(
102
+			'espresso_attendees' => 'edit_attendee',
103
+		);
104
+		$this->_pagenow_map     = array(
105
+			'add_new_attendee' => 'post-new.php',
106
+			'edit_attendee'    => 'post.php',
107
+			'trash'            => 'post.php',
108
+		);
109
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
110
+		//add filters so that the comment urls don't take users to a confusing 404 page
111
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
112
+	}
113
+
114
+
115
+	public function clear_comment_link($link, $comment, $args)
116
+	{
117
+		//gotta make sure this only happens on this route
118
+		$post_type = get_post_type($comment->comment_post_ID);
119
+		if ($post_type === 'espresso_attendees') {
120
+			return '#commentsdiv';
121
+		}
122
+		return $link;
123
+	}
124
+
125
+
126
+	protected function _ajax_hooks()
127
+	{
128
+		//todo: all hooks for registrations ajax goes in here
129
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
130
+	}
131
+
132
+
133
+	protected function _define_page_props()
134
+	{
135
+		$this->_admin_page_title = $this->page_label;
136
+		$this->_labels           = array(
137
+			'buttons'                      => array(
138
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
139
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
140
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
141
+				'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
142
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
143
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
144
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
145
+				'contact_list_export' => esc_html__("Export Data", "event_espresso"),
146
+			),
147
+			'publishbox'                   => array(
148
+				'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
149
+				'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
150
+			),
151
+			'hide_add_button_on_cpt_route' => array(
152
+				'edit_attendee' => true,
153
+			),
154
+		);
155
+	}
156
+
157
+
158
+	/**
159
+	 *        grab url requests and route them
160
+	 *
161
+	 * @access private
162
+	 * @return void
163
+	 */
164
+	public function _set_page_routes()
165
+	{
166
+		$this->_get_registration_status_array();
167
+		$reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
168
+			? $this->_req_data['_REG_ID'] : 0;
169
+		$att_id             = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
170
+			? $this->_req_data['ATT_ID'] : 0;
171
+		$att_id             = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
172
+			? $this->_req_data['post']
173
+			: $att_id;
174
+		$this->_page_routes = array(
175
+			'default'                            => array(
176
+				'func'       => '_registrations_overview_list_table',
177
+				'capability' => 'ee_read_registrations',
178
+			),
179
+			'view_registration'                  => array(
180
+				'func'       => '_registration_details',
181
+				'capability' => 'ee_read_registration',
182
+				'obj_id'     => $reg_id,
183
+			),
184
+			'edit_registration'                  => array(
185
+				'func'               => '_update_attendee_registration_form',
186
+				'noheader'           => true,
187
+				'headers_sent_route' => 'view_registration',
188
+				'capability'         => 'ee_edit_registration',
189
+				'obj_id'             => $reg_id,
190
+				'_REG_ID'            => $reg_id,
191
+			),
192
+			'trash_registrations'                => array(
193
+				'func'       => '_trash_or_restore_registrations',
194
+				'args'       => array('trash' => true),
195
+				'noheader'   => true,
196
+				'capability' => 'ee_delete_registrations',
197
+			),
198
+			'restore_registrations'              => array(
199
+				'func'       => '_trash_or_restore_registrations',
200
+				'args'       => array('trash' => false),
201
+				'noheader'   => true,
202
+				'capability' => 'ee_delete_registrations',
203
+			),
204
+			'delete_registrations'               => array(
205
+				'func'       => '_delete_registrations',
206
+				'noheader'   => true,
207
+				'capability' => 'ee_delete_registrations',
208
+			),
209
+			'new_registration'                   => array(
210
+				'func'       => 'new_registration',
211
+				'capability' => 'ee_edit_registrations',
212
+			),
213
+			'process_reg_step'                   => array(
214
+				'func'       => 'process_reg_step',
215
+				'noheader'   => true,
216
+				'capability' => 'ee_edit_registrations',
217
+			),
218
+			'redirect_to_txn'                    => array(
219
+				'func'       => 'redirect_to_txn',
220
+				'noheader'   => true,
221
+				'capability' => 'ee_edit_registrations',
222
+			),
223
+			'change_reg_status'                  => array(
224
+				'func'       => '_change_reg_status',
225
+				'noheader'   => true,
226
+				'capability' => 'ee_edit_registration',
227
+				'obj_id'     => $reg_id,
228
+			),
229
+			'approve_registration'               => array(
230
+				'func'       => 'approve_registration',
231
+				'noheader'   => true,
232
+				'capability' => 'ee_edit_registration',
233
+				'obj_id'     => $reg_id,
234
+			),
235
+			'approve_and_notify_registration'    => array(
236
+				'func'       => 'approve_registration',
237
+				'noheader'   => true,
238
+				'args'       => array(true),
239
+				'capability' => 'ee_edit_registration',
240
+				'obj_id'     => $reg_id,
241
+			),
242
+			'decline_registration'               => array(
243
+				'func'       => 'decline_registration',
244
+				'noheader'   => true,
245
+				'capability' => 'ee_edit_registration',
246
+				'obj_id'     => $reg_id,
247
+			),
248
+			'decline_and_notify_registration'    => array(
249
+				'func'       => 'decline_registration',
250
+				'noheader'   => true,
251
+				'args'       => array(true),
252
+				'capability' => 'ee_edit_registration',
253
+				'obj_id'     => $reg_id,
254
+			),
255
+			'pending_registration'               => array(
256
+				'func'       => 'pending_registration',
257
+				'noheader'   => true,
258
+				'capability' => 'ee_edit_registration',
259
+				'obj_id'     => $reg_id,
260
+			),
261
+			'pending_and_notify_registration'    => array(
262
+				'func'       => 'pending_registration',
263
+				'noheader'   => true,
264
+				'args'       => array(true),
265
+				'capability' => 'ee_edit_registration',
266
+				'obj_id'     => $reg_id,
267
+			),
268
+			'no_approve_registration'            => array(
269
+				'func'       => 'not_approve_registration',
270
+				'noheader'   => true,
271
+				'capability' => 'ee_edit_registration',
272
+				'obj_id'     => $reg_id,
273
+			),
274
+			'no_approve_and_notify_registration' => array(
275
+				'func'       => 'not_approve_registration',
276
+				'noheader'   => true,
277
+				'args'       => array(true),
278
+				'capability' => 'ee_edit_registration',
279
+				'obj_id'     => $reg_id,
280
+			),
281
+			'cancel_registration'                => array(
282
+				'func'       => 'cancel_registration',
283
+				'noheader'   => true,
284
+				'capability' => 'ee_edit_registration',
285
+				'obj_id'     => $reg_id,
286
+			),
287
+			'cancel_and_notify_registration'     => array(
288
+				'func'       => 'cancel_registration',
289
+				'noheader'   => true,
290
+				'args'       => array(true),
291
+				'capability' => 'ee_edit_registration',
292
+				'obj_id'     => $reg_id,
293
+			),
294
+			'wait_list_registration' => array(
295
+				'func'       => 'wait_list_registration',
296
+				'noheader'   => true,
297
+				'capability' => 'ee_edit_registration',
298
+				'obj_id'     => $reg_id,
299
+			),
300
+			'contact_list'                       => array(
301
+				'func'       => '_attendee_contact_list_table',
302
+				'capability' => 'ee_read_contacts',
303
+			),
304
+			'add_new_attendee'                   => array(
305
+				'func' => '_create_new_cpt_item',
306
+				'args' => array(
307
+					'new_attendee' => true,
308
+					'capability'   => 'ee_edit_contacts',
309
+				),
310
+			),
311
+			'edit_attendee'                      => array(
312
+				'func'       => '_edit_cpt_item',
313
+				'capability' => 'ee_edit_contacts',
314
+				'obj_id'     => $att_id,
315
+			),
316
+			'duplicate_attendee'                 => array(
317
+				'func'       => '_duplicate_attendee',
318
+				'noheader'   => true,
319
+				'capability' => 'ee_edit_contacts',
320
+				'obj_id'     => $att_id,
321
+			),
322
+			'insert_attendee'                    => array(
323
+				'func'       => '_insert_or_update_attendee',
324
+				'args'       => array(
325
+					'new_attendee' => true,
326
+				),
327
+				'noheader'   => true,
328
+				'capability' => 'ee_edit_contacts',
329
+			),
330
+			'update_attendee'                    => array(
331
+				'func'       => '_insert_or_update_attendee',
332
+				'args'       => array(
333
+					'new_attendee' => false,
334
+				),
335
+				'noheader'   => true,
336
+				'capability' => 'ee_edit_contacts',
337
+				'obj_id'     => $att_id,
338
+			),
339
+			'trash_attendees' => array(
340
+				'func' => '_trash_or_restore_attendees',
341
+				'args' => array(
342
+					'trash' => 'true'
343
+				),
344
+				'noheader' => true,
345
+				'capability' => 'ee_delete_contacts'
346
+			),
347
+			'trash_attendee'                    => array(
348
+				'func'       => '_trash_or_restore_attendees',
349
+				'args'       => array(
350
+					'trash' => true,
351
+				),
352
+				'noheader'   => true,
353
+				'capability' => 'ee_delete_contacts',
354
+				'obj_id'     => $att_id,
355
+			),
356
+			'restore_attendees'                  => array(
357
+				'func'       => '_trash_or_restore_attendees',
358
+				'args'       => array(
359
+					'trash' => false,
360
+				),
361
+				'noheader'   => true,
362
+				'capability' => 'ee_delete_contacts',
363
+				'obj_id'     => $att_id,
364
+			),
365
+			'resend_registration'                => array(
366
+				'func'       => '_resend_registration',
367
+				'noheader'   => true,
368
+				'capability' => 'ee_send_message',
369
+			),
370
+			'registrations_report'               => array(
371
+				'func'       => '_registrations_report',
372
+				'noheader'   => true,
373
+				'capability' => 'ee_read_registrations',
374
+			),
375
+			'contact_list_export'                => array(
376
+				'func'       => '_contact_list_export',
377
+				'noheader'   => true,
378
+				'capability' => 'export',
379
+			),
380
+			'contact_list_report'                => array(
381
+				'func'       => '_contact_list_report',
382
+				'noheader'   => true,
383
+				'capability' => 'ee_read_contacts',
384
+			),
385
+		);
386
+	}
387
+
388
+
389
+	protected function _set_page_config()
390
+	{
391
+		$this->_page_config = array(
392
+			'default'           => array(
393
+				'nav'           => array(
394
+					'label' => esc_html__('Overview', 'event_espresso'),
395
+					'order' => 5,
396
+				),
397
+				'help_tabs'     => array(
398
+					'registrations_overview_help_tab'                       => array(
399
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
400
+						'filename' => 'registrations_overview',
401
+					),
402
+					'registrations_overview_table_column_headings_help_tab' => array(
403
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
404
+						'filename' => 'registrations_overview_table_column_headings',
405
+					),
406
+					'registrations_overview_filters_help_tab'               => array(
407
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
408
+						'filename' => 'registrations_overview_filters',
409
+					),
410
+					'registrations_overview_views_help_tab'                 => array(
411
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
412
+						'filename' => 'registrations_overview_views',
413
+					),
414
+					'registrations_regoverview_other_help_tab'              => array(
415
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
416
+						'filename' => 'registrations_overview_other',
417
+					),
418
+				),
419
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
420
+				'qtips'         => array('Registration_List_Table_Tips'),
421
+				'list_table'    => 'EE_Registrations_List_Table',
422
+				'require_nonce' => false,
423
+			),
424
+			'view_registration' => array(
425
+				'nav'           => array(
426
+					'label'      => esc_html__('REG Details', 'event_espresso'),
427
+					'order'      => 15,
428
+					'url'        => isset($this->_req_data['_REG_ID'])
429
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
430
+						: $this->_admin_base_url,
431
+					'persistent' => false,
432
+				),
433
+				'help_tabs'     => array(
434
+					'registrations_details_help_tab'                    => array(
435
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
436
+						'filename' => 'registrations_details',
437
+					),
438
+					'registrations_details_table_help_tab'              => array(
439
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
440
+						'filename' => 'registrations_details_table',
441
+					),
442
+					'registrations_details_form_answers_help_tab'       => array(
443
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
444
+						'filename' => 'registrations_details_form_answers',
445
+					),
446
+					'registrations_details_registrant_details_help_tab' => array(
447
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
448
+						'filename' => 'registrations_details_registrant_details',
449
+					),
450
+				),
451
+				'help_tour'     => array('Registration_Details_Help_Tour'),
452
+				'metaboxes'     => array_merge(
453
+					$this->_default_espresso_metaboxes,
454
+					array('_registration_details_metaboxes')
455
+				),
456
+				'require_nonce' => false,
457
+			),
458
+			'new_registration'  => array(
459
+				'nav'           => array(
460
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
461
+					'url'        => '#',
462
+					'order'      => 15,
463
+					'persistent' => false,
464
+				),
465
+				'metaboxes'     => $this->_default_espresso_metaboxes,
466
+				'labels'        => array(
467
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
468
+				),
469
+				'require_nonce' => false,
470
+			),
471
+			'add_new_attendee'  => array(
472
+				'nav'           => array(
473
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
474
+					'order'      => 15,
475
+					'persistent' => false,
476
+				),
477
+				'metaboxes'     => array_merge(
478
+					$this->_default_espresso_metaboxes,
479
+					array('_publish_post_box', 'attendee_editor_metaboxes')
480
+				),
481
+				'require_nonce' => false,
482
+			),
483
+			'edit_attendee'     => array(
484
+				'nav'           => array(
485
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
486
+					'order'      => 15,
487
+					'persistent' => false,
488
+					'url'        => isset($this->_req_data['ATT_ID'])
489
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
490
+						: $this->_admin_base_url,
491
+				),
492
+				'metaboxes'     => array('attendee_editor_metaboxes'),
493
+				'require_nonce' => false,
494
+			),
495
+			'contact_list'      => array(
496
+				'nav'           => array(
497
+					'label' => esc_html__('Contact List', 'event_espresso'),
498
+					'order' => 20,
499
+				),
500
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
501
+				'help_tabs'     => array(
502
+					'registrations_contact_list_help_tab'                       => array(
503
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
504
+						'filename' => 'registrations_contact_list',
505
+					),
506
+					'registrations_contact-list_table_column_headings_help_tab' => array(
507
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
508
+						'filename' => 'registrations_contact_list_table_column_headings',
509
+					),
510
+					'registrations_contact_list_views_help_tab'                 => array(
511
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
512
+						'filename' => 'registrations_contact_list_views',
513
+					),
514
+					'registrations_contact_list_other_help_tab'                 => array(
515
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
516
+						'filename' => 'registrations_contact_list_other',
517
+					),
518
+				),
519
+				'help_tour'     => array('Contact_List_Help_Tour'),
520
+				'metaboxes'     => array(),
521
+				'require_nonce' => false,
522
+			),
523
+			//override default cpt routes
524
+			'create_new'        => '',
525
+			'edit'              => '',
526
+		);
527
+	}
528
+
529
+
530
+	/**
531
+	 * The below methods aren't used by this class currently
532
+	 */
533
+	protected function _add_screen_options()
534
+	{
535
+	}
536
+
537
+
538
+	protected function _add_feature_pointers()
539
+	{
540
+	}
541
+
542
+
543
+	public function admin_init()
544
+	{
545
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
546
+			'click "Update Registration Questions" to save your changes',
547
+			'event_espresso'
548
+		);
549
+	}
550
+
551
+
552
+	public function admin_notices()
553
+	{
554
+	}
555
+
556
+
557
+	public function admin_footer_scripts()
558
+	{
559
+	}
560
+
561
+
562
+	/**
563
+	 *        get list of registration statuses
564
+	 *
565
+	 * @access private
566
+	 * @return void
567
+	 */
568
+	private function _get_registration_status_array()
569
+	{
570
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
571
+	}
572
+
573
+
574
+	protected function _add_screen_options_default()
575
+	{
576
+		$this->_per_page_screen_option();
577
+	}
578
+
579
+
580
+	protected function _add_screen_options_contact_list()
581
+	{
582
+		$page_title              = $this->_admin_page_title;
583
+		$this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
584
+		$this->_per_page_screen_option();
585
+		$this->_admin_page_title = $page_title;
586
+	}
587
+
588
+
589
+	public function load_scripts_styles()
590
+	{
591
+		//style
592
+		wp_register_style(
593
+			'espresso_reg',
594
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
595
+			array('ee-admin-css'),
596
+			EVENT_ESPRESSO_VERSION
597
+		);
598
+		wp_enqueue_style('espresso_reg');
599
+		//script
600
+		wp_register_script(
601
+			'espresso_reg',
602
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
603
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
604
+			EVENT_ESPRESSO_VERSION,
605
+			true
606
+		);
607
+		wp_enqueue_script('espresso_reg');
608
+	}
609
+
610
+
611
+	public function load_scripts_styles_edit_attendee()
612
+	{
613
+		//stuff to only show up on our attendee edit details page.
614
+		$attendee_details_translations = array(
615
+			'att_publish_text' => sprintf(
616
+				esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
617
+				$this->_cpt_model_obj->get_datetime('ATT_created')
618
+			),
619
+		);
620
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
621
+		wp_enqueue_script('jquery-validate');
622
+	}
623
+
624
+
625
+	public function load_scripts_styles_view_registration()
626
+	{
627
+		//styles
628
+		wp_enqueue_style('espresso-ui-theme');
629
+		//scripts
630
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
631
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
632
+	}
633
+
634
+
635
+	public function load_scripts_styles_contact_list()
636
+	{
637
+		wp_deregister_style('espresso_reg');
638
+		wp_register_style(
639
+			'espresso_att',
640
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
641
+			array('ee-admin-css'),
642
+			EVENT_ESPRESSO_VERSION
643
+		);
644
+		wp_enqueue_style('espresso_att');
645
+	}
646
+
647
+
648
+	public function load_scripts_styles_new_registration()
649
+	{
650
+		wp_register_script(
651
+			'ee-spco-for-admin',
652
+			REG_ASSETS_URL . 'spco_for_admin.js',
653
+			array('underscore', 'jquery'),
654
+			EVENT_ESPRESSO_VERSION,
655
+			true
656
+		);
657
+		wp_enqueue_script('ee-spco-for-admin');
658
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
659
+		EE_Form_Section_Proper::wp_enqueue_scripts();
660
+		EED_Ticket_Selector::load_tckt_slctr_assets();
661
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
662
+	}
663
+
664
+
665
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
666
+	{
667
+		add_filter('FHEE_load_EE_messages', '__return_true');
668
+	}
669
+
670
+
671
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
672
+	{
673
+		add_filter('FHEE_load_EE_messages', '__return_true');
674
+	}
675
+
676
+
677
+	protected function _set_list_table_views_default()
678
+	{
679
+		//for notification related bulk actions we need to make sure only active messengers have an option.
680
+		EED_Messages::set_autoloaders();
681
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
682
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
683
+		$active_mts               = $message_resource_manager->list_of_active_message_types();
684
+		//key= bulk_action_slug, value= message type.
685
+		$match_array = array(
686
+			'approve_registration'    => 'registration',
687
+			'decline_registration'    => 'declined_registration',
688
+			'pending_registration'    => 'pending_approval',
689
+			'no_approve_registration' => 'not_approved_registration',
690
+			'cancel_registration'     => 'cancelled_registration',
691
+		);
692
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
693
+			'ee_send_message',
694
+			'batch_send_messages'
695
+		);
696
+		/** setup reg status bulk actions **/
697
+		$def_reg_status_actions['approve_registration'] = __('Approve Registrations', 'event_espresso');
698
+		if ($can_send && in_array($match_array['approve_registration'], $active_mts, true)) {
699
+				$def_reg_status_actions['approve_and_notify_registration'] = __('Approve and Notify Registrations',
700
+					'event_espresso');
701
+		}
702
+		$def_reg_status_actions['decline_registration'] = __('Decline Registrations', 'event_espresso');
703
+		if ($can_send && in_array($match_array['decline_registration'], $active_mts, true)) {
704
+				$def_reg_status_actions['decline_and_notify_registration'] = __('Decline and Notify Registrations',
705
+					'event_espresso');
706
+		}
707
+		$def_reg_status_actions['pending_registration'] = __('Set Registrations to Pending Payment', 'event_espresso');
708
+		if ($can_send && in_array($match_array['pending_registration'], $active_mts, true)) {
709
+				$def_reg_status_actions['pending_and_notify_registration'] = __(
710
+					'Set Registrations to Pending Payment and Notify',
711
+					'event_espresso'
712
+				);
713
+		}
714
+		$def_reg_status_actions['no_approve_registration'] = __('Set Registrations to Not Approved', 'event_espresso');
715
+		if ($can_send && in_array($match_array['no_approve_registration'], $active_mts, true)) {
716
+				$def_reg_status_actions['no_approve_and_notify_registration'] = __(
717
+					'Set Registrations to Not Approved and Notify',
718
+					'event_espresso'
719
+				);
720
+		}
721
+		$def_reg_status_actions['cancel_registration'] = __('Cancel Registrations', 'event_espresso');
722
+		if ($can_send && in_array($match_array['cancel_registration'], $active_mts, true)) {
723
+				$def_reg_status_actions['cancel_and_notify_registration'] = __(
724
+					'Cancel Registrations and Notify',
725
+					'event_espresso'
726
+				);
727
+		}
728
+		$def_reg_status_actions = apply_filters(
729
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
730
+			$def_reg_status_actions,
731
+			$active_mts
732
+		);
733
+
734
+		$this->_views = array(
735
+			'all'   => array(
736
+				'slug'        => 'all',
737
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
738
+				'count'       => 0,
739
+				'bulk_action' => array_merge($def_reg_status_actions, array(
740
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
741
+				)),
742
+			),
743
+			'month' => array(
744
+				'slug'        => 'month',
745
+				'label'       => esc_html__('This Month', 'event_espresso'),
746
+				'count'       => 0,
747
+				'bulk_action' => array_merge($def_reg_status_actions, array(
748
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
749
+				)),
750
+			),
751
+			'today' => array(
752
+				'slug'        => 'today',
753
+				'label'       => sprintf(
754
+					esc_html__('Today - %s', 'event_espresso'),
755
+					date('M d, Y', current_time('timestamp'))
756
+				),
757
+				'count'       => 0,
758
+				'bulk_action' => array_merge($def_reg_status_actions, array(
759
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
760
+				)),
761
+			),
762
+		);
763
+		if (EE_Registry::instance()->CAP->current_user_can(
764
+			'ee_delete_registrations',
765
+			'espresso_registrations_delete_registration'
766
+		)) {
767
+			$this->_views['incomplete'] = array(
768
+				'slug'        => 'incomplete',
769
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
770
+				'count'       => 0,
771
+				'bulk_action' => array(
772
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
773
+				),
774
+			);
775
+			$this->_views['trash']      = array(
776
+				'slug'        => 'trash',
777
+				'label'       => esc_html__('Trash', 'event_espresso'),
778
+				'count'       => 0,
779
+				'bulk_action' => array(
780
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
781
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
782
+				),
783
+			);
784
+		}
785
+	}
786
+
787
+
788
+	protected function _set_list_table_views_contact_list()
789
+	{
790
+		$this->_views = array(
791
+			'in_use' => array(
792
+				'slug'        => 'in_use',
793
+				'label'       => esc_html__('In Use', 'event_espresso'),
794
+				'count'       => 0,
795
+				'bulk_action' => array(
796
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
797
+				),
798
+			),
799
+		);
800
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_contacts',
801
+			'espresso_registrations_trash_attendees')
802
+		) {
803
+			$this->_views['trash'] = array(
804
+				'slug'        => 'trash',
805
+				'label'       => esc_html__('Trash', 'event_espresso'),
806
+				'count'       => 0,
807
+				'bulk_action' => array(
808
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
809
+				),
810
+			);
811
+		}
812
+	}
813
+
814
+
815
+	protected function _registration_legend_items()
816
+	{
817
+		$fc_items = array(
818
+			'star-icon'        => array(
819
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
820
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
821
+			),
822
+			'view_details'     => array(
823
+				'class' => 'dashicons dashicons-clipboard',
824
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
825
+			),
826
+			'edit_attendee'    => array(
827
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
828
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
829
+			),
830
+			'view_transaction' => array(
831
+				'class' => 'dashicons dashicons-cart',
832
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
833
+			),
834
+			'view_invoice'     => array(
835
+				'class' => 'dashicons dashicons-media-spreadsheet',
836
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
837
+			),
838
+		);
839
+		if (EE_Registry::instance()->CAP->current_user_can(
840
+			'ee_send_message',
841
+			'espresso_registrations_resend_registration'
842
+		)) {
843
+			$fc_items['resend_registration'] = array(
844
+				'class' => 'dashicons dashicons-email-alt',
845
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
846
+			);
847
+		} else {
848
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
849
+		}
850
+		if (EE_Registry::instance()->CAP->current_user_can(
851
+			'ee_read_global_messages',
852
+			'view_filtered_messages'
853
+		)) {
854
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
855
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
856
+				$fc_items['view_related_messages'] = array(
857
+					'class' => $related_for_icon['css_class'],
858
+					'desc'  => $related_for_icon['label'],
859
+				);
860
+			}
861
+		}
862
+		$sc_items = array(
863
+			'approved_status'   => array(
864
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
865
+				'desc'  => EEH_Template::pretty_status(
866
+					EEM_Registration::status_id_approved,
867
+					false,
868
+					'sentence'
869
+				),
870
+			),
871
+			'pending_status'    => array(
872
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
873
+				'desc'  => EEH_Template::pretty_status(
874
+					EEM_Registration::status_id_pending_payment,
875
+					false,
876
+					'sentence'
877
+				),
878
+			),
879
+			'wait_list'         => array(
880
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
881
+				'desc'  => EEH_Template::pretty_status(
882
+					EEM_Registration::status_id_wait_list,
883
+					false,
884
+					'sentence'
885
+				),
886
+			),
887
+			'incomplete_status' => array(
888
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
889
+				'desc'  => EEH_Template::pretty_status(
890
+					EEM_Registration::status_id_incomplete,
891
+					false,
892
+					'sentence'
893
+				),
894
+			),
895
+			'not_approved'      => array(
896
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
897
+				'desc'  => EEH_Template::pretty_status(
898
+					EEM_Registration::status_id_not_approved,
899
+					false,
900
+					'sentence'
901
+				),
902
+			),
903
+			'declined_status'   => array(
904
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
905
+				'desc'  => EEH_Template::pretty_status(
906
+					EEM_Registration::status_id_declined,
907
+					false,
908
+					'sentence'
909
+				),
910
+			),
911
+			'cancelled_status'  => array(
912
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
913
+				'desc'  => EEH_Template::pretty_status(
914
+					EEM_Registration::status_id_cancelled,
915
+					false,
916
+					'sentence'
917
+				),
918
+			),
919
+		);
920
+		return array_merge($fc_items, $sc_items);
921
+	}
922
+
923
+
924
+
925
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
926
+	/**
927
+	 * @throws \EE_Error
928
+	 */
929
+	protected function _registrations_overview_list_table()
930
+	{
931
+		$this->_template_args['admin_page_header'] = '';
932
+		$EVT_ID                                    = ! empty($this->_req_data['event_id'])
933
+			? absint($this->_req_data['event_id'])
934
+			: 0;
935
+		if ($EVT_ID) {
936
+			if (EE_Registry::instance()->CAP->current_user_can(
937
+				'ee_edit_registrations',
938
+				'espresso_registrations_new_registration',
939
+				$EVT_ID
940
+			)) {
941
+				$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
942
+					'new_registration',
943
+					'add-registrant',
944
+					array('event_id' => $EVT_ID),
945
+					'add-new-h2'
946
+				);
947
+			}
948
+			$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
949
+			if ($event instanceof EE_Event) {
950
+				$this->_template_args['admin_page_header'] = sprintf(
951
+					esc_html__(
952
+						'%s Viewing registrations for the event: %s%s',
953
+						'event_espresso'
954
+					),
955
+					'<h3 style="line-height:1.5em;">',
956
+					'<br /><a href="'
957
+						. EE_Admin_Page::add_query_args_and_nonce(
958
+							array(
959
+								'action' => 'edit',
960
+								'post'   => $event->ID(),
961
+							),
962
+							EVENTS_ADMIN_URL
963
+						)
964
+						. '">&nbsp;'
965
+						. $event->get('EVT_name')
966
+						. '&nbsp;</a>&nbsp;',
967
+					'</h3>'
968
+				);
969
+			}
970
+			$DTT_ID   = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
971
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
972
+			if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
973
+				$this->_template_args['admin_page_header'] = substr(
974
+					$this->_template_args['admin_page_header'],
975
+					0,
976
+					-5
977
+				);
978
+				$this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
979
+				$this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
980
+				$this->_template_args['admin_page_header'] .= $datetime->name();
981
+				$this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
982
+				$this->_template_args['admin_page_header'] .= '</span></h3>';
983
+			}
984
+		}
985
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
986
+		$this->display_admin_list_table_page_with_no_sidebar();
987
+	}
988
+
989
+
990
+	/**
991
+	 * This sets the _registration property for the registration details screen
992
+	 *
993
+	 * @access private
994
+	 * @return bool
995
+	 */
996
+	private function _set_registration_object()
997
+	{
998
+		//get out if we've already set the object
999
+		if (is_object($this->_registration)) {
1000
+			return true;
1001
+		}
1002
+		$REG    = EEM_Registration::instance();
1003
+		$REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1004
+		if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1005
+			return true;
1006
+		} else {
1007
+			$error_msg = sprintf(
1008
+				esc_html__(
1009
+					'An error occurred and the details for Registration ID #%s could not be retrieved.',
1010
+					'event_espresso'
1011
+				),
1012
+				$REG_ID
1013
+			);
1014
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1015
+			$this->_registration = null;
1016
+			return false;
1017
+		}
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * Used to retrieve registrations for the list table.
1023
+	 *
1024
+	 * @param int  $per_page
1025
+	 * @param bool $count
1026
+	 * @param bool $this_month
1027
+	 * @param bool $today
1028
+	 * @return EE_Registration[]|int
1029
+	 * @throws EE_Error
1030
+	 */
1031
+	public function get_registrations(
1032
+		$per_page = 10,
1033
+		$count = false,
1034
+		$this_month = false,
1035
+		$today = false
1036
+	) {
1037
+		if ($this_month) {
1038
+			$this->_req_data['status'] = 'month';
1039
+		}
1040
+		if ($today) {
1041
+			$this->_req_data['status'] = 'today';
1042
+		}
1043
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1044
+		/**
1045
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1046
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1047
+		 * @see EEM_Base::get_all()
1048
+		 */
1049
+		$query_params['group_by'] = '';
1050
+
1051
+		return $count
1052
+			? EEM_Registration::instance()->count($query_params)
1053
+			/** @type EE_Registration[] */
1054
+			: EEM_Registration::instance()->get_all($query_params);
1055
+	}
1056
+
1057
+
1058
+
1059
+	/**
1060
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1061
+	 * Note: this listens to values on the request for some of the query parameters.
1062
+	 *
1063
+	 * @param array $request
1064
+	 * @param int    $per_page
1065
+	 * @param bool   $count
1066
+	 * @return array
1067
+	 */
1068
+	protected function _get_registration_query_parameters(
1069
+		$request = array(),
1070
+		$per_page = 10,
1071
+		$count = false
1072
+	) {
1073
+
1074
+		$query_params = array(
1075
+			0                          => $this->_get_where_conditions_for_registrations_query(
1076
+				$request
1077
+			),
1078
+			'caps'                     => EEM_Registration::caps_read_admin,
1079
+			'default_where_conditions' => 'this_model_only',
1080
+		);
1081
+		if (! $count) {
1082
+			$query_params = array_merge(
1083
+				$query_params,
1084
+				$this->_get_orderby_for_registrations_query(),
1085
+				$this->_get_limit($per_page)
1086
+			);
1087
+		}
1088
+
1089
+		return $query_params;
1090
+	}
1091
+
1092
+
1093
+	/**
1094
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1095
+	 *
1096
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1097
+	 * @return array
1098
+	 */
1099
+	protected function _add_event_id_to_where_conditions(array $request)
1100
+	{
1101
+		$where = array();
1102
+		if (! empty($request['event_id'])) {
1103
+			$where['EVT_ID'] = absint($request['event_id']);
1104
+		}
1105
+		return $where;
1106
+	}
1107
+
1108
+
1109
+	/**
1110
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1111
+	 *
1112
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1113
+	 * @return array
1114
+	 */
1115
+	protected function _add_category_id_to_where_conditions(array $request)
1116
+	{
1117
+		$where = array();
1118
+		if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1119
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1120
+		}
1121
+		return $where;
1122
+	}
1123
+
1124
+
1125
+	/**
1126
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1127
+	 *
1128
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1129
+	 * @return array
1130
+	 */
1131
+	protected function _add_datetime_id_to_where_conditions(array $request)
1132
+	{
1133
+		$where = array();
1134
+		if (! empty($request['datetime_id'])) {
1135
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1136
+		}
1137
+		if (! empty($request['DTT_ID'])) {
1138
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1139
+		}
1140
+		return $where;
1141
+	}
1142
+
1143
+
1144
+	/**
1145
+	 * Adds the correct registration status to the where conditions for the registrations query.
1146
+	 *
1147
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1148
+	 * @return array
1149
+	 */
1150
+	protected function _add_registration_status_to_where_conditions(array $request)
1151
+	{
1152
+		$where = array();
1153
+		$view = EEH_Array::is_set($request, 'status', '');
1154
+		$registration_status = ! empty($request['_reg_status'])
1155
+			? sanitize_text_field($request['_reg_status'])
1156
+			: '';
1157
+
1158
+		/*
1159 1159
          * If filtering by registration status, then we show registrations matching that status.
1160 1160
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1161 1161
          * UNLESS viewing trashed registrations.
1162 1162
          */
1163
-        if (! empty($registration_status)) {
1164
-            $where['STS_ID'] = $registration_status;
1165
-        } else {
1166
-            //make sure we exclude incomplete registrations, but only if not trashed.
1167
-            if ($view === 'trash') {
1168
-                $where['REG_deleted'] = true;
1169
-            } elseif ($view === 'incomplete') {
1170
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1171
-            } else {
1172
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1173
-            }
1174
-        }
1175
-        return $where;
1176
-    }
1177
-
1178
-
1179
-    /**
1180
-     * Adds any provided date restraints to the where conditions for the registrations query.
1181
-     *
1182
-     * @param array $request usually the same as $this->_req_data but not necessarily
1183
-     * @return array
1184
-     * @throws EE_Error
1185
-     */
1186
-    protected function _add_date_to_where_conditions(array $request)
1187
-    {
1188
-        $where = array();
1189
-        $view = EEH_Array::is_set($request, 'status', '');
1190
-        $month_range             = ! empty($request['month_range'])
1191
-            ? sanitize_text_field($request['month_range'])
1192
-            : '';
1193
-        $retrieve_for_today      = $view === 'today';
1194
-        $retrieve_for_this_month = $view === 'month';
1195
-
1196
-        if ($retrieve_for_today) {
1197
-            $now               = date('Y-m-d', current_time('timestamp'));
1198
-            $where['REG_date'] = array(
1199
-                'BETWEEN',
1200
-                array(
1201
-                    EEM_Registration::instance()->convert_datetime_for_query(
1202
-                        'REG_date',
1203
-                        $now . ' 00:00:00',
1204
-                        'Y-m-d H:i:s'
1205
-                    ),
1206
-                    EEM_Registration::instance()->convert_datetime_for_query(
1207
-                        'REG_date',
1208
-                        $now . ' 23:59:59',
1209
-                        'Y-m-d H:i:s'
1210
-                    ),
1211
-                ),
1212
-            );
1213
-        } elseif ($retrieve_for_this_month) {
1214
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1215
-            $days_this_month        = date('t', current_time('timestamp'));
1216
-            $where['REG_date']      = array(
1217
-                'BETWEEN',
1218
-                array(
1219
-                    EEM_Registration::instance()->convert_datetime_for_query(
1220
-                        'REG_date',
1221
-                        $current_year_and_month . '-01 00:00:00',
1222
-                        'Y-m-d H:i:s'
1223
-                    ),
1224
-                    EEM_Registration::instance()->convert_datetime_for_query(
1225
-                        'REG_date',
1226
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1227
-                        'Y-m-d H:i:s'
1228
-                    ),
1229
-                ),
1230
-            );
1231
-        } elseif ($month_range) {
1232
-            $pieces          = explode(' ', $month_range, 3);
1233
-            $month_requested = ! empty($pieces[0])
1234
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1235
-                : '';
1236
-            $year_requested  = ! empty($pieces[1])
1237
-                ? $pieces[1]
1238
-                : '';
1239
-            //if there is not a month or year then we can't go further
1240
-            if ($month_requested && $year_requested) {
1241
-                $days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1242
-                $where['REG_date'] = array(
1243
-                    'BETWEEN',
1244
-                    array(
1245
-                        EEM_Registration::instance()->convert_datetime_for_query(
1246
-                            'REG_date',
1247
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1248
-                            'Y-m-d H:i:s'
1249
-                        ),
1250
-                        EEM_Registration::instance()->convert_datetime_for_query(
1251
-                            'REG_date',
1252
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1253
-                            'Y-m-d H:i:s'
1254
-                        ),
1255
-                    ),
1256
-                );
1257
-            }
1258
-        }
1259
-        return $where;
1260
-    }
1261
-
1262
-
1263
-    /**
1264
-     * Adds any provided search restraints to the where conditions for the registrations query
1265
-     *
1266
-     * @param array $request usually the same as $this->_req_data but not necessarily
1267
-     * @return array
1268
-     */
1269
-    protected function _add_search_to_where_conditions(array $request)
1270
-    {
1271
-        $where = array();
1272
-        if (! empty($request['s'])) {
1273
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1274
-            $where['OR*search_conditions'] = array(
1275
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1276
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1277
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1278
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1279
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1280
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1281
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1282
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1283
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1284
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1285
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1286
-                'REG_final_price'                         => array('LIKE', $search_string),
1287
-                'REG_code'                                => array('LIKE', $search_string),
1288
-                'REG_count'                               => array('LIKE', $search_string),
1289
-                'REG_group_size'                          => array('LIKE', $search_string),
1290
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1291
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1292
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1293
-            );
1294
-        }
1295
-        return $where;
1296
-    }
1297
-
1298
-
1299
-    /**
1300
-     * Sets up the where conditions for the registrations query.
1301
-     *
1302
-     * @param array $request
1303
-     * @return array
1304
-     * @throws EE_Error
1305
-     */
1306
-    protected function _get_where_conditions_for_registrations_query($request)
1307
-    {
1308
-        return apply_filters(
1309
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1310
-            array_merge(
1311
-                $this->_add_event_id_to_where_conditions($request),
1312
-                $this->_add_category_id_to_where_conditions($request),
1313
-                $this->_add_datetime_id_to_where_conditions($request),
1314
-                $this->_add_registration_status_to_where_conditions($request),
1315
-                $this->_add_date_to_where_conditions($request),
1316
-                $this->_add_search_to_where_conditions($request)
1317
-            ),
1318
-            $request
1319
-        );
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * Sets up the orderby for the registrations query.
1325
-     *
1326
-     * @return array
1327
-     */
1328
-    protected function _get_orderby_for_registrations_query()
1329
-    {
1330
-        $orderby_field = ! empty($this->_req_data['orderby'])
1331
-            ? sanitize_text_field($this->_req_data['orderby'])
1332
-            : '';
1333
-        switch ($orderby_field) {
1334
-            case '_REG_ID':
1335
-                $orderby_field = 'REG_ID';
1336
-                break;
1337
-            case '_Reg_status':
1338
-                $orderby_field = 'STS_ID';
1339
-                break;
1340
-            case 'ATT_fname':
1341
-                $orderby_field = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1342
-                break;
1343
-            case 'ATT_lname':
1344
-                $orderby_field = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1345
-                break;
1346
-            case 'event_name':
1347
-                $orderby_field = 'Event.EVT_name';
1348
-                break;
1349
-            case 'DTT_EVT_start':
1350
-                $orderby_field = 'Event.Datetime.DTT_EVT_start';
1351
-                break;
1352
-            default: //'REG_date'
1353
-                $orderby_field = 'REG_date';
1354
-        }
1355
-
1356
-        //order
1357
-        $order = ! empty($this->_req_data['order'])
1358
-            ? sanitize_text_field($this->_req_data['order'])
1359
-            : 'DESC';
1360
-
1361
-        //mutate orderby_field
1362
-        $orderby_field = array_combine(
1363
-            (array) $orderby_field,
1364
-            array_fill(0, count($orderby_field), $order)
1365
-        );
1366
-        return array('order_by' => $orderby_field);
1367
-    }
1368
-
1369
-
1370
-    /**
1371
-     * Sets up the limit for the registrations query.
1372
-     *
1373
-     * @param $per_page
1374
-     * @return array
1375
-     */
1376
-    protected function _get_limit($per_page)
1377
-    {
1378
-        $current_page = ! empty($this->_req_data['paged'])
1379
-            ? absint($this->_req_data['paged'])
1380
-            : 1;
1381
-        $per_page     = ! empty($this->_req_data['perpage'])
1382
-            ? $this->_req_data['perpage']
1383
-            : $per_page;
1384
-
1385
-        //-1 means return all results so get out if that's set.
1386
-        if ((int)$per_page === -1) {
1387
-            return array();
1388
-        }
1389
-        $per_page = absint($per_page);
1390
-        $offset   = ($current_page - 1) * $per_page;
1391
-        return array('limit' => array($offset, $per_page));
1392
-    }
1393
-
1394
-
1395
-    public function get_registration_status_array()
1396
-    {
1397
-        return self::$_reg_status;
1398
-    }
1399
-
1400
-
1401
-
1402
-
1403
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1404
-    /**
1405
-     *        generates HTML for the View Registration Details Admin page
1406
-     *
1407
-     * @access protected
1408
-     * @return void
1409
-     * @throws DomainException
1410
-     * @throws EE_Error
1411
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1412
-     */
1413
-    protected function _registration_details()
1414
-    {
1415
-        $this->_template_args = array();
1416
-        $this->_set_registration_object();
1417
-        if (is_object($this->_registration)) {
1418
-            $transaction                                   = $this->_registration->transaction()
1419
-                ? $this->_registration->transaction()
1420
-                : EE_Transaction::new_instance();
1421
-            $this->_session                                = $transaction->session_data();
1422
-            $event_id                                      = $this->_registration->event_ID();
1423
-            $this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1424
-            $this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1425
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1426
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1427
-            $this->_template_args['grand_total']           = $transaction->total();
1428
-            $this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1429
-            // link back to overview
1430
-            $this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1431
-            $this->_template_args['registration']                = $this->_registration;
1432
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1433
-                array(
1434
-                    'action'   => 'default',
1435
-                    'event_id' => $event_id,
1436
-                ),
1437
-                REG_ADMIN_URL
1438
-            );
1439
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1440
-                array(
1441
-                    'action' => 'default',
1442
-                    'EVT_ID' => $event_id,
1443
-                    'page'   => 'espresso_transactions',
1444
-                ),
1445
-                admin_url('admin.php')
1446
-            );
1447
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1448
-                array(
1449
-                    'page'   => 'espresso_events',
1450
-                    'action' => 'edit',
1451
-                    'post'   => $event_id,
1452
-                ),
1453
-                admin_url('admin.php')
1454
-            );
1455
-            //next and previous links
1456
-            $next_reg                                      = $this->_registration->next(
1457
-                null,
1458
-                array(),
1459
-                'REG_ID'
1460
-            );
1461
-            $this->_template_args['next_registration']     = $next_reg
1462
-                ? $this->_next_link(
1463
-                    EE_Admin_Page::add_query_args_and_nonce(
1464
-                        array(
1465
-                            'action'  => 'view_registration',
1466
-                            '_REG_ID' => $next_reg['REG_ID'],
1467
-                        ),
1468
-                        REG_ADMIN_URL
1469
-                    ),
1470
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1471
-                )
1472
-                : '';
1473
-            $previous_reg                                  = $this->_registration->previous(
1474
-                null,
1475
-                array(),
1476
-                'REG_ID'
1477
-            );
1478
-            $this->_template_args['previous_registration'] = $previous_reg
1479
-                ? $this->_previous_link(
1480
-                    EE_Admin_Page::add_query_args_and_nonce(
1481
-                        array(
1482
-                            'action'  => 'view_registration',
1483
-                            '_REG_ID' => $previous_reg['REG_ID'],
1484
-                        ),
1485
-                        REG_ADMIN_URL
1486
-                    ),
1487
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1488
-                )
1489
-                : '';
1490
-            // grab header
1491
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1492
-            $this->_template_args['REG_ID']            = $this->_registration->ID();
1493
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1494
-                $template_path,
1495
-                $this->_template_args,
1496
-                true
1497
-            );
1498
-        } else {
1499
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1500
-        }
1501
-        // the details template wrapper
1502
-        $this->display_admin_page_with_sidebar();
1503
-    }
1504
-
1505
-
1506
-    protected function _registration_details_metaboxes()
1507
-    {
1508
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1509
-        $this->_set_registration_object();
1510
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1511
-        add_meta_box('edit-reg-status-mbox', esc_html__('Registration Status', 'event_espresso'),
1512
-            array($this, 'set_reg_status_buttons_metabox'), $this->wp_page_slug, 'normal', 'high');
1513
-        add_meta_box('edit-reg-details-mbox', esc_html__('Registration Details', 'event_espresso'),
1514
-            array($this, '_reg_details_meta_box'), $this->wp_page_slug, 'normal', 'high');
1515
-        if ($attendee instanceof EE_Attendee
1516
-            && EE_Registry::instance()->CAP->current_user_can(
1517
-                'ee_edit_registration',
1518
-                'edit-reg-questions-mbox'
1519
-            )
1520
-        ) {
1521
-            add_meta_box(
1522
-                'edit-reg-questions-mbox',
1523
-                esc_html__('Registration Form Answers', 'event_espresso'),
1524
-                array($this, '_reg_questions_meta_box'),
1525
-                $this->wp_page_slug,
1526
-                'normal',
1527
-                'high'
1528
-            );
1529
-        }
1530
-        add_meta_box(
1531
-            'edit-reg-registrant-mbox',
1532
-            esc_html__('Contact Details', 'event_espresso'),
1533
-            array($this, '_reg_registrant_side_meta_box'),
1534
-            $this->wp_page_slug,
1535
-            'side',
1536
-            'high'
1537
-        );
1538
-        if ($this->_registration->group_size() > 1) {
1539
-            add_meta_box(
1540
-                'edit-reg-attendees-mbox',
1541
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1542
-                array($this, '_reg_attendees_meta_box'),
1543
-                $this->wp_page_slug,
1544
-                'normal',
1545
-                'high'
1546
-            );
1547
-        }
1548
-    }
1549
-
1550
-
1551
-    /**
1552
-     * set_reg_status_buttons_metabox
1553
-     *
1554
-     * @access protected
1555
-     * @return string
1556
-     * @throws \EE_Error
1557
-     */
1558
-    public function set_reg_status_buttons_metabox()
1559
-    {
1560
-        $this->_set_registration_object();
1561
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1562
-        echo $change_reg_status_form->form_open(
1563
-            self::add_query_args_and_nonce(
1564
-                array(
1565
-                    'action' => 'change_reg_status',
1566
-                ),
1567
-                REG_ADMIN_URL
1568
-            )
1569
-        );
1570
-        echo $change_reg_status_form->get_html();
1571
-        echo $change_reg_status_form->form_close();
1572
-    }
1573
-
1574
-
1575
-
1576
-    /**
1577
-     * @return EE_Form_Section_Proper
1578
-     * @throws EE_Error
1579
-     */
1580
-    protected function _generate_reg_status_change_form()
1581
-    {
1582
-        return new EE_Form_Section_Proper(array(
1583
-            'name'            => 'reg_status_change_form',
1584
-            'html_id'         => 'reg-status-change-form',
1585
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1586
-            'subsections'     => array(
1587
-                'return'             => new EE_Hidden_Input(array(
1588
-                    'name'    => 'return',
1589
-                    'default' => 'view_registration',
1590
-                )),
1591
-                'REG_ID'             => new EE_Hidden_Input(array(
1592
-                    'name'    => 'REG_ID',
1593
-                    'default' => $this->_registration->ID(),
1594
-                )),
1595
-                'current_status'     => new EE_Form_Section_HTML(
1596
-                    EEH_HTML::tr(
1597
-                        EEH_HTML::th(
1598
-                            EEH_HTML::label(
1599
-                                EEH_HTML::strong(esc_html__('Current Registration Status', 'event_espresso')
1600
-                                )
1601
-                            )
1602
-                        )
1603
-                        . EEH_HTML::td(
1604
-                            EEH_HTML::strong(
1605
-                                $this->_registration->pretty_status(),
1606
-                                '',
1607
-                                'status-' . $this->_registration->status_ID(),
1608
-                                'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1609
-                            )
1610
-                        )
1611
-                    )
1612
-                ),
1613
-                'reg_status'         => new EE_Select_Input(
1614
-                    $this->_get_reg_statuses(),
1615
-                    array(
1616
-                        'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1617
-                        'default'         => $this->_registration->status_ID(),
1618
-                    )
1619
-                ),
1620
-                'send_notifications' => new EE_Yes_No_Input(
1621
-                    array(
1622
-                        'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1623
-                        'default'         => false,
1624
-                        'html_help_text'  => esc_html__(
1625
-                            'If set to "Yes", then the related messages will be sent to the registrant.',
1626
-                            'event_espresso'
1627
-                        ),
1628
-                    )
1629
-                ),
1630
-                'submit'             => new EE_Submit_Input(
1631
-                    array(
1632
-                        'html_class'      => 'button-primary',
1633
-                        'html_label_text' => '&nbsp;',
1634
-                        'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1635
-                    )
1636
-                ),
1637
-            ),
1638
-        ));
1639
-    }
1640
-
1641
-
1642
-    /**
1643
-     * Returns an array of all the buttons for the various statuses and switch status actions
1644
-     *
1645
-     * @return array
1646
-     * @throws EE_Error
1647
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1648
-     */
1649
-    protected function _get_reg_statuses()
1650
-    {
1651
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1652
-        unset ($reg_status_array[EEM_Registration::status_id_incomplete]);
1653
-        // get current reg status
1654
-        $current_status = $this->_registration->status_ID();
1655
-        // is registration for free event? This will determine whether to display the pending payment option
1656
-        if (
1657
-            $current_status !== EEM_Registration::status_id_pending_payment
1658
-            && $this->_registration->transaction()->is_free()
1659
-        ) {
1660
-            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1661
-        }
1662
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1663
-    }
1664
-
1665
-
1666
-
1667
-    /**
1668
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1669
-     *
1670
-     * @param bool $status REG status given for changing registrations to.
1671
-     * @param bool $notify Whether to send messages notifications or not.
1672
-     * @return array  (array with reg_id(s) updated and whether update was successful.
1673
-     * @throws \EE_Error
1674
-     */
1675
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1676
-    {
1677
-        if (isset($this->_req_data['reg_status_change_form'])) {
1678
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1679
-                ? (array)$this->_req_data['reg_status_change_form']['REG_ID'] : array();
1680
-        } else {
1681
-            $REG_IDs = isset($this->_req_data['_REG_ID']) ? (array)$this->_req_data['_REG_ID'] : array();
1682
-        }
1683
-        $success = $this->_set_registration_status($REG_IDs, $status);
1684
-        //notify?
1685
-        if ($success
1686
-            && $notify
1687
-            && EE_Registry::instance()->CAP->current_user_can(
1688
-                'ee_send_message',
1689
-                'espresso_registrations_resend_registration'
1690
-            )
1691
-        ) {
1692
-            $this->_process_resend_registration();
1693
-        }
1694
-        return $success;
1695
-    }
1696
-
1697
-
1698
-
1699
-    /**
1700
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1701
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1702
-     *
1703
-     * @param array $REG_IDs
1704
-     * @param bool  $status
1705
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1706
-     * @throws \RuntimeException
1707
-     * @throws \EE_Error
1708
-     *               the array of updated registrations).
1709
-     * @throws EE_Error
1710
-     * @throws RuntimeException
1711
-     */
1712
-    protected function _set_registration_status($REG_IDs = array(), $status = false)
1713
-    {
1714
-        $success = false;
1715
-        // typecast $REG_IDs
1716
-        $REG_IDs = (array)$REG_IDs;
1717
-        if ( ! empty($REG_IDs)) {
1718
-            $success = true;
1719
-            // set default status if none is passed
1720
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1721
-            // sanitize $REG_IDs
1722
-            $REG_IDs = array_filter($REG_IDs, 'absint');
1723
-            //loop through REG_ID's and change status
1724
-            foreach ($REG_IDs as $REG_ID) {
1725
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1726
-                if ($registration instanceof EE_Registration) {
1727
-                    $registration->set_status($status);
1728
-                    $result = $registration->save();
1729
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1730
-                    $success = $result !== false ? $success : false;
1731
-                }
1732
-            }
1733
-        }
1734
-        //reset _req_data['_REG_ID'] for any potential future messages notifications
1735
-        $this->_req_data['_REG_ID'] = $REG_IDs;
1736
-        //return $success and processed registrations
1737
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * Common logic for setting up success message and redirecting to appropriate route
1743
-     *
1744
-     * @param  string $STS_ID status id for the registration changed to
1745
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1746
-     * @return void
1747
-     */
1748
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1749
-    {
1750
-        $result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1751
-            : array('success' => false);
1752
-        $success = isset($result['success']) && $result['success'];
1753
-        //setup success message
1754
-        if ($success) {
1755
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1756
-                $msg = sprintf(esc_html__('Registration status has been set to %s', 'event_espresso'),
1757
-                    EEH_Template::pretty_status($STS_ID, false, 'lower'));
1758
-            } else {
1759
-                $msg = sprintf(esc_html__('Registrations have been set to %s.', 'event_espresso'),
1760
-                    EEH_Template::pretty_status($STS_ID, false, 'lower'));
1761
-            }
1762
-            EE_Error::add_success($msg);
1763
-        } else {
1764
-            EE_Error::add_error(
1765
-                esc_html__(
1766
-                    'Something went wrong, and the status was not changed',
1767
-                    'event_espresso'
1768
-                ), __FILE__, __LINE__, __FUNCTION__
1769
-            );
1770
-        }
1771
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1772
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1773
-        } else {
1774
-            $route = array('action' => 'default');
1775
-        }
1776
-        //unset nonces
1777
-        foreach ($this->_req_data as $ref => $value) {
1778
-            if (strpos($ref, 'nonce') !== false) {
1779
-                unset($this->_req_data[$ref]);
1780
-                continue;
1781
-            }
1782
-            $value                 = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
1783
-            $this->_req_data[$ref] = $value;
1784
-        }
1785
-        //merge request vars so that the reloaded list table contains any existing filter query params
1786
-        $route = array_merge($this->_req_data, $route);
1787
-        $this->_redirect_after_action($success, '', '', $route, true);
1788
-    }
1789
-
1790
-
1791
-    /**
1792
-     * incoming reg status change from reg details page.
1793
-     *
1794
-     * @return void
1795
-     */
1796
-    protected function _change_reg_status()
1797
-    {
1798
-        $this->_req_data['return'] = 'view_registration';
1799
-        //set notify based on whether the send notifications toggle is set or not
1800
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1801
-        //$notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
1802
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
1803
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
1804
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
1805
-            case EEM_Registration::status_id_approved :
1806
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence') :
1807
-                $this->approve_registration($notify);
1808
-                break;
1809
-            case EEM_Registration::status_id_pending_payment :
1810
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence') :
1811
-                $this->pending_registration($notify);
1812
-                break;
1813
-            case EEM_Registration::status_id_not_approved :
1814
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence') :
1815
-                $this->not_approve_registration($notify);
1816
-                break;
1817
-            case EEM_Registration::status_id_declined :
1818
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence') :
1819
-                $this->decline_registration($notify);
1820
-                break;
1821
-            case EEM_Registration::status_id_cancelled :
1822
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence') :
1823
-                $this->cancel_registration($notify);
1824
-                break;
1825
-            case EEM_Registration::status_id_wait_list :
1826
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence') :
1827
-                $this->wait_list_registration($notify);
1828
-                break;
1829
-            case EEM_Registration::status_id_incomplete :
1830
-            default :
1831
-                $result['success'] = false;
1832
-                unset($this->_req_data['return']);
1833
-                $this->_reg_status_change_return('', false);
1834
-                break;
1835
-        }
1836
-    }
1837
-
1838
-
1839
-    /**
1840
-     * approve_registration
1841
-     *
1842
-     * @access protected
1843
-     * @param bool $notify whether or not to notify the registrant about their approval.
1844
-     * @return void
1845
-     */
1846
-    protected function approve_registration($notify = false)
1847
-    {
1848
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1849
-    }
1850
-
1851
-
1852
-    /**
1853
-     *        decline_registration
1854
-     *
1855
-     * @access protected
1856
-     * @param bool $notify whether or not to notify the registrant about their status change.
1857
-     * @return void
1858
-     */
1859
-    protected function decline_registration($notify = false)
1860
-    {
1861
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1862
-    }
1863
-
1864
-
1865
-    /**
1866
-     *        cancel_registration
1867
-     *
1868
-     * @access protected
1869
-     * @param bool $notify whether or not to notify the registrant about their status change.
1870
-     * @return void
1871
-     */
1872
-    protected function cancel_registration($notify = false)
1873
-    {
1874
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1875
-    }
1876
-
1877
-
1878
-    /**
1879
-     *        not_approve_registration
1880
-     *
1881
-     * @access protected
1882
-     * @param bool $notify whether or not to notify the registrant about their status change.
1883
-     * @return void
1884
-     */
1885
-    protected function not_approve_registration($notify = false)
1886
-    {
1887
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1888
-    }
1889
-
1890
-
1891
-    /**
1892
-     *        decline_registration
1893
-     *
1894
-     * @access protected
1895
-     * @param bool $notify whether or not to notify the registrant about their status change.
1896
-     * @return void
1897
-     */
1898
-    protected function pending_registration($notify = false)
1899
-    {
1900
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1901
-    }
1902
-
1903
-
1904
-    /**
1905
-     * waitlist_registration
1906
-     *
1907
-     * @access protected
1908
-     * @param bool $notify whether or not to notify the registrant about their status change.
1909
-     * @return void
1910
-     */
1911
-    protected function wait_list_registration($notify = false)
1912
-    {
1913
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1914
-    }
1915
-
1916
-
1917
-    /**
1918
-     *        generates HTML for the Registration main meta box
1919
-     *
1920
-     * @access public
1921
-     * @return void
1922
-     * @throws DomainException
1923
-     * @throws EE_Error
1924
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1925
-     */
1926
-    public function _reg_details_meta_box()
1927
-    {
1928
-        EEH_Autoloader::register_line_item_display_autoloaders();
1929
-        EEH_Autoloader::register_line_item_filter_autoloaders();
1930
-        EE_Registry::instance()->load_helper('Line_Item');
1931
-        $transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
1932
-            : EE_Transaction::new_instance();
1933
-        $this->_session = $transaction->session_data();
1934
-        $filters        = new EE_Line_Item_Filter_Collection();
1935
-        //$filters->add( new EE_Non_Zero_Line_Item_Filter() );
1936
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
1937
-        $line_item_filter_processor              = new EE_Line_Item_Filter_Processor($filters,
1938
-            $transaction->total_line_item());
1939
-        $filtered_line_item_tree                 = $line_item_filter_processor->process();
1940
-        $line_item_display                       = new EE_Line_Item_Display('reg_admin_table',
1941
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy');
1942
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
1943
-            $filtered_line_item_tree,
1944
-            array('EE_Registration' => $this->_registration)
1945
-        );
1946
-        $attendee                                = $this->_registration->attendee();
1947
-        if (EE_Registry::instance()->CAP->current_user_can(
1948
-            'ee_read_transaction',
1949
-            'espresso_transactions_view_transaction'
1950
-        )) {
1951
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
1952
-                EE_Admin_Page::add_query_args_and_nonce(
1953
-                    array(
1954
-                        'action' => 'view_transaction',
1955
-                        'TXN_ID' => $transaction->ID(),
1956
-                    ),
1957
-                    TXN_ADMIN_URL
1958
-                ),
1959
-                esc_html__(' View Transaction', 'event_espresso'),
1960
-                'button secondary-button right',
1961
-                'dashicons dashicons-cart'
1962
-            );
1963
-        } else {
1964
-            $this->_template_args['view_transaction_button'] = '';
1965
-        }
1966
-        if ($attendee instanceof EE_Attendee
1967
-            && EE_Registry::instance()->CAP->current_user_can(
1968
-                'ee_send_message',
1969
-                'espresso_registrations_resend_registration'
1970
-            )
1971
-        ) {
1972
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
1973
-                EE_Admin_Page::add_query_args_and_nonce(
1974
-                    array(
1975
-                        'action'      => 'resend_registration',
1976
-                        '_REG_ID'     => $this->_registration->ID(),
1977
-                        'redirect_to' => 'view_registration',
1978
-                    ),
1979
-                    REG_ADMIN_URL
1980
-                ),
1981
-                esc_html__(' Resend Registration', 'event_espresso'),
1982
-                'button secondary-button right',
1983
-                'dashicons dashicons-email-alt'
1984
-            );
1985
-        } else {
1986
-            $this->_template_args['resend_registration_button'] = '';
1987
-        }
1988
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1989
-        $payment                               = $transaction->get_first_related('Payment');
1990
-        $payment                               = ! $payment instanceof EE_Payment
1991
-            ? EE_Payment::new_instance()
1992
-            : $payment;
1993
-        $payment_method                        = $payment->get_first_related('Payment_Method');
1994
-        $payment_method                        = ! $payment_method instanceof EE_Payment_Method
1995
-            ? EE_Payment_Method::new_instance()
1996
-            : $payment_method;
1997
-        $reg_details                           = array(
1998
-            'payment_method'       => $payment_method->name(),
1999
-            'response_msg'         => $payment->gateway_response(),
2000
-            'registration_id'      => $this->_registration->get('REG_code'),
2001
-            'registration_session' => $this->_registration->session_ID(),
2002
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2003
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2004
-        );
2005
-        if (isset($reg_details['registration_id'])) {
2006
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2007
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2008
-                'Registration ID',
2009
-                'event_espresso'
2010
-            );
2011
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2012
-        }
2013
-        if (isset($reg_details['payment_method'])) {
2014
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2015
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2016
-                'Most Recent Payment Method',
2017
-                'event_espresso'
2018
-            );
2019
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2020
-            $this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2021
-            $this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2022
-                'Payment method response',
2023
-                'event_espresso'
2024
-            );
2025
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2026
-        }
2027
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2028
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2029
-            'Registration Session',
2030
-            'event_espresso'
2031
-        );
2032
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2033
-        $this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2034
-        $this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2035
-            'Registration placed from IP',
2036
-            'event_espresso'
2037
-        );
2038
-        $this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2039
-        $this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2040
-        $this->_template_args['reg_details']['user_agent']['label']           = esc_html__('Registrant User Agent',
2041
-            'event_espresso');
2042
-        $this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2043
-        $this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2044
-            array(
2045
-                'action'   => 'default',
2046
-                'event_id' => $this->_registration->event_ID(),
2047
-            ),
2048
-            REG_ADMIN_URL
2049
-        );
2050
-        $this->_template_args['REG_ID']                                       = $this->_registration->ID();
2051
-        $this->_template_args['event_id']                                     = $this->_registration->event_ID();
2052
-        $template_path                                                        =
2053
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2054
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2055
-    }
2056
-
2057
-
2058
-    /**
2059
-     * generates HTML for the Registration Questions meta box.
2060
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2061
-     * otherwise uses new forms system
2062
-     *
2063
-     * @access public
2064
-     * @return void
2065
-     * @throws DomainException
2066
-     * @throws EE_Error
2067
-     */
2068
-    public function _reg_questions_meta_box()
2069
-    {
2070
-        //allow someone to override this method entirely
2071
-        if (apply_filters('FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default', true, $this,
2072
-            $this->_registration)) {
2073
-            $form                                              = $this->_get_reg_custom_questions_form(
2074
-                $this->_registration->ID()
2075
-            );
2076
-            $this->_template_args['att_questions']             = count($form->subforms()) > 0
2077
-                ? $form->get_html_and_js()
2078
-                : '';
2079
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2080
-            $this->_template_args['REG_ID']                    = $this->_registration->ID();
2081
-            $template_path                                     =
2082
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2083
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2084
-        }
2085
-    }
2086
-
2087
-
2088
-    /**
2089
-     * form_before_question_group
2090
-     *
2091
-     * @deprecated    as of 4.8.32.rc.000
2092
-     * @access        public
2093
-     * @param        string $output
2094
-     * @return        string
2095
-     */
2096
-    public function form_before_question_group($output)
2097
-    {
2098
-        EE_Error::doing_it_wrong(
2099
-            __CLASS__ . '::' . __FUNCTION__,
2100
-            esc_html__(
2101
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2102
-                'event_espresso'
2103
-            ),
2104
-            '4.8.32.rc.000'
2105
-        );
2106
-        return '
1163
+		if (! empty($registration_status)) {
1164
+			$where['STS_ID'] = $registration_status;
1165
+		} else {
1166
+			//make sure we exclude incomplete registrations, but only if not trashed.
1167
+			if ($view === 'trash') {
1168
+				$where['REG_deleted'] = true;
1169
+			} elseif ($view === 'incomplete') {
1170
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1171
+			} else {
1172
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1173
+			}
1174
+		}
1175
+		return $where;
1176
+	}
1177
+
1178
+
1179
+	/**
1180
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1181
+	 *
1182
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1183
+	 * @return array
1184
+	 * @throws EE_Error
1185
+	 */
1186
+	protected function _add_date_to_where_conditions(array $request)
1187
+	{
1188
+		$where = array();
1189
+		$view = EEH_Array::is_set($request, 'status', '');
1190
+		$month_range             = ! empty($request['month_range'])
1191
+			? sanitize_text_field($request['month_range'])
1192
+			: '';
1193
+		$retrieve_for_today      = $view === 'today';
1194
+		$retrieve_for_this_month = $view === 'month';
1195
+
1196
+		if ($retrieve_for_today) {
1197
+			$now               = date('Y-m-d', current_time('timestamp'));
1198
+			$where['REG_date'] = array(
1199
+				'BETWEEN',
1200
+				array(
1201
+					EEM_Registration::instance()->convert_datetime_for_query(
1202
+						'REG_date',
1203
+						$now . ' 00:00:00',
1204
+						'Y-m-d H:i:s'
1205
+					),
1206
+					EEM_Registration::instance()->convert_datetime_for_query(
1207
+						'REG_date',
1208
+						$now . ' 23:59:59',
1209
+						'Y-m-d H:i:s'
1210
+					),
1211
+				),
1212
+			);
1213
+		} elseif ($retrieve_for_this_month) {
1214
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1215
+			$days_this_month        = date('t', current_time('timestamp'));
1216
+			$where['REG_date']      = array(
1217
+				'BETWEEN',
1218
+				array(
1219
+					EEM_Registration::instance()->convert_datetime_for_query(
1220
+						'REG_date',
1221
+						$current_year_and_month . '-01 00:00:00',
1222
+						'Y-m-d H:i:s'
1223
+					),
1224
+					EEM_Registration::instance()->convert_datetime_for_query(
1225
+						'REG_date',
1226
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1227
+						'Y-m-d H:i:s'
1228
+					),
1229
+				),
1230
+			);
1231
+		} elseif ($month_range) {
1232
+			$pieces          = explode(' ', $month_range, 3);
1233
+			$month_requested = ! empty($pieces[0])
1234
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1235
+				: '';
1236
+			$year_requested  = ! empty($pieces[1])
1237
+				? $pieces[1]
1238
+				: '';
1239
+			//if there is not a month or year then we can't go further
1240
+			if ($month_requested && $year_requested) {
1241
+				$days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1242
+				$where['REG_date'] = array(
1243
+					'BETWEEN',
1244
+					array(
1245
+						EEM_Registration::instance()->convert_datetime_for_query(
1246
+							'REG_date',
1247
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1248
+							'Y-m-d H:i:s'
1249
+						),
1250
+						EEM_Registration::instance()->convert_datetime_for_query(
1251
+							'REG_date',
1252
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1253
+							'Y-m-d H:i:s'
1254
+						),
1255
+					),
1256
+				);
1257
+			}
1258
+		}
1259
+		return $where;
1260
+	}
1261
+
1262
+
1263
+	/**
1264
+	 * Adds any provided search restraints to the where conditions for the registrations query
1265
+	 *
1266
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1267
+	 * @return array
1268
+	 */
1269
+	protected function _add_search_to_where_conditions(array $request)
1270
+	{
1271
+		$where = array();
1272
+		if (! empty($request['s'])) {
1273
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1274
+			$where['OR*search_conditions'] = array(
1275
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1276
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1277
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1278
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1279
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1280
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1281
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1282
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1283
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1284
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1285
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1286
+				'REG_final_price'                         => array('LIKE', $search_string),
1287
+				'REG_code'                                => array('LIKE', $search_string),
1288
+				'REG_count'                               => array('LIKE', $search_string),
1289
+				'REG_group_size'                          => array('LIKE', $search_string),
1290
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1291
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1292
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1293
+			);
1294
+		}
1295
+		return $where;
1296
+	}
1297
+
1298
+
1299
+	/**
1300
+	 * Sets up the where conditions for the registrations query.
1301
+	 *
1302
+	 * @param array $request
1303
+	 * @return array
1304
+	 * @throws EE_Error
1305
+	 */
1306
+	protected function _get_where_conditions_for_registrations_query($request)
1307
+	{
1308
+		return apply_filters(
1309
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1310
+			array_merge(
1311
+				$this->_add_event_id_to_where_conditions($request),
1312
+				$this->_add_category_id_to_where_conditions($request),
1313
+				$this->_add_datetime_id_to_where_conditions($request),
1314
+				$this->_add_registration_status_to_where_conditions($request),
1315
+				$this->_add_date_to_where_conditions($request),
1316
+				$this->_add_search_to_where_conditions($request)
1317
+			),
1318
+			$request
1319
+		);
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * Sets up the orderby for the registrations query.
1325
+	 *
1326
+	 * @return array
1327
+	 */
1328
+	protected function _get_orderby_for_registrations_query()
1329
+	{
1330
+		$orderby_field = ! empty($this->_req_data['orderby'])
1331
+			? sanitize_text_field($this->_req_data['orderby'])
1332
+			: '';
1333
+		switch ($orderby_field) {
1334
+			case '_REG_ID':
1335
+				$orderby_field = 'REG_ID';
1336
+				break;
1337
+			case '_Reg_status':
1338
+				$orderby_field = 'STS_ID';
1339
+				break;
1340
+			case 'ATT_fname':
1341
+				$orderby_field = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1342
+				break;
1343
+			case 'ATT_lname':
1344
+				$orderby_field = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1345
+				break;
1346
+			case 'event_name':
1347
+				$orderby_field = 'Event.EVT_name';
1348
+				break;
1349
+			case 'DTT_EVT_start':
1350
+				$orderby_field = 'Event.Datetime.DTT_EVT_start';
1351
+				break;
1352
+			default: //'REG_date'
1353
+				$orderby_field = 'REG_date';
1354
+		}
1355
+
1356
+		//order
1357
+		$order = ! empty($this->_req_data['order'])
1358
+			? sanitize_text_field($this->_req_data['order'])
1359
+			: 'DESC';
1360
+
1361
+		//mutate orderby_field
1362
+		$orderby_field = array_combine(
1363
+			(array) $orderby_field,
1364
+			array_fill(0, count($orderby_field), $order)
1365
+		);
1366
+		return array('order_by' => $orderby_field);
1367
+	}
1368
+
1369
+
1370
+	/**
1371
+	 * Sets up the limit for the registrations query.
1372
+	 *
1373
+	 * @param $per_page
1374
+	 * @return array
1375
+	 */
1376
+	protected function _get_limit($per_page)
1377
+	{
1378
+		$current_page = ! empty($this->_req_data['paged'])
1379
+			? absint($this->_req_data['paged'])
1380
+			: 1;
1381
+		$per_page     = ! empty($this->_req_data['perpage'])
1382
+			? $this->_req_data['perpage']
1383
+			: $per_page;
1384
+
1385
+		//-1 means return all results so get out if that's set.
1386
+		if ((int)$per_page === -1) {
1387
+			return array();
1388
+		}
1389
+		$per_page = absint($per_page);
1390
+		$offset   = ($current_page - 1) * $per_page;
1391
+		return array('limit' => array($offset, $per_page));
1392
+	}
1393
+
1394
+
1395
+	public function get_registration_status_array()
1396
+	{
1397
+		return self::$_reg_status;
1398
+	}
1399
+
1400
+
1401
+
1402
+
1403
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1404
+	/**
1405
+	 *        generates HTML for the View Registration Details Admin page
1406
+	 *
1407
+	 * @access protected
1408
+	 * @return void
1409
+	 * @throws DomainException
1410
+	 * @throws EE_Error
1411
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1412
+	 */
1413
+	protected function _registration_details()
1414
+	{
1415
+		$this->_template_args = array();
1416
+		$this->_set_registration_object();
1417
+		if (is_object($this->_registration)) {
1418
+			$transaction                                   = $this->_registration->transaction()
1419
+				? $this->_registration->transaction()
1420
+				: EE_Transaction::new_instance();
1421
+			$this->_session                                = $transaction->session_data();
1422
+			$event_id                                      = $this->_registration->event_ID();
1423
+			$this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1424
+			$this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1425
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1426
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1427
+			$this->_template_args['grand_total']           = $transaction->total();
1428
+			$this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1429
+			// link back to overview
1430
+			$this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1431
+			$this->_template_args['registration']                = $this->_registration;
1432
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1433
+				array(
1434
+					'action'   => 'default',
1435
+					'event_id' => $event_id,
1436
+				),
1437
+				REG_ADMIN_URL
1438
+			);
1439
+			$this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1440
+				array(
1441
+					'action' => 'default',
1442
+					'EVT_ID' => $event_id,
1443
+					'page'   => 'espresso_transactions',
1444
+				),
1445
+				admin_url('admin.php')
1446
+			);
1447
+			$this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1448
+				array(
1449
+					'page'   => 'espresso_events',
1450
+					'action' => 'edit',
1451
+					'post'   => $event_id,
1452
+				),
1453
+				admin_url('admin.php')
1454
+			);
1455
+			//next and previous links
1456
+			$next_reg                                      = $this->_registration->next(
1457
+				null,
1458
+				array(),
1459
+				'REG_ID'
1460
+			);
1461
+			$this->_template_args['next_registration']     = $next_reg
1462
+				? $this->_next_link(
1463
+					EE_Admin_Page::add_query_args_and_nonce(
1464
+						array(
1465
+							'action'  => 'view_registration',
1466
+							'_REG_ID' => $next_reg['REG_ID'],
1467
+						),
1468
+						REG_ADMIN_URL
1469
+					),
1470
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1471
+				)
1472
+				: '';
1473
+			$previous_reg                                  = $this->_registration->previous(
1474
+				null,
1475
+				array(),
1476
+				'REG_ID'
1477
+			);
1478
+			$this->_template_args['previous_registration'] = $previous_reg
1479
+				? $this->_previous_link(
1480
+					EE_Admin_Page::add_query_args_and_nonce(
1481
+						array(
1482
+							'action'  => 'view_registration',
1483
+							'_REG_ID' => $previous_reg['REG_ID'],
1484
+						),
1485
+						REG_ADMIN_URL
1486
+					),
1487
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1488
+				)
1489
+				: '';
1490
+			// grab header
1491
+			$template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1492
+			$this->_template_args['REG_ID']            = $this->_registration->ID();
1493
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1494
+				$template_path,
1495
+				$this->_template_args,
1496
+				true
1497
+			);
1498
+		} else {
1499
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1500
+		}
1501
+		// the details template wrapper
1502
+		$this->display_admin_page_with_sidebar();
1503
+	}
1504
+
1505
+
1506
+	protected function _registration_details_metaboxes()
1507
+	{
1508
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1509
+		$this->_set_registration_object();
1510
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1511
+		add_meta_box('edit-reg-status-mbox', esc_html__('Registration Status', 'event_espresso'),
1512
+			array($this, 'set_reg_status_buttons_metabox'), $this->wp_page_slug, 'normal', 'high');
1513
+		add_meta_box('edit-reg-details-mbox', esc_html__('Registration Details', 'event_espresso'),
1514
+			array($this, '_reg_details_meta_box'), $this->wp_page_slug, 'normal', 'high');
1515
+		if ($attendee instanceof EE_Attendee
1516
+			&& EE_Registry::instance()->CAP->current_user_can(
1517
+				'ee_edit_registration',
1518
+				'edit-reg-questions-mbox'
1519
+			)
1520
+		) {
1521
+			add_meta_box(
1522
+				'edit-reg-questions-mbox',
1523
+				esc_html__('Registration Form Answers', 'event_espresso'),
1524
+				array($this, '_reg_questions_meta_box'),
1525
+				$this->wp_page_slug,
1526
+				'normal',
1527
+				'high'
1528
+			);
1529
+		}
1530
+		add_meta_box(
1531
+			'edit-reg-registrant-mbox',
1532
+			esc_html__('Contact Details', 'event_espresso'),
1533
+			array($this, '_reg_registrant_side_meta_box'),
1534
+			$this->wp_page_slug,
1535
+			'side',
1536
+			'high'
1537
+		);
1538
+		if ($this->_registration->group_size() > 1) {
1539
+			add_meta_box(
1540
+				'edit-reg-attendees-mbox',
1541
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1542
+				array($this, '_reg_attendees_meta_box'),
1543
+				$this->wp_page_slug,
1544
+				'normal',
1545
+				'high'
1546
+			);
1547
+		}
1548
+	}
1549
+
1550
+
1551
+	/**
1552
+	 * set_reg_status_buttons_metabox
1553
+	 *
1554
+	 * @access protected
1555
+	 * @return string
1556
+	 * @throws \EE_Error
1557
+	 */
1558
+	public function set_reg_status_buttons_metabox()
1559
+	{
1560
+		$this->_set_registration_object();
1561
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1562
+		echo $change_reg_status_form->form_open(
1563
+			self::add_query_args_and_nonce(
1564
+				array(
1565
+					'action' => 'change_reg_status',
1566
+				),
1567
+				REG_ADMIN_URL
1568
+			)
1569
+		);
1570
+		echo $change_reg_status_form->get_html();
1571
+		echo $change_reg_status_form->form_close();
1572
+	}
1573
+
1574
+
1575
+
1576
+	/**
1577
+	 * @return EE_Form_Section_Proper
1578
+	 * @throws EE_Error
1579
+	 */
1580
+	protected function _generate_reg_status_change_form()
1581
+	{
1582
+		return new EE_Form_Section_Proper(array(
1583
+			'name'            => 'reg_status_change_form',
1584
+			'html_id'         => 'reg-status-change-form',
1585
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1586
+			'subsections'     => array(
1587
+				'return'             => new EE_Hidden_Input(array(
1588
+					'name'    => 'return',
1589
+					'default' => 'view_registration',
1590
+				)),
1591
+				'REG_ID'             => new EE_Hidden_Input(array(
1592
+					'name'    => 'REG_ID',
1593
+					'default' => $this->_registration->ID(),
1594
+				)),
1595
+				'current_status'     => new EE_Form_Section_HTML(
1596
+					EEH_HTML::tr(
1597
+						EEH_HTML::th(
1598
+							EEH_HTML::label(
1599
+								EEH_HTML::strong(esc_html__('Current Registration Status', 'event_espresso')
1600
+								)
1601
+							)
1602
+						)
1603
+						. EEH_HTML::td(
1604
+							EEH_HTML::strong(
1605
+								$this->_registration->pretty_status(),
1606
+								'',
1607
+								'status-' . $this->_registration->status_ID(),
1608
+								'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1609
+							)
1610
+						)
1611
+					)
1612
+				),
1613
+				'reg_status'         => new EE_Select_Input(
1614
+					$this->_get_reg_statuses(),
1615
+					array(
1616
+						'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1617
+						'default'         => $this->_registration->status_ID(),
1618
+					)
1619
+				),
1620
+				'send_notifications' => new EE_Yes_No_Input(
1621
+					array(
1622
+						'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1623
+						'default'         => false,
1624
+						'html_help_text'  => esc_html__(
1625
+							'If set to "Yes", then the related messages will be sent to the registrant.',
1626
+							'event_espresso'
1627
+						),
1628
+					)
1629
+				),
1630
+				'submit'             => new EE_Submit_Input(
1631
+					array(
1632
+						'html_class'      => 'button-primary',
1633
+						'html_label_text' => '&nbsp;',
1634
+						'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1635
+					)
1636
+				),
1637
+			),
1638
+		));
1639
+	}
1640
+
1641
+
1642
+	/**
1643
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1644
+	 *
1645
+	 * @return array
1646
+	 * @throws EE_Error
1647
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1648
+	 */
1649
+	protected function _get_reg_statuses()
1650
+	{
1651
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1652
+		unset ($reg_status_array[EEM_Registration::status_id_incomplete]);
1653
+		// get current reg status
1654
+		$current_status = $this->_registration->status_ID();
1655
+		// is registration for free event? This will determine whether to display the pending payment option
1656
+		if (
1657
+			$current_status !== EEM_Registration::status_id_pending_payment
1658
+			&& $this->_registration->transaction()->is_free()
1659
+		) {
1660
+			unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1661
+		}
1662
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1663
+	}
1664
+
1665
+
1666
+
1667
+	/**
1668
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1669
+	 *
1670
+	 * @param bool $status REG status given for changing registrations to.
1671
+	 * @param bool $notify Whether to send messages notifications or not.
1672
+	 * @return array  (array with reg_id(s) updated and whether update was successful.
1673
+	 * @throws \EE_Error
1674
+	 */
1675
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1676
+	{
1677
+		if (isset($this->_req_data['reg_status_change_form'])) {
1678
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1679
+				? (array)$this->_req_data['reg_status_change_form']['REG_ID'] : array();
1680
+		} else {
1681
+			$REG_IDs = isset($this->_req_data['_REG_ID']) ? (array)$this->_req_data['_REG_ID'] : array();
1682
+		}
1683
+		$success = $this->_set_registration_status($REG_IDs, $status);
1684
+		//notify?
1685
+		if ($success
1686
+			&& $notify
1687
+			&& EE_Registry::instance()->CAP->current_user_can(
1688
+				'ee_send_message',
1689
+				'espresso_registrations_resend_registration'
1690
+			)
1691
+		) {
1692
+			$this->_process_resend_registration();
1693
+		}
1694
+		return $success;
1695
+	}
1696
+
1697
+
1698
+
1699
+	/**
1700
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1701
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1702
+	 *
1703
+	 * @param array $REG_IDs
1704
+	 * @param bool  $status
1705
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1706
+	 * @throws \RuntimeException
1707
+	 * @throws \EE_Error
1708
+	 *               the array of updated registrations).
1709
+	 * @throws EE_Error
1710
+	 * @throws RuntimeException
1711
+	 */
1712
+	protected function _set_registration_status($REG_IDs = array(), $status = false)
1713
+	{
1714
+		$success = false;
1715
+		// typecast $REG_IDs
1716
+		$REG_IDs = (array)$REG_IDs;
1717
+		if ( ! empty($REG_IDs)) {
1718
+			$success = true;
1719
+			// set default status if none is passed
1720
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1721
+			// sanitize $REG_IDs
1722
+			$REG_IDs = array_filter($REG_IDs, 'absint');
1723
+			//loop through REG_ID's and change status
1724
+			foreach ($REG_IDs as $REG_ID) {
1725
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1726
+				if ($registration instanceof EE_Registration) {
1727
+					$registration->set_status($status);
1728
+					$result = $registration->save();
1729
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1730
+					$success = $result !== false ? $success : false;
1731
+				}
1732
+			}
1733
+		}
1734
+		//reset _req_data['_REG_ID'] for any potential future messages notifications
1735
+		$this->_req_data['_REG_ID'] = $REG_IDs;
1736
+		//return $success and processed registrations
1737
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * Common logic for setting up success message and redirecting to appropriate route
1743
+	 *
1744
+	 * @param  string $STS_ID status id for the registration changed to
1745
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1746
+	 * @return void
1747
+	 */
1748
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1749
+	{
1750
+		$result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1751
+			: array('success' => false);
1752
+		$success = isset($result['success']) && $result['success'];
1753
+		//setup success message
1754
+		if ($success) {
1755
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1756
+				$msg = sprintf(esc_html__('Registration status has been set to %s', 'event_espresso'),
1757
+					EEH_Template::pretty_status($STS_ID, false, 'lower'));
1758
+			} else {
1759
+				$msg = sprintf(esc_html__('Registrations have been set to %s.', 'event_espresso'),
1760
+					EEH_Template::pretty_status($STS_ID, false, 'lower'));
1761
+			}
1762
+			EE_Error::add_success($msg);
1763
+		} else {
1764
+			EE_Error::add_error(
1765
+				esc_html__(
1766
+					'Something went wrong, and the status was not changed',
1767
+					'event_espresso'
1768
+				), __FILE__, __LINE__, __FUNCTION__
1769
+			);
1770
+		}
1771
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1772
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1773
+		} else {
1774
+			$route = array('action' => 'default');
1775
+		}
1776
+		//unset nonces
1777
+		foreach ($this->_req_data as $ref => $value) {
1778
+			if (strpos($ref, 'nonce') !== false) {
1779
+				unset($this->_req_data[$ref]);
1780
+				continue;
1781
+			}
1782
+			$value                 = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
1783
+			$this->_req_data[$ref] = $value;
1784
+		}
1785
+		//merge request vars so that the reloaded list table contains any existing filter query params
1786
+		$route = array_merge($this->_req_data, $route);
1787
+		$this->_redirect_after_action($success, '', '', $route, true);
1788
+	}
1789
+
1790
+
1791
+	/**
1792
+	 * incoming reg status change from reg details page.
1793
+	 *
1794
+	 * @return void
1795
+	 */
1796
+	protected function _change_reg_status()
1797
+	{
1798
+		$this->_req_data['return'] = 'view_registration';
1799
+		//set notify based on whether the send notifications toggle is set or not
1800
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1801
+		//$notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
1802
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
1803
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
1804
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
1805
+			case EEM_Registration::status_id_approved :
1806
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence') :
1807
+				$this->approve_registration($notify);
1808
+				break;
1809
+			case EEM_Registration::status_id_pending_payment :
1810
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence') :
1811
+				$this->pending_registration($notify);
1812
+				break;
1813
+			case EEM_Registration::status_id_not_approved :
1814
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence') :
1815
+				$this->not_approve_registration($notify);
1816
+				break;
1817
+			case EEM_Registration::status_id_declined :
1818
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence') :
1819
+				$this->decline_registration($notify);
1820
+				break;
1821
+			case EEM_Registration::status_id_cancelled :
1822
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence') :
1823
+				$this->cancel_registration($notify);
1824
+				break;
1825
+			case EEM_Registration::status_id_wait_list :
1826
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence') :
1827
+				$this->wait_list_registration($notify);
1828
+				break;
1829
+			case EEM_Registration::status_id_incomplete :
1830
+			default :
1831
+				$result['success'] = false;
1832
+				unset($this->_req_data['return']);
1833
+				$this->_reg_status_change_return('', false);
1834
+				break;
1835
+		}
1836
+	}
1837
+
1838
+
1839
+	/**
1840
+	 * approve_registration
1841
+	 *
1842
+	 * @access protected
1843
+	 * @param bool $notify whether or not to notify the registrant about their approval.
1844
+	 * @return void
1845
+	 */
1846
+	protected function approve_registration($notify = false)
1847
+	{
1848
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1849
+	}
1850
+
1851
+
1852
+	/**
1853
+	 *        decline_registration
1854
+	 *
1855
+	 * @access protected
1856
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1857
+	 * @return void
1858
+	 */
1859
+	protected function decline_registration($notify = false)
1860
+	{
1861
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1862
+	}
1863
+
1864
+
1865
+	/**
1866
+	 *        cancel_registration
1867
+	 *
1868
+	 * @access protected
1869
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1870
+	 * @return void
1871
+	 */
1872
+	protected function cancel_registration($notify = false)
1873
+	{
1874
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1875
+	}
1876
+
1877
+
1878
+	/**
1879
+	 *        not_approve_registration
1880
+	 *
1881
+	 * @access protected
1882
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1883
+	 * @return void
1884
+	 */
1885
+	protected function not_approve_registration($notify = false)
1886
+	{
1887
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1888
+	}
1889
+
1890
+
1891
+	/**
1892
+	 *        decline_registration
1893
+	 *
1894
+	 * @access protected
1895
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1896
+	 * @return void
1897
+	 */
1898
+	protected function pending_registration($notify = false)
1899
+	{
1900
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1901
+	}
1902
+
1903
+
1904
+	/**
1905
+	 * waitlist_registration
1906
+	 *
1907
+	 * @access protected
1908
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1909
+	 * @return void
1910
+	 */
1911
+	protected function wait_list_registration($notify = false)
1912
+	{
1913
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1914
+	}
1915
+
1916
+
1917
+	/**
1918
+	 *        generates HTML for the Registration main meta box
1919
+	 *
1920
+	 * @access public
1921
+	 * @return void
1922
+	 * @throws DomainException
1923
+	 * @throws EE_Error
1924
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1925
+	 */
1926
+	public function _reg_details_meta_box()
1927
+	{
1928
+		EEH_Autoloader::register_line_item_display_autoloaders();
1929
+		EEH_Autoloader::register_line_item_filter_autoloaders();
1930
+		EE_Registry::instance()->load_helper('Line_Item');
1931
+		$transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
1932
+			: EE_Transaction::new_instance();
1933
+		$this->_session = $transaction->session_data();
1934
+		$filters        = new EE_Line_Item_Filter_Collection();
1935
+		//$filters->add( new EE_Non_Zero_Line_Item_Filter() );
1936
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
1937
+		$line_item_filter_processor              = new EE_Line_Item_Filter_Processor($filters,
1938
+			$transaction->total_line_item());
1939
+		$filtered_line_item_tree                 = $line_item_filter_processor->process();
1940
+		$line_item_display                       = new EE_Line_Item_Display('reg_admin_table',
1941
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy');
1942
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
1943
+			$filtered_line_item_tree,
1944
+			array('EE_Registration' => $this->_registration)
1945
+		);
1946
+		$attendee                                = $this->_registration->attendee();
1947
+		if (EE_Registry::instance()->CAP->current_user_can(
1948
+			'ee_read_transaction',
1949
+			'espresso_transactions_view_transaction'
1950
+		)) {
1951
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
1952
+				EE_Admin_Page::add_query_args_and_nonce(
1953
+					array(
1954
+						'action' => 'view_transaction',
1955
+						'TXN_ID' => $transaction->ID(),
1956
+					),
1957
+					TXN_ADMIN_URL
1958
+				),
1959
+				esc_html__(' View Transaction', 'event_espresso'),
1960
+				'button secondary-button right',
1961
+				'dashicons dashicons-cart'
1962
+			);
1963
+		} else {
1964
+			$this->_template_args['view_transaction_button'] = '';
1965
+		}
1966
+		if ($attendee instanceof EE_Attendee
1967
+			&& EE_Registry::instance()->CAP->current_user_can(
1968
+				'ee_send_message',
1969
+				'espresso_registrations_resend_registration'
1970
+			)
1971
+		) {
1972
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
1973
+				EE_Admin_Page::add_query_args_and_nonce(
1974
+					array(
1975
+						'action'      => 'resend_registration',
1976
+						'_REG_ID'     => $this->_registration->ID(),
1977
+						'redirect_to' => 'view_registration',
1978
+					),
1979
+					REG_ADMIN_URL
1980
+				),
1981
+				esc_html__(' Resend Registration', 'event_espresso'),
1982
+				'button secondary-button right',
1983
+				'dashicons dashicons-email-alt'
1984
+			);
1985
+		} else {
1986
+			$this->_template_args['resend_registration_button'] = '';
1987
+		}
1988
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1989
+		$payment                               = $transaction->get_first_related('Payment');
1990
+		$payment                               = ! $payment instanceof EE_Payment
1991
+			? EE_Payment::new_instance()
1992
+			: $payment;
1993
+		$payment_method                        = $payment->get_first_related('Payment_Method');
1994
+		$payment_method                        = ! $payment_method instanceof EE_Payment_Method
1995
+			? EE_Payment_Method::new_instance()
1996
+			: $payment_method;
1997
+		$reg_details                           = array(
1998
+			'payment_method'       => $payment_method->name(),
1999
+			'response_msg'         => $payment->gateway_response(),
2000
+			'registration_id'      => $this->_registration->get('REG_code'),
2001
+			'registration_session' => $this->_registration->session_ID(),
2002
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2003
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2004
+		);
2005
+		if (isset($reg_details['registration_id'])) {
2006
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2007
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2008
+				'Registration ID',
2009
+				'event_espresso'
2010
+			);
2011
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2012
+		}
2013
+		if (isset($reg_details['payment_method'])) {
2014
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2015
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2016
+				'Most Recent Payment Method',
2017
+				'event_espresso'
2018
+			);
2019
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2020
+			$this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2021
+			$this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2022
+				'Payment method response',
2023
+				'event_espresso'
2024
+			);
2025
+			$this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2026
+		}
2027
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2028
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2029
+			'Registration Session',
2030
+			'event_espresso'
2031
+		);
2032
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2033
+		$this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2034
+		$this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2035
+			'Registration placed from IP',
2036
+			'event_espresso'
2037
+		);
2038
+		$this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2039
+		$this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2040
+		$this->_template_args['reg_details']['user_agent']['label']           = esc_html__('Registrant User Agent',
2041
+			'event_espresso');
2042
+		$this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2043
+		$this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2044
+			array(
2045
+				'action'   => 'default',
2046
+				'event_id' => $this->_registration->event_ID(),
2047
+			),
2048
+			REG_ADMIN_URL
2049
+		);
2050
+		$this->_template_args['REG_ID']                                       = $this->_registration->ID();
2051
+		$this->_template_args['event_id']                                     = $this->_registration->event_ID();
2052
+		$template_path                                                        =
2053
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2054
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2055
+	}
2056
+
2057
+
2058
+	/**
2059
+	 * generates HTML for the Registration Questions meta box.
2060
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2061
+	 * otherwise uses new forms system
2062
+	 *
2063
+	 * @access public
2064
+	 * @return void
2065
+	 * @throws DomainException
2066
+	 * @throws EE_Error
2067
+	 */
2068
+	public function _reg_questions_meta_box()
2069
+	{
2070
+		//allow someone to override this method entirely
2071
+		if (apply_filters('FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default', true, $this,
2072
+			$this->_registration)) {
2073
+			$form                                              = $this->_get_reg_custom_questions_form(
2074
+				$this->_registration->ID()
2075
+			);
2076
+			$this->_template_args['att_questions']             = count($form->subforms()) > 0
2077
+				? $form->get_html_and_js()
2078
+				: '';
2079
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2080
+			$this->_template_args['REG_ID']                    = $this->_registration->ID();
2081
+			$template_path                                     =
2082
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2083
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2084
+		}
2085
+	}
2086
+
2087
+
2088
+	/**
2089
+	 * form_before_question_group
2090
+	 *
2091
+	 * @deprecated    as of 4.8.32.rc.000
2092
+	 * @access        public
2093
+	 * @param        string $output
2094
+	 * @return        string
2095
+	 */
2096
+	public function form_before_question_group($output)
2097
+	{
2098
+		EE_Error::doing_it_wrong(
2099
+			__CLASS__ . '::' . __FUNCTION__,
2100
+			esc_html__(
2101
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2102
+				'event_espresso'
2103
+			),
2104
+			'4.8.32.rc.000'
2105
+		);
2106
+		return '
2107 2107
 	<table class="form-table ee-width-100">
2108 2108
 		<tbody>
2109 2109
 			';
2110
-    }
2111
-
2112
-
2113
-    /**
2114
-     * form_after_question_group
2115
-     *
2116
-     * @deprecated    as of 4.8.32.rc.000
2117
-     * @access        public
2118
-     * @param        string $output
2119
-     * @return        string
2120
-     */
2121
-    public function form_after_question_group($output)
2122
-    {
2123
-        EE_Error::doing_it_wrong(
2124
-            __CLASS__ . '::' . __FUNCTION__,
2125
-            esc_html__(
2126
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2127
-                'event_espresso'
2128
-            ),
2129
-            '4.8.32.rc.000'
2130
-        );
2131
-        return '
2110
+	}
2111
+
2112
+
2113
+	/**
2114
+	 * form_after_question_group
2115
+	 *
2116
+	 * @deprecated    as of 4.8.32.rc.000
2117
+	 * @access        public
2118
+	 * @param        string $output
2119
+	 * @return        string
2120
+	 */
2121
+	public function form_after_question_group($output)
2122
+	{
2123
+		EE_Error::doing_it_wrong(
2124
+			__CLASS__ . '::' . __FUNCTION__,
2125
+			esc_html__(
2126
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2127
+				'event_espresso'
2128
+			),
2129
+			'4.8.32.rc.000'
2130
+		);
2131
+		return '
2132 2132
 			<tr class="hide-if-no-js">
2133 2133
 				<th> </th>
2134 2134
 				<td class="reg-admin-edit-attendee-question-td">
2135 2135
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2136
-               . esc_attr__('click to edit question', 'event_espresso')
2137
-               . '">
2136
+			   . esc_attr__('click to edit question', 'event_espresso')
2137
+			   . '">
2138 2138
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2139
-               . esc_html__('edit the above question group', 'event_espresso')
2140
-               . '</span>
2139
+			   . esc_html__('edit the above question group', 'event_espresso')
2140
+			   . '</span>
2141 2141
 						<div class="dashicons dashicons-edit"></div>
2142 2142
 					</a>
2143 2143
 				</td>
@@ -2145,558 +2145,558 @@  discard block
 block discarded – undo
2145 2145
 		</tbody>
2146 2146
 	</table>
2147 2147
 ';
2148
-    }
2149
-
2150
-
2151
-    /**
2152
-     * form_form_field_label_wrap
2153
-     *
2154
-     * @deprecated    as of 4.8.32.rc.000
2155
-     * @access        public
2156
-     * @param        string $label
2157
-     * @return        string
2158
-     */
2159
-    public function form_form_field_label_wrap($label)
2160
-    {
2161
-        EE_Error::doing_it_wrong(
2162
-            __CLASS__ . '::' . __FUNCTION__,
2163
-            esc_html__(
2164
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2165
-                'event_espresso'
2166
-            ),
2167
-            '4.8.32.rc.000'
2168
-        );
2169
-        return '
2148
+	}
2149
+
2150
+
2151
+	/**
2152
+	 * form_form_field_label_wrap
2153
+	 *
2154
+	 * @deprecated    as of 4.8.32.rc.000
2155
+	 * @access        public
2156
+	 * @param        string $label
2157
+	 * @return        string
2158
+	 */
2159
+	public function form_form_field_label_wrap($label)
2160
+	{
2161
+		EE_Error::doing_it_wrong(
2162
+			__CLASS__ . '::' . __FUNCTION__,
2163
+			esc_html__(
2164
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2165
+				'event_espresso'
2166
+			),
2167
+			'4.8.32.rc.000'
2168
+		);
2169
+		return '
2170 2170
 			<tr>
2171 2171
 				<th>
2172 2172
 					' . $label . '
2173 2173
 				</th>';
2174
-    }
2175
-
2176
-
2177
-    /**
2178
-     * form_form_field_input__wrap
2179
-     *
2180
-     * @deprecated    as of 4.8.32.rc.000
2181
-     * @access        public
2182
-     * @param        string $input
2183
-     * @return        string
2184
-     */
2185
-    public function form_form_field_input__wrap($input)
2186
-    {
2187
-        EE_Error::doing_it_wrong(
2188
-            __CLASS__ . '::' . __FUNCTION__,
2189
-            esc_html__(
2190
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2191
-                'event_espresso'
2192
-            ),
2193
-            '4.8.32.rc.000'
2194
-        );
2195
-        return '
2174
+	}
2175
+
2176
+
2177
+	/**
2178
+	 * form_form_field_input__wrap
2179
+	 *
2180
+	 * @deprecated    as of 4.8.32.rc.000
2181
+	 * @access        public
2182
+	 * @param        string $input
2183
+	 * @return        string
2184
+	 */
2185
+	public function form_form_field_input__wrap($input)
2186
+	{
2187
+		EE_Error::doing_it_wrong(
2188
+			__CLASS__ . '::' . __FUNCTION__,
2189
+			esc_html__(
2190
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2191
+				'event_espresso'
2192
+			),
2193
+			'4.8.32.rc.000'
2194
+		);
2195
+		return '
2196 2196
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2197 2197
 					' . $input . '
2198 2198
 				</td>
2199 2199
 			</tr>';
2200
-    }
2201
-
2202
-
2203
-    /**
2204
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2205
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2206
-     * to display the page
2207
-     *
2208
-     * @access protected
2209
-     * @return void
2210
-     * @throws EE_Error
2211
-     */
2212
-    protected function _update_attendee_registration_form()
2213
-    {
2214
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2215
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2216
-            $REG_ID  = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2217
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2218
-            if ($success) {
2219
-                $what  = esc_html__('Registration Form', 'event_espresso');
2220
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2221
-                    : array('action' => 'default');
2222
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2223
-            }
2224
-        }
2225
-    }
2226
-
2227
-
2228
-    /**
2229
-     * Gets the form for saving registrations custom questions (if done
2230
-     * previously retrieves the cached form object, which may have validation errors in it)
2231
-     *
2232
-     * @param int $REG_ID
2233
-     * @return EE_Registration_Custom_Questions_Form
2234
-     * @throws EE_Error
2235
-     */
2236
-    protected function _get_reg_custom_questions_form($REG_ID)
2237
-    {
2238
-        if ( ! $this->_reg_custom_questions_form) {
2239
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2240
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2241
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2242
-            );
2243
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2244
-        }
2245
-        return $this->_reg_custom_questions_form;
2246
-    }
2247
-
2248
-
2249
-    /**
2250
-     * Saves
2251
-     *
2252
-     * @access private
2253
-     * @param bool $REG_ID
2254
-     * @return bool
2255
-     * @throws EE_Error
2256
-     */
2257
-    private function _save_reg_custom_questions_form($REG_ID = false)
2258
-    {
2259
-        if ( ! $REG_ID) {
2260
-            EE_Error::add_error(
2261
-                esc_html__(
2262
-                    'An error occurred. No registration ID was received.', 'event_espresso'),
2263
-                __FILE__, __FUNCTION__, __LINE__
2264
-            );
2265
-        }
2266
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2267
-        $form->receive_form_submission($this->_req_data);
2268
-        $success = false;
2269
-        if ($form->is_valid()) {
2270
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2271
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2272
-                    $where_conditions    = array(
2273
-                        'QST_ID' => $question_id,
2274
-                        'REG_ID' => $REG_ID,
2275
-                    );
2276
-                    $possibly_new_values = array(
2277
-                        'ANS_value' => $input->normalized_value(),
2278
-                    );
2279
-                    $answer              = EEM_Answer::instance()->get_one(array($where_conditions));
2280
-                    if ($answer instanceof EE_Answer) {
2281
-                        $success = $answer->save($possibly_new_values);
2282
-                    } else {
2283
-                        //insert it then
2284
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2285
-                        $answer      = EE_Answer::new_instance($cols_n_vals);
2286
-                        $success     = $answer->save();
2287
-                    }
2288
-                }
2289
-            }
2290
-        } else {
2291
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2292
-        }
2293
-        return $success;
2294
-    }
2295
-
2296
-
2297
-    /**
2298
-     *        generates HTML for the Registration main meta box
2299
-     *
2300
-     * @access public
2301
-     * @return void
2302
-     * @throws DomainException
2303
-     * @throws EE_Error
2304
-     */
2305
-    public function _reg_attendees_meta_box()
2306
-    {
2307
-        $REG = EEM_Registration::instance();
2308
-        //get all other registrations on this transaction, and cache
2309
-        //the attendees for them so we don't have to run another query using force_join
2310
-        $registrations                           = $REG->get_all(array(
2311
-            array(
2312
-                'TXN_ID' => $this->_registration->transaction_ID(),
2313
-                'REG_ID' => array('!=', $this->_registration->ID()),
2314
-            ),
2315
-            'force_join' => array('Attendee'),
2316
-        ));
2317
-        $this->_template_args['attendees']       = array();
2318
-        $this->_template_args['attendee_notice'] = '';
2319
-        if (empty($registrations)
2320
-            || (is_array($registrations)
2321
-                && ! EEH_Array::get_one_item_from_array($registrations))
2322
-        ) {
2323
-            EE_Error::add_error(
2324
-                esc_html__(
2325
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2326
-                    'event_espresso'
2327
-                ), __FILE__, __FUNCTION__, __LINE__
2328
-            );
2329
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2330
-        } else {
2331
-            $att_nmbr = 1;
2332
-            foreach ($registrations as $registration) {
2333
-                /* @var $registration EE_Registration */
2334
-                $attendee                                                    = $registration->attendee()
2335
-                    ? $registration->attendee()
2336
-                    : EEM_Attendee::instance()
2337
-                                  ->create_default_object();
2338
-                $this->_template_args['attendees'][$att_nmbr]['STS_ID']      = $registration->status_ID();
2339
-                $this->_template_args['attendees'][$att_nmbr]['fname']       = $attendee->fname();
2340
-                $this->_template_args['attendees'][$att_nmbr]['lname']       = $attendee->lname();
2341
-                $this->_template_args['attendees'][$att_nmbr]['email']       = $attendee->email();
2342
-                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2343
-                $this->_template_args['attendees'][$att_nmbr]['address']     = implode(
2344
-                    ', ',
2345
-                    $attendee->full_address_as_array()
2346
-                );
2347
-                $this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2348
-                    array(
2349
-                        'action' => 'edit_attendee',
2350
-                        'post'   => $attendee->ID(),
2351
-                    ),
2352
-                    REG_ADMIN_URL
2353
-                );
2354
-                $this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2355
-                $att_nmbr++;
2356
-            }
2357
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2358
-        }
2359
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2360
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2361
-    }
2362
-
2363
-
2364
-    /**
2365
-     *        generates HTML for the Edit Registration side meta box
2366
-     *
2367
-     * @access public
2368
-     * @return void
2369
-     * @throws DomainException
2370
-     * @throws EE_Error
2371
-     */
2372
-    public function _reg_registrant_side_meta_box()
2373
-    {
2374
-        /*@var $attendee EE_Attendee */
2375
-        $att_check = $this->_registration->attendee();
2376
-        $attendee  = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2377
-        //now let's determine if this is not the primary registration.  If it isn't then we set the
2378
-        //primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2379
-        //primary registration object (that way we know if we need to show create button or not)
2380
-        if ( ! $this->_registration->is_primary_registrant()) {
2381
-            $primary_registration = $this->_registration->get_primary_registration();
2382
-            $primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2383
-                : null;
2384
-            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2385
-                //in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2386
-                //custom attendee object so let's not worry about the primary reg.
2387
-                $primary_registration = null;
2388
-            }
2389
-        } else {
2390
-            $primary_registration = null;
2391
-        }
2392
-        $this->_template_args['ATT_ID']            = $attendee->ID();
2393
-        $this->_template_args['fname']             = $attendee->fname();
2394
-        $this->_template_args['lname']             = $attendee->lname();
2395
-        $this->_template_args['email']             = $attendee->email();
2396
-        $this->_template_args['phone']             = $attendee->phone();
2397
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2398
-        //edit link
2399
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2400
-            'action' => 'edit_attendee',
2401
-            'post'   => $attendee->ID(),
2402
-        ), REG_ADMIN_URL);
2403
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2404
-        //create link
2405
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2406
-            ? EE_Admin_Page::add_query_args_and_nonce(array(
2407
-                'action'  => 'duplicate_attendee',
2408
-                '_REG_ID' => $this->_registration->ID(),
2409
-            ), REG_ADMIN_URL) : '';
2410
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2411
-        $this->_template_args['att_check']    = $att_check;
2412
-        $template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2413
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2414
-    }
2415
-
2416
-
2417
-    /**
2418
-     * trash or restore registrations
2419
-     *
2420
-     * @param  boolean $trash whether to archive or restore
2421
-     * @return void
2422
-     * @throws EE_Error
2423
-     * @throws RuntimeException
2424
-     * @access protected
2425
-     */
2426
-    protected function _trash_or_restore_registrations($trash = true)
2427
-    {
2428
-        //if empty _REG_ID then get out because there's nothing to do
2429
-        if (empty($this->_req_data['_REG_ID'])) {
2430
-            EE_Error::add_error(
2431
-                sprintf(
2432
-                    esc_html__(
2433
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2434
-                        'event_espresso'
2435
-                    ),
2436
-                    $trash ? 'trash' : 'restore'
2437
-                ),
2438
-                __FILE__, __LINE__, __FUNCTION__
2439
-            );
2440
-            $this->_redirect_after_action(false, '', '', array(), true);
2441
-        }
2442
-        $success = 0;
2443
-        $overwrite_msgs = false;
2444
-        //Checkboxes
2445
-        if ( ! is_array($this->_req_data['_REG_ID'])) {
2446
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2447
-        }
2448
-        $reg_count = count($this->_req_data['_REG_ID']);
2449
-        // cycle thru checkboxes
2450
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2451
-            /** @var EE_Registration $REG */
2452
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2453
-            $payments = $REG->registration_payments();
2454
-            if (! empty($payments)) {
2455
-                $name = $REG->attendee() instanceof EE_Attendee
2456
-                    ? $REG->attendee()->full_name()
2457
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2458
-                $overwrite_msgs = true;
2459
-                EE_Error::add_error(
2460
-                    sprintf(
2461
-                        esc_html__(
2462
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2463
-                            'event_espresso'
2464
-                        ),
2465
-                        $name
2466
-                    ),
2467
-                    __FILE__, __FUNCTION__, __LINE__
2468
-                );
2469
-                //can't trash this registration because it has payments.
2470
-                continue;
2471
-            }
2472
-            $updated = $trash ? $REG->delete() : $REG->restore();
2473
-            if ($updated) {
2474
-                $success++;
2475
-            }
2476
-        }
2477
-        $this->_redirect_after_action(
2478
-            $success === $reg_count, // were ALL registrations affected?
2479
-            $success > 1
2480
-                ? esc_html__('Registrations', 'event_espresso')
2481
-                : esc_html__('Registration', 'event_espresso'),
2482
-            $trash
2483
-                ? esc_html__('moved to the trash', 'event_espresso')
2484
-                : esc_html__('restored', 'event_espresso'),
2485
-            array('action' => 'default'),
2486
-            $overwrite_msgs
2487
-        );
2488
-    }
2489
-
2490
-
2491
-    /**
2492
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2493
-     * registration but also.
2494
-     * 1. Removing relations to EE_Attendee
2495
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2496
-     * ALSO trashed.
2497
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2498
-     * 4. Removing relationships between all tickets and the related registrations
2499
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2500
-     * 6. Deleting permanently any related Checkins.
2501
-     *
2502
-     * @return void
2503
-     * @throws EE_Error
2504
-     */
2505
-    protected function _delete_registrations()
2506
-    {
2507
-        $REG_MDL = EEM_Registration::instance();
2508
-        $success = 1;
2509
-        //Checkboxes
2510
-        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2511
-            // if array has more than one element than success message should be plural
2512
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2513
-            // cycle thru checkboxes
2514
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2515
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2516
-                if ( ! $REG instanceof EE_Registration) {
2517
-                    continue;
2518
-                }
2519
-                $deleted = $this->_delete_registration($REG);
2520
-                if ( ! $deleted) {
2521
-                    $success = 0;
2522
-                }
2523
-            }
2524
-        } else {
2525
-            // grab single id and delete
2526
-            $REG_ID  = $this->_req_data['_REG_ID'];
2527
-            $REG     = $REG_MDL->get_one_by_ID($REG_ID);
2528
-            $deleted = $this->_delete_registration($REG);
2529
-            if ( ! $deleted) {
2530
-                $success = 0;
2531
-            }
2532
-        }
2533
-        $what        = $success > 1
2534
-            ? esc_html__('Registrations', 'event_espresso')
2535
-            : esc_html__('Registration', 'event_espresso');
2536
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2537
-        $this->_redirect_after_action(
2538
-            $success,
2539
-            $what,
2540
-            $action_desc,
2541
-            array('action' => 'default'),
2542
-            true
2543
-        );
2544
-    }
2545
-
2546
-
2547
-    /**
2548
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2549
-     * models get affected.
2550
-     *
2551
-     * @param  EE_Registration $REG registration to be deleted permenantly
2552
-     * @return bool true = successful deletion, false = fail.
2553
-     * @throws EE_Error
2554
-     */
2555
-    protected function _delete_registration(EE_Registration $REG)
2556
-    {
2557
-        //first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2558
-        //registrations on the transaction that are NOT trashed.
2559
-        $TXN         = $REG->get_first_related('Transaction');
2560
-        $REGS        = $TXN->get_many_related('Registration');
2561
-        $all_trashed = true;
2562
-        foreach ($REGS as $registration) {
2563
-            if ( ! $registration->get('REG_deleted')) {
2564
-                $all_trashed = false;
2565
-            }
2566
-        }
2567
-        if ( ! $all_trashed) {
2568
-            EE_Error::add_error(
2569
-                esc_html__(
2570
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2571
-                    'event_espresso'
2572
-                ),
2573
-                __FILE__, __FUNCTION__, __LINE__
2574
-            );
2575
-            return false;
2576
-        }
2577
-        //k made it here so that means we can delete all the related transactions and their answers (but let's do them
2578
-        //separately from THIS one).
2579
-        foreach ($REGS as $registration) {
2580
-            //delete related answers
2581
-            $registration->delete_related_permanently('Answer');
2582
-            //remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2583
-            $attendee = $registration->get_first_related('Attendee');
2584
-            if ($attendee instanceof EE_Attendee) {
2585
-                $registration->_remove_relation_to($attendee, 'Attendee');
2586
-            }
2587
-            //now remove relationships to tickets on this registration.
2588
-            $registration->_remove_relations('Ticket');
2589
-            //now delete permanently the checkins related to this registration.
2590
-            $registration->delete_related_permanently('Checkin');
2591
-            if ($registration->ID() === $REG->ID()) {
2592
-                continue;
2593
-            } //we don't want to delete permanently the existing registration just yet.
2594
-            //remove relation to transaction for these registrations if NOT the existing registrations
2595
-            $registration->_remove_relations('Transaction');
2596
-            //delete permanently any related messages.
2597
-            $registration->delete_related_permanently('Message');
2598
-            //now delete this registration permanently
2599
-            $registration->delete_permanently();
2600
-        }
2601
-        //now all related registrations on the transaction are handled.  So let's just handle this registration itself
2602
-        // (the transaction and line items should be all that's left).
2603
-        // delete the line items related to the transaction for this registration.
2604
-        $TXN->delete_related_permanently('Line_Item');
2605
-        //we need to remove all the relationships on the transaction
2606
-        $TXN->delete_related_permanently('Payment');
2607
-        $TXN->delete_related_permanently('Extra_Meta');
2608
-        $TXN->delete_related_permanently('Message');
2609
-        //now we can delete this REG permanently (and the transaction of course)
2610
-        $REG->delete_related_permanently('Transaction');
2611
-        return $REG->delete_permanently();
2612
-    }
2613
-
2614
-
2615
-    /**
2616
-     *    generates HTML for the Register New Attendee Admin page
2617
-     *
2618
-     * @access private
2619
-     * @throws DomainException
2620
-     * @throws EE_Error
2621
-     */
2622
-    public function new_registration()
2623
-    {
2624
-        if ( ! $this->_set_reg_event()) {
2625
-            throw new EE_Error(
2626
-                esc_html__(
2627
-                    'Unable to continue with registering because there is no Event ID in the request',
2628
-                    'event_espresso'
2629
-                )
2630
-            );
2631
-        }
2632
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2633
-        // gotta start with a clean slate if we're not coming here via ajax
2634
-        if ( ! defined('DOING_AJAX')
2635
-             && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2636
-        ) {
2637
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2638
-        }
2639
-        $this->_template_args['event_name'] = '';
2640
-        // event name
2641
-        if ($this->_reg_event) {
2642
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2643
-            $edit_event_url                     = self::add_query_args_and_nonce(array(
2644
-                'action' => 'edit',
2645
-                'post'   => $this->_reg_event->ID(),
2646
-            ), EVENTS_ADMIN_URL);
2647
-            $edit_event_lnk                     = '<a href="'
2648
-                                                  . $edit_event_url
2649
-                                                  . '" title="'
2650
-                                                  . esc_attr__('Edit ', 'event_espresso')
2651
-                                                  . $this->_reg_event->name()
2652
-                                                  . '">'
2653
-                                                  . esc_html__('Edit Event', 'event_espresso')
2654
-                                                  . '</a>';
2655
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2656
-                                                   . $edit_event_lnk
2657
-                                                   . '</span>';
2658
-        }
2659
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2660
-        if (defined('DOING_AJAX')) {
2661
-            $this->_return_json();
2662
-        }
2663
-        // grab header
2664
-        $template_path                              =
2665
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2666
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2667
-            $this->_template_args, true);
2668
-        //$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2669
-        // the details template wrapper
2670
-        $this->display_admin_page_with_sidebar();
2671
-    }
2672
-
2673
-
2674
-    /**
2675
-     * This returns the content for a registration step
2676
-     *
2677
-     * @access protected
2678
-     * @return string html
2679
-     * @throws DomainException
2680
-     * @throws EE_Error
2681
-     */
2682
-    protected function _get_registration_step_content()
2683
-    {
2684
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2685
-            $warning_msg = sprintf(
2686
-                esc_html__(
2687
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2688
-                    'event_espresso'
2689
-                ),
2690
-                '<br />',
2691
-                '<h3 class="important-notice">',
2692
-                '</h3>',
2693
-                '<div class="float-right">',
2694
-                '<span id="redirect_timer" class="important-notice">30</span>',
2695
-                '</div>',
2696
-                '<b>',
2697
-                '</b>'
2698
-            );
2699
-            return '
2200
+	}
2201
+
2202
+
2203
+	/**
2204
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2205
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2206
+	 * to display the page
2207
+	 *
2208
+	 * @access protected
2209
+	 * @return void
2210
+	 * @throws EE_Error
2211
+	 */
2212
+	protected function _update_attendee_registration_form()
2213
+	{
2214
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2215
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2216
+			$REG_ID  = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2217
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2218
+			if ($success) {
2219
+				$what  = esc_html__('Registration Form', 'event_espresso');
2220
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2221
+					: array('action' => 'default');
2222
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2223
+			}
2224
+		}
2225
+	}
2226
+
2227
+
2228
+	/**
2229
+	 * Gets the form for saving registrations custom questions (if done
2230
+	 * previously retrieves the cached form object, which may have validation errors in it)
2231
+	 *
2232
+	 * @param int $REG_ID
2233
+	 * @return EE_Registration_Custom_Questions_Form
2234
+	 * @throws EE_Error
2235
+	 */
2236
+	protected function _get_reg_custom_questions_form($REG_ID)
2237
+	{
2238
+		if ( ! $this->_reg_custom_questions_form) {
2239
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2240
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2241
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2242
+			);
2243
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2244
+		}
2245
+		return $this->_reg_custom_questions_form;
2246
+	}
2247
+
2248
+
2249
+	/**
2250
+	 * Saves
2251
+	 *
2252
+	 * @access private
2253
+	 * @param bool $REG_ID
2254
+	 * @return bool
2255
+	 * @throws EE_Error
2256
+	 */
2257
+	private function _save_reg_custom_questions_form($REG_ID = false)
2258
+	{
2259
+		if ( ! $REG_ID) {
2260
+			EE_Error::add_error(
2261
+				esc_html__(
2262
+					'An error occurred. No registration ID was received.', 'event_espresso'),
2263
+				__FILE__, __FUNCTION__, __LINE__
2264
+			);
2265
+		}
2266
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2267
+		$form->receive_form_submission($this->_req_data);
2268
+		$success = false;
2269
+		if ($form->is_valid()) {
2270
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2271
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2272
+					$where_conditions    = array(
2273
+						'QST_ID' => $question_id,
2274
+						'REG_ID' => $REG_ID,
2275
+					);
2276
+					$possibly_new_values = array(
2277
+						'ANS_value' => $input->normalized_value(),
2278
+					);
2279
+					$answer              = EEM_Answer::instance()->get_one(array($where_conditions));
2280
+					if ($answer instanceof EE_Answer) {
2281
+						$success = $answer->save($possibly_new_values);
2282
+					} else {
2283
+						//insert it then
2284
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2285
+						$answer      = EE_Answer::new_instance($cols_n_vals);
2286
+						$success     = $answer->save();
2287
+					}
2288
+				}
2289
+			}
2290
+		} else {
2291
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2292
+		}
2293
+		return $success;
2294
+	}
2295
+
2296
+
2297
+	/**
2298
+	 *        generates HTML for the Registration main meta box
2299
+	 *
2300
+	 * @access public
2301
+	 * @return void
2302
+	 * @throws DomainException
2303
+	 * @throws EE_Error
2304
+	 */
2305
+	public function _reg_attendees_meta_box()
2306
+	{
2307
+		$REG = EEM_Registration::instance();
2308
+		//get all other registrations on this transaction, and cache
2309
+		//the attendees for them so we don't have to run another query using force_join
2310
+		$registrations                           = $REG->get_all(array(
2311
+			array(
2312
+				'TXN_ID' => $this->_registration->transaction_ID(),
2313
+				'REG_ID' => array('!=', $this->_registration->ID()),
2314
+			),
2315
+			'force_join' => array('Attendee'),
2316
+		));
2317
+		$this->_template_args['attendees']       = array();
2318
+		$this->_template_args['attendee_notice'] = '';
2319
+		if (empty($registrations)
2320
+			|| (is_array($registrations)
2321
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2322
+		) {
2323
+			EE_Error::add_error(
2324
+				esc_html__(
2325
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2326
+					'event_espresso'
2327
+				), __FILE__, __FUNCTION__, __LINE__
2328
+			);
2329
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2330
+		} else {
2331
+			$att_nmbr = 1;
2332
+			foreach ($registrations as $registration) {
2333
+				/* @var $registration EE_Registration */
2334
+				$attendee                                                    = $registration->attendee()
2335
+					? $registration->attendee()
2336
+					: EEM_Attendee::instance()
2337
+								  ->create_default_object();
2338
+				$this->_template_args['attendees'][$att_nmbr]['STS_ID']      = $registration->status_ID();
2339
+				$this->_template_args['attendees'][$att_nmbr]['fname']       = $attendee->fname();
2340
+				$this->_template_args['attendees'][$att_nmbr]['lname']       = $attendee->lname();
2341
+				$this->_template_args['attendees'][$att_nmbr]['email']       = $attendee->email();
2342
+				$this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2343
+				$this->_template_args['attendees'][$att_nmbr]['address']     = implode(
2344
+					', ',
2345
+					$attendee->full_address_as_array()
2346
+				);
2347
+				$this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2348
+					array(
2349
+						'action' => 'edit_attendee',
2350
+						'post'   => $attendee->ID(),
2351
+					),
2352
+					REG_ADMIN_URL
2353
+				);
2354
+				$this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2355
+				$att_nmbr++;
2356
+			}
2357
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2358
+		}
2359
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2360
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2361
+	}
2362
+
2363
+
2364
+	/**
2365
+	 *        generates HTML for the Edit Registration side meta box
2366
+	 *
2367
+	 * @access public
2368
+	 * @return void
2369
+	 * @throws DomainException
2370
+	 * @throws EE_Error
2371
+	 */
2372
+	public function _reg_registrant_side_meta_box()
2373
+	{
2374
+		/*@var $attendee EE_Attendee */
2375
+		$att_check = $this->_registration->attendee();
2376
+		$attendee  = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2377
+		//now let's determine if this is not the primary registration.  If it isn't then we set the
2378
+		//primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2379
+		//primary registration object (that way we know if we need to show create button or not)
2380
+		if ( ! $this->_registration->is_primary_registrant()) {
2381
+			$primary_registration = $this->_registration->get_primary_registration();
2382
+			$primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2383
+				: null;
2384
+			if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2385
+				//in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2386
+				//custom attendee object so let's not worry about the primary reg.
2387
+				$primary_registration = null;
2388
+			}
2389
+		} else {
2390
+			$primary_registration = null;
2391
+		}
2392
+		$this->_template_args['ATT_ID']            = $attendee->ID();
2393
+		$this->_template_args['fname']             = $attendee->fname();
2394
+		$this->_template_args['lname']             = $attendee->lname();
2395
+		$this->_template_args['email']             = $attendee->email();
2396
+		$this->_template_args['phone']             = $attendee->phone();
2397
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2398
+		//edit link
2399
+		$this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2400
+			'action' => 'edit_attendee',
2401
+			'post'   => $attendee->ID(),
2402
+		), REG_ADMIN_URL);
2403
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2404
+		//create link
2405
+		$this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2406
+			? EE_Admin_Page::add_query_args_and_nonce(array(
2407
+				'action'  => 'duplicate_attendee',
2408
+				'_REG_ID' => $this->_registration->ID(),
2409
+			), REG_ADMIN_URL) : '';
2410
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2411
+		$this->_template_args['att_check']    = $att_check;
2412
+		$template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2413
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2414
+	}
2415
+
2416
+
2417
+	/**
2418
+	 * trash or restore registrations
2419
+	 *
2420
+	 * @param  boolean $trash whether to archive or restore
2421
+	 * @return void
2422
+	 * @throws EE_Error
2423
+	 * @throws RuntimeException
2424
+	 * @access protected
2425
+	 */
2426
+	protected function _trash_or_restore_registrations($trash = true)
2427
+	{
2428
+		//if empty _REG_ID then get out because there's nothing to do
2429
+		if (empty($this->_req_data['_REG_ID'])) {
2430
+			EE_Error::add_error(
2431
+				sprintf(
2432
+					esc_html__(
2433
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2434
+						'event_espresso'
2435
+					),
2436
+					$trash ? 'trash' : 'restore'
2437
+				),
2438
+				__FILE__, __LINE__, __FUNCTION__
2439
+			);
2440
+			$this->_redirect_after_action(false, '', '', array(), true);
2441
+		}
2442
+		$success = 0;
2443
+		$overwrite_msgs = false;
2444
+		//Checkboxes
2445
+		if ( ! is_array($this->_req_data['_REG_ID'])) {
2446
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2447
+		}
2448
+		$reg_count = count($this->_req_data['_REG_ID']);
2449
+		// cycle thru checkboxes
2450
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2451
+			/** @var EE_Registration $REG */
2452
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2453
+			$payments = $REG->registration_payments();
2454
+			if (! empty($payments)) {
2455
+				$name = $REG->attendee() instanceof EE_Attendee
2456
+					? $REG->attendee()->full_name()
2457
+					: esc_html__('Unknown Attendee', 'event_espresso');
2458
+				$overwrite_msgs = true;
2459
+				EE_Error::add_error(
2460
+					sprintf(
2461
+						esc_html__(
2462
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2463
+							'event_espresso'
2464
+						),
2465
+						$name
2466
+					),
2467
+					__FILE__, __FUNCTION__, __LINE__
2468
+				);
2469
+				//can't trash this registration because it has payments.
2470
+				continue;
2471
+			}
2472
+			$updated = $trash ? $REG->delete() : $REG->restore();
2473
+			if ($updated) {
2474
+				$success++;
2475
+			}
2476
+		}
2477
+		$this->_redirect_after_action(
2478
+			$success === $reg_count, // were ALL registrations affected?
2479
+			$success > 1
2480
+				? esc_html__('Registrations', 'event_espresso')
2481
+				: esc_html__('Registration', 'event_espresso'),
2482
+			$trash
2483
+				? esc_html__('moved to the trash', 'event_espresso')
2484
+				: esc_html__('restored', 'event_espresso'),
2485
+			array('action' => 'default'),
2486
+			$overwrite_msgs
2487
+		);
2488
+	}
2489
+
2490
+
2491
+	/**
2492
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2493
+	 * registration but also.
2494
+	 * 1. Removing relations to EE_Attendee
2495
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2496
+	 * ALSO trashed.
2497
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2498
+	 * 4. Removing relationships between all tickets and the related registrations
2499
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2500
+	 * 6. Deleting permanently any related Checkins.
2501
+	 *
2502
+	 * @return void
2503
+	 * @throws EE_Error
2504
+	 */
2505
+	protected function _delete_registrations()
2506
+	{
2507
+		$REG_MDL = EEM_Registration::instance();
2508
+		$success = 1;
2509
+		//Checkboxes
2510
+		if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2511
+			// if array has more than one element than success message should be plural
2512
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2513
+			// cycle thru checkboxes
2514
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2515
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2516
+				if ( ! $REG instanceof EE_Registration) {
2517
+					continue;
2518
+				}
2519
+				$deleted = $this->_delete_registration($REG);
2520
+				if ( ! $deleted) {
2521
+					$success = 0;
2522
+				}
2523
+			}
2524
+		} else {
2525
+			// grab single id and delete
2526
+			$REG_ID  = $this->_req_data['_REG_ID'];
2527
+			$REG     = $REG_MDL->get_one_by_ID($REG_ID);
2528
+			$deleted = $this->_delete_registration($REG);
2529
+			if ( ! $deleted) {
2530
+				$success = 0;
2531
+			}
2532
+		}
2533
+		$what        = $success > 1
2534
+			? esc_html__('Registrations', 'event_espresso')
2535
+			: esc_html__('Registration', 'event_espresso');
2536
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2537
+		$this->_redirect_after_action(
2538
+			$success,
2539
+			$what,
2540
+			$action_desc,
2541
+			array('action' => 'default'),
2542
+			true
2543
+		);
2544
+	}
2545
+
2546
+
2547
+	/**
2548
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2549
+	 * models get affected.
2550
+	 *
2551
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2552
+	 * @return bool true = successful deletion, false = fail.
2553
+	 * @throws EE_Error
2554
+	 */
2555
+	protected function _delete_registration(EE_Registration $REG)
2556
+	{
2557
+		//first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2558
+		//registrations on the transaction that are NOT trashed.
2559
+		$TXN         = $REG->get_first_related('Transaction');
2560
+		$REGS        = $TXN->get_many_related('Registration');
2561
+		$all_trashed = true;
2562
+		foreach ($REGS as $registration) {
2563
+			if ( ! $registration->get('REG_deleted')) {
2564
+				$all_trashed = false;
2565
+			}
2566
+		}
2567
+		if ( ! $all_trashed) {
2568
+			EE_Error::add_error(
2569
+				esc_html__(
2570
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2571
+					'event_espresso'
2572
+				),
2573
+				__FILE__, __FUNCTION__, __LINE__
2574
+			);
2575
+			return false;
2576
+		}
2577
+		//k made it here so that means we can delete all the related transactions and their answers (but let's do them
2578
+		//separately from THIS one).
2579
+		foreach ($REGS as $registration) {
2580
+			//delete related answers
2581
+			$registration->delete_related_permanently('Answer');
2582
+			//remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2583
+			$attendee = $registration->get_first_related('Attendee');
2584
+			if ($attendee instanceof EE_Attendee) {
2585
+				$registration->_remove_relation_to($attendee, 'Attendee');
2586
+			}
2587
+			//now remove relationships to tickets on this registration.
2588
+			$registration->_remove_relations('Ticket');
2589
+			//now delete permanently the checkins related to this registration.
2590
+			$registration->delete_related_permanently('Checkin');
2591
+			if ($registration->ID() === $REG->ID()) {
2592
+				continue;
2593
+			} //we don't want to delete permanently the existing registration just yet.
2594
+			//remove relation to transaction for these registrations if NOT the existing registrations
2595
+			$registration->_remove_relations('Transaction');
2596
+			//delete permanently any related messages.
2597
+			$registration->delete_related_permanently('Message');
2598
+			//now delete this registration permanently
2599
+			$registration->delete_permanently();
2600
+		}
2601
+		//now all related registrations on the transaction are handled.  So let's just handle this registration itself
2602
+		// (the transaction and line items should be all that's left).
2603
+		// delete the line items related to the transaction for this registration.
2604
+		$TXN->delete_related_permanently('Line_Item');
2605
+		//we need to remove all the relationships on the transaction
2606
+		$TXN->delete_related_permanently('Payment');
2607
+		$TXN->delete_related_permanently('Extra_Meta');
2608
+		$TXN->delete_related_permanently('Message');
2609
+		//now we can delete this REG permanently (and the transaction of course)
2610
+		$REG->delete_related_permanently('Transaction');
2611
+		return $REG->delete_permanently();
2612
+	}
2613
+
2614
+
2615
+	/**
2616
+	 *    generates HTML for the Register New Attendee Admin page
2617
+	 *
2618
+	 * @access private
2619
+	 * @throws DomainException
2620
+	 * @throws EE_Error
2621
+	 */
2622
+	public function new_registration()
2623
+	{
2624
+		if ( ! $this->_set_reg_event()) {
2625
+			throw new EE_Error(
2626
+				esc_html__(
2627
+					'Unable to continue with registering because there is no Event ID in the request',
2628
+					'event_espresso'
2629
+				)
2630
+			);
2631
+		}
2632
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2633
+		// gotta start with a clean slate if we're not coming here via ajax
2634
+		if ( ! defined('DOING_AJAX')
2635
+			 && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2636
+		) {
2637
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2638
+		}
2639
+		$this->_template_args['event_name'] = '';
2640
+		// event name
2641
+		if ($this->_reg_event) {
2642
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2643
+			$edit_event_url                     = self::add_query_args_and_nonce(array(
2644
+				'action' => 'edit',
2645
+				'post'   => $this->_reg_event->ID(),
2646
+			), EVENTS_ADMIN_URL);
2647
+			$edit_event_lnk                     = '<a href="'
2648
+												  . $edit_event_url
2649
+												  . '" title="'
2650
+												  . esc_attr__('Edit ', 'event_espresso')
2651
+												  . $this->_reg_event->name()
2652
+												  . '">'
2653
+												  . esc_html__('Edit Event', 'event_espresso')
2654
+												  . '</a>';
2655
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2656
+												   . $edit_event_lnk
2657
+												   . '</span>';
2658
+		}
2659
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2660
+		if (defined('DOING_AJAX')) {
2661
+			$this->_return_json();
2662
+		}
2663
+		// grab header
2664
+		$template_path                              =
2665
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2666
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2667
+			$this->_template_args, true);
2668
+		//$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2669
+		// the details template wrapper
2670
+		$this->display_admin_page_with_sidebar();
2671
+	}
2672
+
2673
+
2674
+	/**
2675
+	 * This returns the content for a registration step
2676
+	 *
2677
+	 * @access protected
2678
+	 * @return string html
2679
+	 * @throws DomainException
2680
+	 * @throws EE_Error
2681
+	 */
2682
+	protected function _get_registration_step_content()
2683
+	{
2684
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2685
+			$warning_msg = sprintf(
2686
+				esc_html__(
2687
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2688
+					'event_espresso'
2689
+				),
2690
+				'<br />',
2691
+				'<h3 class="important-notice">',
2692
+				'</h3>',
2693
+				'<div class="float-right">',
2694
+				'<span id="redirect_timer" class="important-notice">30</span>',
2695
+				'</div>',
2696
+				'<b>',
2697
+				'</b>'
2698
+			);
2699
+			return '
2700 2700
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2701 2701
 	<script >
2702 2702
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2709,792 +2709,792 @@  discard block
 block discarded – undo
2709 2709
 	        }
2710 2710
 	    }, 800 );
2711 2711
 	</script >';
2712
-        }
2713
-        $template_args = array(
2714
-            'title'                    => '',
2715
-            'content'                  => '',
2716
-            'step_button_text'         => '',
2717
-            'show_notification_toggle' => false,
2718
-        );
2719
-        //to indicate we're processing a new registration
2720
-        $hidden_fields = array(
2721
-            'processing_registration' => array(
2722
-                'type'  => 'hidden',
2723
-                'value' => 0,
2724
-            ),
2725
-            'event_id'                => array(
2726
-                'type'  => 'hidden',
2727
-                'value' => $this->_reg_event->ID(),
2728
-            ),
2729
-        );
2730
-        //if the cart is empty then we know we're at step one so we'll display ticket selector
2731
-        $cart = EE_Registry::instance()->SSN->cart();
2732
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2733
-        switch ($step) {
2734
-            case 'ticket' :
2735
-                $hidden_fields['processing_registration']['value'] = 1;
2736
-                $template_args['title']                            = esc_html__(
2737
-                    'Step One: Select the Ticket for this registration',
2738
-                    'event_espresso'
2739
-                );
2740
-                $template_args['content']                          =
2741
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2742
-                $template_args['step_button_text']                 = esc_html__(
2743
-                    'Add Tickets and Continue to Registrant Details',
2744
-                    'event_espresso'
2745
-                );
2746
-                $template_args['show_notification_toggle']         = false;
2747
-                break;
2748
-            case 'questions' :
2749
-                $hidden_fields['processing_registration']['value'] = 2;
2750
-                $template_args['title']                            = esc_html__(
2751
-                    'Step Two: Add Registrant Details for this Registration',
2752
-                    'event_espresso'
2753
-                );
2754
-                //in theory we should be able to run EED_SPCO at this point because the cart should have been setup
2755
-                // properly by the first process_reg_step run.
2756
-                $template_args['content']                  =
2757
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
2758
-                $template_args['step_button_text']         = esc_html__(
2759
-                    'Save Registration and Continue to Details',
2760
-                    'event_espresso'
2761
-                );
2762
-                $template_args['show_notification_toggle'] = true;
2763
-                break;
2764
-        }
2765
-        //we come back to the process_registration_step route.
2766
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2767
-        return EEH_Template::display_template(
2768
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2769
-            $template_args,
2770
-            true
2771
-        );
2772
-    }
2773
-
2774
-
2775
-    /**
2776
-     *        set_reg_event
2777
-     *
2778
-     * @access private
2779
-     * @return bool
2780
-     * @throws EE_Error
2781
-     */
2782
-    private function _set_reg_event()
2783
-    {
2784
-        if (is_object($this->_reg_event)) {
2785
-            return true;
2786
-        }
2787
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2788
-        if ( ! $EVT_ID) {
2789
-            return false;
2790
-        }
2791
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2792
-        return true;
2793
-    }
2794
-
2795
-
2796
-    /**
2797
-     * process_reg_step
2798
-     *
2799
-     * @access        public
2800
-     * @return string
2801
-     * @throws DomainException
2802
-     * @throws EE_Error
2803
-     * @throws RuntimeException
2804
-     */
2805
-    public function process_reg_step()
2806
-    {
2807
-        EE_System::do_not_cache();
2808
-        $this->_set_reg_event();
2809
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2810
-        EE_Registry::instance()->REQ->set('uts', time());
2811
-        //what step are we on?
2812
-        $cart = EE_Registry::instance()->SSN->cart();
2813
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2814
-        //if doing ajax then we need to verify the nonce
2815
-        if (defined('DOING_AJAX')) {
2816
-            $nonce = isset($this->_req_data[$this->_req_nonce])
2817
-                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
2818
-            $this->_verify_nonce($nonce, $this->_req_nonce);
2819
-        }
2820
-        switch ($step) {
2821
-            case 'ticket' :
2822
-                //process ticket selection
2823
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
2824
-                if ($success) {
2825
-                    EE_Error::add_success(
2826
-                        esc_html__(
2827
-                            'Tickets Selected. Now complete the registration.',
2828
-                            'event_espresso'
2829
-                        )
2830
-                    );
2831
-                } else {
2832
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
2833
-                }
2834
-                if (defined('DOING_AJAX')) {
2835
-                    $this->new_registration(); //display next step
2836
-                } else {
2837
-                    $query_args = array(
2838
-                        'action'                  => 'new_registration',
2839
-                        'processing_registration' => 1,
2840
-                        'event_id'                => $this->_reg_event->ID(),
2841
-                        'uts'                     => time(),
2842
-                    );
2843
-                    $this->_redirect_after_action(
2844
-                        false,
2845
-                        '',
2846
-                        '',
2847
-                        $query_args,
2848
-                        true
2849
-                    );
2850
-                }
2851
-                break;
2852
-            case 'questions' :
2853
-                if (! isset(
2854
-                    $this->_req_data['txn_reg_status_change'],
2855
-                    $this->_req_data['txn_reg_status_change']['send_notifications'])
2856
-                ) {
2857
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
2858
-                }
2859
-                //process registration
2860
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
2861
-                if ($cart instanceof EE_Cart) {
2862
-                    $grand_total = $cart->get_cart_grand_total();
2863
-                    if ($grand_total instanceof EE_Line_Item) {
2864
-                        $grand_total->save_this_and_descendants_to_txn();
2865
-                    }
2866
-                }
2867
-                if ( ! $transaction instanceof EE_Transaction) {
2868
-                    $query_args = array(
2869
-                        'action'                  => 'new_registration',
2870
-                        'processing_registration' => 2,
2871
-                        'event_id'                => $this->_reg_event->ID(),
2872
-                        'uts'                     => time(),
2873
-                    );
2874
-                    if (defined('DOING_AJAX')) {
2875
-                        //display registration form again because there are errors (maybe validation?)
2876
-                        $this->new_registration();
2877
-                        return;
2878
-                    } else {
2879
-                        $this->_redirect_after_action(
2880
-                            false,
2881
-                            '',
2882
-                            '',
2883
-                            $query_args,
2884
-                            true
2885
-                        );
2886
-                        return;
2887
-                    }
2888
-                }
2889
-                // maybe update status, and make sure to save transaction if not done already
2890
-                if ( ! $transaction->update_status_based_on_total_paid()) {
2891
-                    $transaction->save();
2892
-                }
2893
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2894
-                $this->_req_data = array();
2895
-                $query_args      = array(
2896
-                    'action'        => 'redirect_to_txn',
2897
-                    'TXN_ID'        => $transaction->ID(),
2898
-                    'EVT_ID'        => $this->_reg_event->ID(),
2899
-                    'event_name'    => urlencode($this->_reg_event->name()),
2900
-                    'redirect_from' => 'new_registration',
2901
-                );
2902
-                $this->_redirect_after_action(false, '', '', $query_args, true);
2903
-                break;
2904
-        }
2905
-        //what are you looking here for?  Should be nothing to do at this point.
2906
-    }
2907
-
2908
-
2909
-    /**
2910
-     * redirect_to_txn
2911
-     *
2912
-     * @access public
2913
-     * @return void
2914
-     * @throws EE_Error
2915
-     */
2916
-    public function redirect_to_txn()
2917
-    {
2918
-        EE_System::do_not_cache();
2919
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2920
-        $query_args = array(
2921
-            'action' => 'view_transaction',
2922
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
2923
-            'page'   => 'espresso_transactions',
2924
-        );
2925
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
2926
-            $query_args['EVT_ID']        = $this->_req_data['EVT_ID'];
2927
-            $query_args['event_name']    = urlencode($this->_req_data['event_name']);
2928
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
2929
-        }
2930
-        EE_Error::add_success(
2931
-            esc_html__(
2932
-                'Registration Created.  Please review the transaction and add any payments as necessary',
2933
-                'event_espresso'
2934
-            )
2935
-        );
2936
-        $this->_redirect_after_action(false, '', '', $query_args, true);
2937
-    }
2938
-
2939
-
2940
-    /**
2941
-     *        generates HTML for the Attendee Contact List
2942
-     *
2943
-     * @access protected
2944
-     * @return void
2945
-     */
2946
-    protected function _attendee_contact_list_table()
2947
-    {
2948
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2949
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
2950
-        $this->display_admin_list_table_page_with_no_sidebar();
2951
-    }
2952
-
2953
-
2954
-    /**
2955
-     *        get_attendees
2956
-     *
2957
-     * @param      $per_page
2958
-     * @param bool $count whether to return count or data.
2959
-     * @param bool $trash
2960
-     * @return array
2961
-     * @throws EE_Error
2962
-     * @access public
2963
-     */
2964
-    public function get_attendees($per_page, $count = false, $trash = false)
2965
-    {
2966
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2967
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
2968
-        $ATT_MDL                    = EEM_Attendee::instance();
2969
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2970
-        switch ($this->_req_data['orderby']) {
2971
-            case 'ATT_ID':
2972
-                $orderby = 'ATT_ID';
2973
-                break;
2974
-            case 'ATT_fname':
2975
-                $orderby = 'ATT_fname';
2976
-                break;
2977
-            case 'ATT_email':
2978
-                $orderby = 'ATT_email';
2979
-                break;
2980
-            case 'ATT_city':
2981
-                $orderby = 'ATT_city';
2982
-                break;
2983
-            case 'STA_ID':
2984
-                $orderby = 'STA_ID';
2985
-                break;
2986
-            case 'CNT_ID':
2987
-                $orderby = 'CNT_ID';
2988
-                break;
2989
-            default:
2990
-                $orderby = 'ATT_lname';
2991
-        }
2992
-        $sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
2993
-            ? $this->_req_data['order']
2994
-            : 'ASC';
2995
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
2996
-            ? $this->_req_data['paged']
2997
-            : 1;
2998
-        $per_page     = isset($per_page) && ! empty($per_page) ? $per_page : 10;
2999
-        $per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3000
-            ? $this->_req_data['perpage']
3001
-            : $per_page;
3002
-        $_where       = array();
3003
-        if ( ! empty($this->_req_data['s'])) {
3004
-            $sstr         = '%' . $this->_req_data['s'] . '%';
3005
-            $_where['OR'] = array(
3006
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3007
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3008
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3009
-                'ATT_fname'                         => array('LIKE', $sstr),
3010
-                'ATT_lname'                         => array('LIKE', $sstr),
3011
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3012
-                'ATT_email'                         => array('LIKE', $sstr),
3013
-                'ATT_address'                       => array('LIKE', $sstr),
3014
-                'ATT_address2'                      => array('LIKE', $sstr),
3015
-                'ATT_city'                          => array('LIKE', $sstr),
3016
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3017
-                'State.STA_name'                    => array('LIKE', $sstr),
3018
-                'ATT_phone'                         => array('LIKE', $sstr),
3019
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3020
-                'Registration.REG_code'             => array('LIKE', $sstr),
3021
-                'Registration.REG_count'            => array('LIKE', $sstr),
3022
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3023
-            );
3024
-        }
3025
-        $offset = ($current_page - 1) * $per_page;
3026
-        $limit  = $count ? null : array($offset, $per_page);
3027
-        if ($trash) {
3028
-            $_where['status'] = array('!=', 'publish');
3029
-            $all_attendees    = $count
3030
-                ? $ATT_MDL->count(array(
3031
-                    $_where,
3032
-                    'order_by' => array($orderby => $sort),
3033
-                    'limit'    => $limit,
3034
-                ), 'ATT_ID', true)
3035
-                : $ATT_MDL->get_all(array(
3036
-                    $_where,
3037
-                    'order_by' => array($orderby => $sort),
3038
-                    'limit'    => $limit,
3039
-                ));
3040
-        } else {
3041
-            $_where['status'] = array('IN', array('publish'));
3042
-            $all_attendees    = $count
3043
-                ? $ATT_MDL->count(array(
3044
-                    $_where,
3045
-                    'order_by' => array($orderby => $sort),
3046
-                    'limit'    => $limit,
3047
-                ), 'ATT_ID', true)
3048
-                : $ATT_MDL->get_all(array(
3049
-                    $_where,
3050
-                    'order_by' => array($orderby => $sort),
3051
-                    'limit'    => $limit,
3052
-                ));
3053
-        }
3054
-        return $all_attendees;
3055
-    }
3056
-
3057
-
3058
-    /**
3059
-     * This is just taking care of resending the registration confirmation
3060
-     *
3061
-     * @access protected
3062
-     * @return void
3063
-     */
3064
-    protected function _resend_registration()
3065
-    {
3066
-        $this->_process_resend_registration();
3067
-        $query_args = isset($this->_req_data['redirect_to'])
3068
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3069
-            : array('action' => 'default');
3070
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3071
-    }
3072
-
3073
-    /**
3074
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3075
-     * to use when selecting registrations
3076
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3077
-     *                                                     the query parameters from the request
3078
-     * @return void ends the request with a redirect or download
3079
-     */
3080
-    public function _registrations_report_base( $method_name_for_getting_query_params )
3081
-    {
3082
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3083
-            wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3084
-                array(
3085
-                    'page'        => 'espresso_batch',
3086
-                    'batch'       => 'file',
3087
-                    'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3088
-                    'filters'     => urlencode(
3089
-                        serialize(
3090
-                            call_user_func(
3091
-                                array( $this, $method_name_for_getting_query_params ),
3092
-                                EEH_Array::is_set(
3093
-                                    $this->_req_data,
3094
-                                    'filters',
3095
-                                    array()
3096
-                                )
3097
-                            )
3098
-                        )
3099
-                ),
3100
-                'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3101
-                'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3102
-                'return_url'  => urlencode($this->_req_data['return_url']),
3103
-            )));
3104
-        } else {
3105
-            $new_request_args = array(
3106
-                'export' => 'report',
3107
-                'action' => 'registrations_report_for_event',
3108
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3109
-            );
3110
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3111
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3112
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3113
-                $EE_Export = EE_Export::instance($this->_req_data);
3114
-                $EE_Export->export();
3115
-            }
3116
-        }
3117
-    }
3118
-
3119
-
3120
-
3121
-    /**
3122
-     * Creates a registration report using only query parameters in the request
3123
-     * @return void
3124
-     */
3125
-    public function _registrations_report()
3126
-    {
3127
-        $this->_registrations_report_base('_get_registration_query_parameters');
3128
-    }
3129
-
3130
-
3131
-    public function _contact_list_export()
3132
-    {
3133
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3134
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3135
-            $EE_Export = EE_Export::instance($this->_req_data);
3136
-            $EE_Export->export_attendees();
3137
-        }
3138
-    }
3139
-
3140
-
3141
-    public function _contact_list_report()
3142
-    {
3143
-        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3144
-            wp_redirect(EE_Admin_Page::add_query_args_and_nonce(array(
3145
-                'page'        => 'espresso_batch',
3146
-                'batch'       => 'file',
3147
-                'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3148
-                'return_url'  => urlencode($this->_req_data['return_url']),
3149
-            )));
3150
-        } else {
3151
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3152
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3153
-                $EE_Export = EE_Export::instance($this->_req_data);
3154
-                $EE_Export->report_attendees();
3155
-            }
3156
-        }
3157
-    }
3158
-
3159
-
3160
-
3161
-
3162
-
3163
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3164
-    /**
3165
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3166
-     *
3167
-     * @return void
3168
-     * @throws EE_Error
3169
-     */
3170
-    protected function _duplicate_attendee()
3171
-    {
3172
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3173
-        //verify we have necessary info
3174
-        if (empty($this->_req_data['_REG_ID'])) {
3175
-            EE_Error::add_error(
3176
-                esc_html__(
3177
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3178
-                    'event_espresso'
3179
-                ), __FILE__, __LINE__, __FUNCTION__
3180
-            );
3181
-            $query_args = array('action' => $action);
3182
-            $this->_redirect_after_action('', '', '', $query_args, true);
3183
-        }
3184
-        //okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3185
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3186
-        $attendee     = $registration->attendee();
3187
-        //remove relation of existing attendee on registration
3188
-        $registration->_remove_relation_to($attendee, 'Attendee');
3189
-        //new attendee
3190
-        $new_attendee = clone $attendee;
3191
-        $new_attendee->set('ATT_ID', 0);
3192
-        $new_attendee->save();
3193
-        //add new attendee to reg
3194
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3195
-        EE_Error::add_success(
3196
-            esc_html__(
3197
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3198
-                'event_espresso'
3199
-            )
3200
-        );
3201
-        //redirect to edit page for attendee
3202
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3203
-        $this->_redirect_after_action('', '', '', $query_args, true);
3204
-    }
3205
-
3206
-
3207
-    //related to cpt routes
3208
-    protected function _insert_update_cpt_item($post_id, $post)
3209
-    {
3210
-        $success  = true;
3211
-        $attendee = EEM_Attendee::instance()->get_one_by_ID($post_id);
3212
-        //for attendee updates
3213
-        if ($post->post_type = 'espresso_attendees' && ! empty($attendee)) {
3214
-            //note we should only be UPDATING attendees at this point.
3215
-            $updated_fields = array(
3216
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3217
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3218
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3219
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3220
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3221
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3222
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3223
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3224
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3225
-                'ATT_email'     => isset($this->_req_data['ATT_email']) ? $this->_req_data['ATT_email'] : '',
3226
-                'ATT_phone'     => isset($this->_req_data['ATT_phone']) ? $this->_req_data['ATT_phone'] : '',
3227
-            );
3228
-            foreach ($updated_fields as $field => $value) {
3229
-                $attendee->set($field, $value);
3230
-            }
3231
-            $success                   = $attendee->save();
3232
-            $attendee_update_callbacks = apply_filters(
3233
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3234
-                array()
3235
-            );
3236
-            foreach ($attendee_update_callbacks as $a_callback) {
3237
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3238
-                    throw new EE_Error(
3239
-                        sprintf(
3240
-                            esc_html__(
3241
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3242
-                                'event_espresso'
3243
-                            ),
3244
-                            $a_callback
3245
-                        )
3246
-                    );
3247
-                }
3248
-            }
3249
-        }
3250
-        if ($success === false) {
3251
-            EE_Error::add_error(
3252
-                esc_html__(
3253
-                    'Something went wrong with updating the meta table data for the registration.',
3254
-                    'event_espresso'
3255
-                ),
3256
-                __FILE__, __FUNCTION__, __LINE__
3257
-            );
3258
-        }
3259
-    }
3260
-
3261
-
3262
-    public function trash_cpt_item($post_id)
3263
-    {
3264
-    }
3265
-
3266
-
3267
-    public function delete_cpt_item($post_id)
3268
-    {
3269
-    }
3270
-
3271
-
3272
-    public function restore_cpt_item($post_id)
3273
-    {
3274
-    }
3275
-
3276
-
3277
-    protected function _restore_cpt_item($post_id, $revision_id)
3278
-    {
3279
-    }
3280
-
3281
-
3282
-    public function attendee_editor_metaboxes()
3283
-    {
3284
-        $this->verify_cpt_object();
3285
-        remove_meta_box(
3286
-            'postexcerpt',
3287
-            esc_html__('Excerpt', 'event_espresso'),
3288
-            'post_excerpt_meta_box',
3289
-            $this->_cpt_routes[$this->_req_action],
3290
-            'normal',
3291
-            'core'
3292
-        );
3293
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3294
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3295
-            add_meta_box(
3296
-                'postexcerpt',
3297
-                esc_html__('Short Biography', 'event_espresso'),
3298
-                'post_excerpt_meta_box',
3299
-                $this->_cpt_routes[$this->_req_action],
3300
-                'normal'
3301
-            );
3302
-        }
3303
-        if (post_type_supports('espresso_attendees', 'comments')) {
3304
-            add_meta_box(
3305
-                'commentsdiv',
3306
-                esc_html__('Notes on the Contact', 'event_espresso'),
3307
-                'post_comment_meta_box',
3308
-                $this->_cpt_routes[$this->_req_action],
3309
-                'normal',
3310
-                'core'
3311
-            );
3312
-        }
3313
-        add_meta_box(
3314
-            'attendee_contact_info',
3315
-            esc_html__('Contact Info', 'event_espresso'),
3316
-            array($this, 'attendee_contact_info'),
3317
-            $this->_cpt_routes[$this->_req_action],
3318
-            'side',
3319
-            'core'
3320
-        );
3321
-        add_meta_box(
3322
-            'attendee_details_address',
3323
-            esc_html__('Address Details', 'event_espresso'),
3324
-            array($this, 'attendee_address_details'),
3325
-            $this->_cpt_routes[$this->_req_action],
3326
-            'normal',
3327
-            'core'
3328
-        );
3329
-        add_meta_box(
3330
-            'attendee_registrations',
3331
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3332
-            array($this, 'attendee_registrations_meta_box'),
3333
-            $this->_cpt_routes[$this->_req_action],
3334
-            'normal',
3335
-            'high'
3336
-        );
3337
-    }
3338
-
3339
-
3340
-    /**
3341
-     * Metabox for attendee contact info
3342
-     *
3343
-     * @param  WP_Post $post wp post object
3344
-     * @return string attendee contact info ( and form )
3345
-     * @throws DomainException
3346
-     */
3347
-    public function attendee_contact_info($post)
3348
-    {
3349
-        //get attendee object ( should already have it )
3350
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3351
-        $template                         = REG_TEMPLATE_PATH . 'attendee_contact_info_metabox_content.template.php';
3352
-        EEH_Template::display_template($template, $this->_template_args);
3353
-    }
3354
-
3355
-
3356
-    /**
3357
-     * Metabox for attendee details
3358
-     *
3359
-     * @param  WP_Post $post wp post object
3360
-     * @return string attendee address details (and form)
3361
-     * @throws DomainException
3362
-     */
3363
-    public function attendee_address_details($post)
3364
-    {
3365
-        //get attendee object (should already have it)
3366
-        $this->_template_args['attendee']     = $this->_cpt_model_obj;
3367
-        $this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3368
-            new EE_Question_Form_Input(
3369
-                EE_Question::new_instance(
3370
-                    array(
3371
-                        'QST_ID'           => 0,
3372
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3373
-                        'QST_system'       => 'admin-state',
3374
-                    )
3375
-                ),
3376
-                EE_Answer::new_instance(
3377
-                    array(
3378
-                        'ANS_ID'    => 0,
3379
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3380
-                    )
3381
-                ),
3382
-                array(
3383
-                    'input_id'       => 'STA_ID',
3384
-                    'input_name'     => 'STA_ID',
3385
-                    'input_prefix'   => '',
3386
-                    'append_qstn_id' => false,
3387
-                )
3388
-            )
3389
-        );
3390
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3391
-            new EE_Question_Form_Input(
3392
-                EE_Question::new_instance(
3393
-                    array(
3394
-                        'QST_ID'           => 0,
3395
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3396
-                        'QST_system'       => 'admin-country',
3397
-                    )
3398
-                ),
3399
-                EE_Answer::new_instance(
3400
-                    array(
3401
-                        'ANS_ID'    => 0,
3402
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3403
-                    )
3404
-                ),
3405
-                array(
3406
-                    'input_id'       => 'CNT_ISO',
3407
-                    'input_name'     => 'CNT_ISO',
3408
-                    'input_prefix'   => '',
3409
-                    'append_qstn_id' => false,
3410
-                )
3411
-            )
3412
-        );
3413
-        $template                             =
3414
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3415
-        EEH_Template::display_template($template, $this->_template_args);
3416
-    }
3417
-
3418
-
3419
-    /**
3420
-     *        _attendee_details
3421
-     *
3422
-     * @access protected
3423
-     * @param $post
3424
-     * @return void
3425
-     * @throws DomainException
3426
-     * @throws EE_Error
3427
-     */
3428
-    public function attendee_registrations_meta_box($post)
3429
-    {
3430
-        $this->_template_args['attendee']      = $this->_cpt_model_obj;
3431
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3432
-        $template                              =
3433
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3434
-        EEH_Template::display_template($template, $this->_template_args);
3435
-    }
3436
-
3437
-
3438
-    /**
3439
-     * add in the form fields for the attendee edit
3440
-     *
3441
-     * @param  WP_Post $post wp post object
3442
-     * @return string html for new form.
3443
-     * @throws DomainException
3444
-     */
3445
-    public function after_title_form_fields($post)
3446
-    {
3447
-        if ($post->post_type == 'espresso_attendees') {
3448
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3449
-            $template_args['attendee'] = $this->_cpt_model_obj;
3450
-            EEH_Template::display_template($template, $template_args);
3451
-        }
3452
-    }
3453
-
3454
-
3455
-    /**
3456
-     *        _trash_or_restore_attendee
3457
-     *
3458
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3459
-     * @return void
3460
-     * @throws EE_Error
3461
-     * @access protected
3462
-     */
3463
-    protected function _trash_or_restore_attendees($trash = true)
3464
-    {
3465
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3466
-        $ATT_MDL = EEM_Attendee::instance();
3467
-        $success = 1;
3468
-        //Checkboxes
3469
-        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3470
-            // if array has more than one element than success message should be plural
3471
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3472
-            // cycle thru checkboxes
3473
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3474
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3475
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3476
-                if ( ! $updated) {
3477
-                    $success = 0;
3478
-                }
3479
-            }
3480
-        } else {
3481
-            // grab single id and delete
3482
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3483
-            //get attendee
3484
-            $att     = $ATT_MDL->get_one_by_ID($ATT_ID);
3485
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3486
-            $updated = $att->save();
3487
-            if ( ! $updated) {
3488
-                $success = 0;
3489
-            }
3490
-        }
3491
-        $what        = $success > 1
3492
-            ? esc_html__('Contacts', 'event_espresso')
3493
-            : esc_html__('Contact', 'event_espresso');
3494
-        $action_desc = $trash
3495
-            ? esc_html__('moved to the trash', 'event_espresso')
3496
-            : esc_html__('restored', 'event_espresso');
3497
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3498
-    }
2712
+		}
2713
+		$template_args = array(
2714
+			'title'                    => '',
2715
+			'content'                  => '',
2716
+			'step_button_text'         => '',
2717
+			'show_notification_toggle' => false,
2718
+		);
2719
+		//to indicate we're processing a new registration
2720
+		$hidden_fields = array(
2721
+			'processing_registration' => array(
2722
+				'type'  => 'hidden',
2723
+				'value' => 0,
2724
+			),
2725
+			'event_id'                => array(
2726
+				'type'  => 'hidden',
2727
+				'value' => $this->_reg_event->ID(),
2728
+			),
2729
+		);
2730
+		//if the cart is empty then we know we're at step one so we'll display ticket selector
2731
+		$cart = EE_Registry::instance()->SSN->cart();
2732
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2733
+		switch ($step) {
2734
+			case 'ticket' :
2735
+				$hidden_fields['processing_registration']['value'] = 1;
2736
+				$template_args['title']                            = esc_html__(
2737
+					'Step One: Select the Ticket for this registration',
2738
+					'event_espresso'
2739
+				);
2740
+				$template_args['content']                          =
2741
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2742
+				$template_args['step_button_text']                 = esc_html__(
2743
+					'Add Tickets and Continue to Registrant Details',
2744
+					'event_espresso'
2745
+				);
2746
+				$template_args['show_notification_toggle']         = false;
2747
+				break;
2748
+			case 'questions' :
2749
+				$hidden_fields['processing_registration']['value'] = 2;
2750
+				$template_args['title']                            = esc_html__(
2751
+					'Step Two: Add Registrant Details for this Registration',
2752
+					'event_espresso'
2753
+				);
2754
+				//in theory we should be able to run EED_SPCO at this point because the cart should have been setup
2755
+				// properly by the first process_reg_step run.
2756
+				$template_args['content']                  =
2757
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
2758
+				$template_args['step_button_text']         = esc_html__(
2759
+					'Save Registration and Continue to Details',
2760
+					'event_espresso'
2761
+				);
2762
+				$template_args['show_notification_toggle'] = true;
2763
+				break;
2764
+		}
2765
+		//we come back to the process_registration_step route.
2766
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2767
+		return EEH_Template::display_template(
2768
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2769
+			$template_args,
2770
+			true
2771
+		);
2772
+	}
2773
+
2774
+
2775
+	/**
2776
+	 *        set_reg_event
2777
+	 *
2778
+	 * @access private
2779
+	 * @return bool
2780
+	 * @throws EE_Error
2781
+	 */
2782
+	private function _set_reg_event()
2783
+	{
2784
+		if (is_object($this->_reg_event)) {
2785
+			return true;
2786
+		}
2787
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2788
+		if ( ! $EVT_ID) {
2789
+			return false;
2790
+		}
2791
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2792
+		return true;
2793
+	}
2794
+
2795
+
2796
+	/**
2797
+	 * process_reg_step
2798
+	 *
2799
+	 * @access        public
2800
+	 * @return string
2801
+	 * @throws DomainException
2802
+	 * @throws EE_Error
2803
+	 * @throws RuntimeException
2804
+	 */
2805
+	public function process_reg_step()
2806
+	{
2807
+		EE_System::do_not_cache();
2808
+		$this->_set_reg_event();
2809
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2810
+		EE_Registry::instance()->REQ->set('uts', time());
2811
+		//what step are we on?
2812
+		$cart = EE_Registry::instance()->SSN->cart();
2813
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2814
+		//if doing ajax then we need to verify the nonce
2815
+		if (defined('DOING_AJAX')) {
2816
+			$nonce = isset($this->_req_data[$this->_req_nonce])
2817
+				? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
2818
+			$this->_verify_nonce($nonce, $this->_req_nonce);
2819
+		}
2820
+		switch ($step) {
2821
+			case 'ticket' :
2822
+				//process ticket selection
2823
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
2824
+				if ($success) {
2825
+					EE_Error::add_success(
2826
+						esc_html__(
2827
+							'Tickets Selected. Now complete the registration.',
2828
+							'event_espresso'
2829
+						)
2830
+					);
2831
+				} else {
2832
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
2833
+				}
2834
+				if (defined('DOING_AJAX')) {
2835
+					$this->new_registration(); //display next step
2836
+				} else {
2837
+					$query_args = array(
2838
+						'action'                  => 'new_registration',
2839
+						'processing_registration' => 1,
2840
+						'event_id'                => $this->_reg_event->ID(),
2841
+						'uts'                     => time(),
2842
+					);
2843
+					$this->_redirect_after_action(
2844
+						false,
2845
+						'',
2846
+						'',
2847
+						$query_args,
2848
+						true
2849
+					);
2850
+				}
2851
+				break;
2852
+			case 'questions' :
2853
+				if (! isset(
2854
+					$this->_req_data['txn_reg_status_change'],
2855
+					$this->_req_data['txn_reg_status_change']['send_notifications'])
2856
+				) {
2857
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
2858
+				}
2859
+				//process registration
2860
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
2861
+				if ($cart instanceof EE_Cart) {
2862
+					$grand_total = $cart->get_cart_grand_total();
2863
+					if ($grand_total instanceof EE_Line_Item) {
2864
+						$grand_total->save_this_and_descendants_to_txn();
2865
+					}
2866
+				}
2867
+				if ( ! $transaction instanceof EE_Transaction) {
2868
+					$query_args = array(
2869
+						'action'                  => 'new_registration',
2870
+						'processing_registration' => 2,
2871
+						'event_id'                => $this->_reg_event->ID(),
2872
+						'uts'                     => time(),
2873
+					);
2874
+					if (defined('DOING_AJAX')) {
2875
+						//display registration form again because there are errors (maybe validation?)
2876
+						$this->new_registration();
2877
+						return;
2878
+					} else {
2879
+						$this->_redirect_after_action(
2880
+							false,
2881
+							'',
2882
+							'',
2883
+							$query_args,
2884
+							true
2885
+						);
2886
+						return;
2887
+					}
2888
+				}
2889
+				// maybe update status, and make sure to save transaction if not done already
2890
+				if ( ! $transaction->update_status_based_on_total_paid()) {
2891
+					$transaction->save();
2892
+				}
2893
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2894
+				$this->_req_data = array();
2895
+				$query_args      = array(
2896
+					'action'        => 'redirect_to_txn',
2897
+					'TXN_ID'        => $transaction->ID(),
2898
+					'EVT_ID'        => $this->_reg_event->ID(),
2899
+					'event_name'    => urlencode($this->_reg_event->name()),
2900
+					'redirect_from' => 'new_registration',
2901
+				);
2902
+				$this->_redirect_after_action(false, '', '', $query_args, true);
2903
+				break;
2904
+		}
2905
+		//what are you looking here for?  Should be nothing to do at this point.
2906
+	}
2907
+
2908
+
2909
+	/**
2910
+	 * redirect_to_txn
2911
+	 *
2912
+	 * @access public
2913
+	 * @return void
2914
+	 * @throws EE_Error
2915
+	 */
2916
+	public function redirect_to_txn()
2917
+	{
2918
+		EE_System::do_not_cache();
2919
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2920
+		$query_args = array(
2921
+			'action' => 'view_transaction',
2922
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
2923
+			'page'   => 'espresso_transactions',
2924
+		);
2925
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
2926
+			$query_args['EVT_ID']        = $this->_req_data['EVT_ID'];
2927
+			$query_args['event_name']    = urlencode($this->_req_data['event_name']);
2928
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
2929
+		}
2930
+		EE_Error::add_success(
2931
+			esc_html__(
2932
+				'Registration Created.  Please review the transaction and add any payments as necessary',
2933
+				'event_espresso'
2934
+			)
2935
+		);
2936
+		$this->_redirect_after_action(false, '', '', $query_args, true);
2937
+	}
2938
+
2939
+
2940
+	/**
2941
+	 *        generates HTML for the Attendee Contact List
2942
+	 *
2943
+	 * @access protected
2944
+	 * @return void
2945
+	 */
2946
+	protected function _attendee_contact_list_table()
2947
+	{
2948
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2949
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
2950
+		$this->display_admin_list_table_page_with_no_sidebar();
2951
+	}
2952
+
2953
+
2954
+	/**
2955
+	 *        get_attendees
2956
+	 *
2957
+	 * @param      $per_page
2958
+	 * @param bool $count whether to return count or data.
2959
+	 * @param bool $trash
2960
+	 * @return array
2961
+	 * @throws EE_Error
2962
+	 * @access public
2963
+	 */
2964
+	public function get_attendees($per_page, $count = false, $trash = false)
2965
+	{
2966
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2967
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
2968
+		$ATT_MDL                    = EEM_Attendee::instance();
2969
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2970
+		switch ($this->_req_data['orderby']) {
2971
+			case 'ATT_ID':
2972
+				$orderby = 'ATT_ID';
2973
+				break;
2974
+			case 'ATT_fname':
2975
+				$orderby = 'ATT_fname';
2976
+				break;
2977
+			case 'ATT_email':
2978
+				$orderby = 'ATT_email';
2979
+				break;
2980
+			case 'ATT_city':
2981
+				$orderby = 'ATT_city';
2982
+				break;
2983
+			case 'STA_ID':
2984
+				$orderby = 'STA_ID';
2985
+				break;
2986
+			case 'CNT_ID':
2987
+				$orderby = 'CNT_ID';
2988
+				break;
2989
+			default:
2990
+				$orderby = 'ATT_lname';
2991
+		}
2992
+		$sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
2993
+			? $this->_req_data['order']
2994
+			: 'ASC';
2995
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
2996
+			? $this->_req_data['paged']
2997
+			: 1;
2998
+		$per_page     = isset($per_page) && ! empty($per_page) ? $per_page : 10;
2999
+		$per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3000
+			? $this->_req_data['perpage']
3001
+			: $per_page;
3002
+		$_where       = array();
3003
+		if ( ! empty($this->_req_data['s'])) {
3004
+			$sstr         = '%' . $this->_req_data['s'] . '%';
3005
+			$_where['OR'] = array(
3006
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3007
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3008
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3009
+				'ATT_fname'                         => array('LIKE', $sstr),
3010
+				'ATT_lname'                         => array('LIKE', $sstr),
3011
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3012
+				'ATT_email'                         => array('LIKE', $sstr),
3013
+				'ATT_address'                       => array('LIKE', $sstr),
3014
+				'ATT_address2'                      => array('LIKE', $sstr),
3015
+				'ATT_city'                          => array('LIKE', $sstr),
3016
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3017
+				'State.STA_name'                    => array('LIKE', $sstr),
3018
+				'ATT_phone'                         => array('LIKE', $sstr),
3019
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3020
+				'Registration.REG_code'             => array('LIKE', $sstr),
3021
+				'Registration.REG_count'            => array('LIKE', $sstr),
3022
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3023
+			);
3024
+		}
3025
+		$offset = ($current_page - 1) * $per_page;
3026
+		$limit  = $count ? null : array($offset, $per_page);
3027
+		if ($trash) {
3028
+			$_where['status'] = array('!=', 'publish');
3029
+			$all_attendees    = $count
3030
+				? $ATT_MDL->count(array(
3031
+					$_where,
3032
+					'order_by' => array($orderby => $sort),
3033
+					'limit'    => $limit,
3034
+				), 'ATT_ID', true)
3035
+				: $ATT_MDL->get_all(array(
3036
+					$_where,
3037
+					'order_by' => array($orderby => $sort),
3038
+					'limit'    => $limit,
3039
+				));
3040
+		} else {
3041
+			$_where['status'] = array('IN', array('publish'));
3042
+			$all_attendees    = $count
3043
+				? $ATT_MDL->count(array(
3044
+					$_where,
3045
+					'order_by' => array($orderby => $sort),
3046
+					'limit'    => $limit,
3047
+				), 'ATT_ID', true)
3048
+				: $ATT_MDL->get_all(array(
3049
+					$_where,
3050
+					'order_by' => array($orderby => $sort),
3051
+					'limit'    => $limit,
3052
+				));
3053
+		}
3054
+		return $all_attendees;
3055
+	}
3056
+
3057
+
3058
+	/**
3059
+	 * This is just taking care of resending the registration confirmation
3060
+	 *
3061
+	 * @access protected
3062
+	 * @return void
3063
+	 */
3064
+	protected function _resend_registration()
3065
+	{
3066
+		$this->_process_resend_registration();
3067
+		$query_args = isset($this->_req_data['redirect_to'])
3068
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3069
+			: array('action' => 'default');
3070
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3071
+	}
3072
+
3073
+	/**
3074
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3075
+	 * to use when selecting registrations
3076
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3077
+	 *                                                     the query parameters from the request
3078
+	 * @return void ends the request with a redirect or download
3079
+	 */
3080
+	public function _registrations_report_base( $method_name_for_getting_query_params )
3081
+	{
3082
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3083
+			wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3084
+				array(
3085
+					'page'        => 'espresso_batch',
3086
+					'batch'       => 'file',
3087
+					'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3088
+					'filters'     => urlencode(
3089
+						serialize(
3090
+							call_user_func(
3091
+								array( $this, $method_name_for_getting_query_params ),
3092
+								EEH_Array::is_set(
3093
+									$this->_req_data,
3094
+									'filters',
3095
+									array()
3096
+								)
3097
+							)
3098
+						)
3099
+				),
3100
+				'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3101
+				'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3102
+				'return_url'  => urlencode($this->_req_data['return_url']),
3103
+			)));
3104
+		} else {
3105
+			$new_request_args = array(
3106
+				'export' => 'report',
3107
+				'action' => 'registrations_report_for_event',
3108
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3109
+			);
3110
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3111
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3112
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3113
+				$EE_Export = EE_Export::instance($this->_req_data);
3114
+				$EE_Export->export();
3115
+			}
3116
+		}
3117
+	}
3118
+
3119
+
3120
+
3121
+	/**
3122
+	 * Creates a registration report using only query parameters in the request
3123
+	 * @return void
3124
+	 */
3125
+	public function _registrations_report()
3126
+	{
3127
+		$this->_registrations_report_base('_get_registration_query_parameters');
3128
+	}
3129
+
3130
+
3131
+	public function _contact_list_export()
3132
+	{
3133
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3134
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3135
+			$EE_Export = EE_Export::instance($this->_req_data);
3136
+			$EE_Export->export_attendees();
3137
+		}
3138
+	}
3139
+
3140
+
3141
+	public function _contact_list_report()
3142
+	{
3143
+		if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3144
+			wp_redirect(EE_Admin_Page::add_query_args_and_nonce(array(
3145
+				'page'        => 'espresso_batch',
3146
+				'batch'       => 'file',
3147
+				'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3148
+				'return_url'  => urlencode($this->_req_data['return_url']),
3149
+			)));
3150
+		} else {
3151
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3152
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3153
+				$EE_Export = EE_Export::instance($this->_req_data);
3154
+				$EE_Export->report_attendees();
3155
+			}
3156
+		}
3157
+	}
3158
+
3159
+
3160
+
3161
+
3162
+
3163
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3164
+	/**
3165
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3166
+	 *
3167
+	 * @return void
3168
+	 * @throws EE_Error
3169
+	 */
3170
+	protected function _duplicate_attendee()
3171
+	{
3172
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3173
+		//verify we have necessary info
3174
+		if (empty($this->_req_data['_REG_ID'])) {
3175
+			EE_Error::add_error(
3176
+				esc_html__(
3177
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3178
+					'event_espresso'
3179
+				), __FILE__, __LINE__, __FUNCTION__
3180
+			);
3181
+			$query_args = array('action' => $action);
3182
+			$this->_redirect_after_action('', '', '', $query_args, true);
3183
+		}
3184
+		//okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3185
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3186
+		$attendee     = $registration->attendee();
3187
+		//remove relation of existing attendee on registration
3188
+		$registration->_remove_relation_to($attendee, 'Attendee');
3189
+		//new attendee
3190
+		$new_attendee = clone $attendee;
3191
+		$new_attendee->set('ATT_ID', 0);
3192
+		$new_attendee->save();
3193
+		//add new attendee to reg
3194
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3195
+		EE_Error::add_success(
3196
+			esc_html__(
3197
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3198
+				'event_espresso'
3199
+			)
3200
+		);
3201
+		//redirect to edit page for attendee
3202
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3203
+		$this->_redirect_after_action('', '', '', $query_args, true);
3204
+	}
3205
+
3206
+
3207
+	//related to cpt routes
3208
+	protected function _insert_update_cpt_item($post_id, $post)
3209
+	{
3210
+		$success  = true;
3211
+		$attendee = EEM_Attendee::instance()->get_one_by_ID($post_id);
3212
+		//for attendee updates
3213
+		if ($post->post_type = 'espresso_attendees' && ! empty($attendee)) {
3214
+			//note we should only be UPDATING attendees at this point.
3215
+			$updated_fields = array(
3216
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3217
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3218
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3219
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3220
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3221
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3222
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3223
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3224
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3225
+				'ATT_email'     => isset($this->_req_data['ATT_email']) ? $this->_req_data['ATT_email'] : '',
3226
+				'ATT_phone'     => isset($this->_req_data['ATT_phone']) ? $this->_req_data['ATT_phone'] : '',
3227
+			);
3228
+			foreach ($updated_fields as $field => $value) {
3229
+				$attendee->set($field, $value);
3230
+			}
3231
+			$success                   = $attendee->save();
3232
+			$attendee_update_callbacks = apply_filters(
3233
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3234
+				array()
3235
+			);
3236
+			foreach ($attendee_update_callbacks as $a_callback) {
3237
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3238
+					throw new EE_Error(
3239
+						sprintf(
3240
+							esc_html__(
3241
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3242
+								'event_espresso'
3243
+							),
3244
+							$a_callback
3245
+						)
3246
+					);
3247
+				}
3248
+			}
3249
+		}
3250
+		if ($success === false) {
3251
+			EE_Error::add_error(
3252
+				esc_html__(
3253
+					'Something went wrong with updating the meta table data for the registration.',
3254
+					'event_espresso'
3255
+				),
3256
+				__FILE__, __FUNCTION__, __LINE__
3257
+			);
3258
+		}
3259
+	}
3260
+
3261
+
3262
+	public function trash_cpt_item($post_id)
3263
+	{
3264
+	}
3265
+
3266
+
3267
+	public function delete_cpt_item($post_id)
3268
+	{
3269
+	}
3270
+
3271
+
3272
+	public function restore_cpt_item($post_id)
3273
+	{
3274
+	}
3275
+
3276
+
3277
+	protected function _restore_cpt_item($post_id, $revision_id)
3278
+	{
3279
+	}
3280
+
3281
+
3282
+	public function attendee_editor_metaboxes()
3283
+	{
3284
+		$this->verify_cpt_object();
3285
+		remove_meta_box(
3286
+			'postexcerpt',
3287
+			esc_html__('Excerpt', 'event_espresso'),
3288
+			'post_excerpt_meta_box',
3289
+			$this->_cpt_routes[$this->_req_action],
3290
+			'normal',
3291
+			'core'
3292
+		);
3293
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3294
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3295
+			add_meta_box(
3296
+				'postexcerpt',
3297
+				esc_html__('Short Biography', 'event_espresso'),
3298
+				'post_excerpt_meta_box',
3299
+				$this->_cpt_routes[$this->_req_action],
3300
+				'normal'
3301
+			);
3302
+		}
3303
+		if (post_type_supports('espresso_attendees', 'comments')) {
3304
+			add_meta_box(
3305
+				'commentsdiv',
3306
+				esc_html__('Notes on the Contact', 'event_espresso'),
3307
+				'post_comment_meta_box',
3308
+				$this->_cpt_routes[$this->_req_action],
3309
+				'normal',
3310
+				'core'
3311
+			);
3312
+		}
3313
+		add_meta_box(
3314
+			'attendee_contact_info',
3315
+			esc_html__('Contact Info', 'event_espresso'),
3316
+			array($this, 'attendee_contact_info'),
3317
+			$this->_cpt_routes[$this->_req_action],
3318
+			'side',
3319
+			'core'
3320
+		);
3321
+		add_meta_box(
3322
+			'attendee_details_address',
3323
+			esc_html__('Address Details', 'event_espresso'),
3324
+			array($this, 'attendee_address_details'),
3325
+			$this->_cpt_routes[$this->_req_action],
3326
+			'normal',
3327
+			'core'
3328
+		);
3329
+		add_meta_box(
3330
+			'attendee_registrations',
3331
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3332
+			array($this, 'attendee_registrations_meta_box'),
3333
+			$this->_cpt_routes[$this->_req_action],
3334
+			'normal',
3335
+			'high'
3336
+		);
3337
+	}
3338
+
3339
+
3340
+	/**
3341
+	 * Metabox for attendee contact info
3342
+	 *
3343
+	 * @param  WP_Post $post wp post object
3344
+	 * @return string attendee contact info ( and form )
3345
+	 * @throws DomainException
3346
+	 */
3347
+	public function attendee_contact_info($post)
3348
+	{
3349
+		//get attendee object ( should already have it )
3350
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3351
+		$template                         = REG_TEMPLATE_PATH . 'attendee_contact_info_metabox_content.template.php';
3352
+		EEH_Template::display_template($template, $this->_template_args);
3353
+	}
3354
+
3355
+
3356
+	/**
3357
+	 * Metabox for attendee details
3358
+	 *
3359
+	 * @param  WP_Post $post wp post object
3360
+	 * @return string attendee address details (and form)
3361
+	 * @throws DomainException
3362
+	 */
3363
+	public function attendee_address_details($post)
3364
+	{
3365
+		//get attendee object (should already have it)
3366
+		$this->_template_args['attendee']     = $this->_cpt_model_obj;
3367
+		$this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3368
+			new EE_Question_Form_Input(
3369
+				EE_Question::new_instance(
3370
+					array(
3371
+						'QST_ID'           => 0,
3372
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3373
+						'QST_system'       => 'admin-state',
3374
+					)
3375
+				),
3376
+				EE_Answer::new_instance(
3377
+					array(
3378
+						'ANS_ID'    => 0,
3379
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3380
+					)
3381
+				),
3382
+				array(
3383
+					'input_id'       => 'STA_ID',
3384
+					'input_name'     => 'STA_ID',
3385
+					'input_prefix'   => '',
3386
+					'append_qstn_id' => false,
3387
+				)
3388
+			)
3389
+		);
3390
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3391
+			new EE_Question_Form_Input(
3392
+				EE_Question::new_instance(
3393
+					array(
3394
+						'QST_ID'           => 0,
3395
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3396
+						'QST_system'       => 'admin-country',
3397
+					)
3398
+				),
3399
+				EE_Answer::new_instance(
3400
+					array(
3401
+						'ANS_ID'    => 0,
3402
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3403
+					)
3404
+				),
3405
+				array(
3406
+					'input_id'       => 'CNT_ISO',
3407
+					'input_name'     => 'CNT_ISO',
3408
+					'input_prefix'   => '',
3409
+					'append_qstn_id' => false,
3410
+				)
3411
+			)
3412
+		);
3413
+		$template                             =
3414
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3415
+		EEH_Template::display_template($template, $this->_template_args);
3416
+	}
3417
+
3418
+
3419
+	/**
3420
+	 *        _attendee_details
3421
+	 *
3422
+	 * @access protected
3423
+	 * @param $post
3424
+	 * @return void
3425
+	 * @throws DomainException
3426
+	 * @throws EE_Error
3427
+	 */
3428
+	public function attendee_registrations_meta_box($post)
3429
+	{
3430
+		$this->_template_args['attendee']      = $this->_cpt_model_obj;
3431
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3432
+		$template                              =
3433
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3434
+		EEH_Template::display_template($template, $this->_template_args);
3435
+	}
3436
+
3437
+
3438
+	/**
3439
+	 * add in the form fields for the attendee edit
3440
+	 *
3441
+	 * @param  WP_Post $post wp post object
3442
+	 * @return string html for new form.
3443
+	 * @throws DomainException
3444
+	 */
3445
+	public function after_title_form_fields($post)
3446
+	{
3447
+		if ($post->post_type == 'espresso_attendees') {
3448
+			$template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3449
+			$template_args['attendee'] = $this->_cpt_model_obj;
3450
+			EEH_Template::display_template($template, $template_args);
3451
+		}
3452
+	}
3453
+
3454
+
3455
+	/**
3456
+	 *        _trash_or_restore_attendee
3457
+	 *
3458
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3459
+	 * @return void
3460
+	 * @throws EE_Error
3461
+	 * @access protected
3462
+	 */
3463
+	protected function _trash_or_restore_attendees($trash = true)
3464
+	{
3465
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3466
+		$ATT_MDL = EEM_Attendee::instance();
3467
+		$success = 1;
3468
+		//Checkboxes
3469
+		if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3470
+			// if array has more than one element than success message should be plural
3471
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3472
+			// cycle thru checkboxes
3473
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3474
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3475
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3476
+				if ( ! $updated) {
3477
+					$success = 0;
3478
+				}
3479
+			}
3480
+		} else {
3481
+			// grab single id and delete
3482
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3483
+			//get attendee
3484
+			$att     = $ATT_MDL->get_one_by_ID($ATT_ID);
3485
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3486
+			$updated = $att->save();
3487
+			if ( ! $updated) {
3488
+				$success = 0;
3489
+			}
3490
+		}
3491
+		$what        = $success > 1
3492
+			? esc_html__('Contacts', 'event_espresso')
3493
+			: esc_html__('Contact', 'event_espresso');
3494
+		$action_desc = $trash
3495
+			? esc_html__('moved to the trash', 'event_espresso')
3496
+			: esc_html__('restored', 'event_espresso');
3497
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3498
+	}
3499 3499
 
3500 3500
 }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('ABSPATH')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /*
5 5
   Plugin Name:		Event Espresso
@@ -40,243 +40,243 @@  discard block
 block discarded – undo
40 40
  * @since            4.0
41 41
  */
42 42
 if (function_exists('espresso_version')) {
43
-    /**
44
-     *    espresso_duplicate_plugin_error
45
-     *    displays if more than one version of EE is activated at the same time
46
-     */
47
-    function espresso_duplicate_plugin_error()
48
-    {
49
-        ?>
43
+	/**
44
+	 *    espresso_duplicate_plugin_error
45
+	 *    displays if more than one version of EE is activated at the same time
46
+	 */
47
+	function espresso_duplicate_plugin_error()
48
+	{
49
+		?>
50 50
         <div class="error">
51 51
             <p>
52 52
                 <?php echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                ); ?>
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+				); ?>
56 56
             </p>
57 57
         </div>
58 58
         <?php
59
-        espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-    }
59
+		espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+	}
61 61
 
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
-    if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
+	if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                            esc_html__(
79
-                                    'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                                    'event_espresso'
81
-                            ),
82
-                            EE_MIN_PHP_VER_REQUIRED,
83
-                            PHP_VERSION,
84
-                            '<br/>',
85
-                            '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+							esc_html__(
79
+									'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+									'event_espresso'
81
+							),
82
+							EE_MIN_PHP_VER_REQUIRED,
83
+							PHP_VERSION,
84
+							'<br/>',
85
+							'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        /**
97
-         * espresso_version
98
-         * Returns the plugin version
99
-         *
100
-         * @return string
101
-         */
102
-        function espresso_version()
103
-        {
104
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.021');
105
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		/**
97
+		 * espresso_version
98
+		 * Returns the plugin version
99
+		 *
100
+		 * @return string
101
+		 */
102
+		function espresso_version()
103
+		{
104
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.021');
105
+		}
106 106
 
107
-        // define versions
108
-        define('EVENT_ESPRESSO_VERSION', espresso_version());
109
-        define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
-        define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
-        define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
-        //used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
-        if ( ! defined('DS')) {
115
-            define('DS', '/');
116
-        }
117
-        if ( ! defined('PS')) {
118
-            define('PS', PATH_SEPARATOR);
119
-        }
120
-        if ( ! defined('SP')) {
121
-            define('SP', ' ');
122
-        }
123
-        if ( ! defined('EENL')) {
124
-            define('EENL', "\n");
125
-        }
126
-        define('EE_SUPPORT_EMAIL', '[email protected]');
127
-        // define the plugin directory and URL
128
-        define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
-        define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
-        define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
-        // main root folder paths
132
-        define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
-        define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
-        define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
-        define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
-        define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
-        define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
-        define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
-        define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
-        // core system paths
141
-        define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
-        define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
-        define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
-        define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
-        define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
-        define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
-        define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
-        define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
-        define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
-        define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
-        define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
-        define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
-        // gateways
154
-        define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
-        define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
-        // asset URL paths
157
-        define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
-        define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
-        define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
-        define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
-        define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
-        define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
-        // define upload paths
164
-        $uploads = wp_upload_dir();
165
-        // define the uploads directory and URL
166
-        define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
-        define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
-        // define the templates directory and URL
169
-        define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
-        define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
-        // define the gateway directory and URL
172
-        define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
-        define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
-        // languages folder/path
175
-        define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
-        define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
-        //check for dompdf fonts in uploads
178
-        if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
-            define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
-        }
181
-        //ajax constants
182
-        define(
183
-                'EE_FRONT_AJAX',
184
-                isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
-        );
186
-        define(
187
-                'EE_ADMIN_AJAX',
188
-                isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
-        );
190
-        //just a handy constant occasionally needed for finding values representing infinity in the DB
191
-        //you're better to use this than its straight value (currently -1) in case you ever
192
-        //want to change its default value! or find when -1 means infinity
193
-        define('EE_INF_IN_DB', -1);
194
-        define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
-        define('EE_DEBUG', false);
196
-        // for older WP versions
197
-        if ( ! defined('MONTH_IN_SECONDS')) {
198
-            define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
-        }
200
-        /**
201
-         *    espresso_plugin_activation
202
-         *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
-         */
204
-        function espresso_plugin_activation()
205
-        {
206
-            update_option('ee_espresso_activation', true);
207
-        }
107
+		// define versions
108
+		define('EVENT_ESPRESSO_VERSION', espresso_version());
109
+		define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
+		define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
+		define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
+		//used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
+		if ( ! defined('DS')) {
115
+			define('DS', '/');
116
+		}
117
+		if ( ! defined('PS')) {
118
+			define('PS', PATH_SEPARATOR);
119
+		}
120
+		if ( ! defined('SP')) {
121
+			define('SP', ' ');
122
+		}
123
+		if ( ! defined('EENL')) {
124
+			define('EENL', "\n");
125
+		}
126
+		define('EE_SUPPORT_EMAIL', '[email protected]');
127
+		// define the plugin directory and URL
128
+		define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
+		define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
+		define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
+		// main root folder paths
132
+		define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
+		define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
+		define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
+		define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
+		define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
+		define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
+		define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
+		define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
+		// core system paths
141
+		define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
+		define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
+		define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
+		define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
+		define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
+		define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
+		define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
+		define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
+		define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
+		define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
+		define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
+		define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
+		// gateways
154
+		define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
+		define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
+		// asset URL paths
157
+		define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
+		define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
+		define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
+		define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
+		define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
+		define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
+		// define upload paths
164
+		$uploads = wp_upload_dir();
165
+		// define the uploads directory and URL
166
+		define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
+		define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
+		// define the templates directory and URL
169
+		define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
+		define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
+		// define the gateway directory and URL
172
+		define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
+		define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
+		// languages folder/path
175
+		define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
+		define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
+		//check for dompdf fonts in uploads
178
+		if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
+			define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
+		}
181
+		//ajax constants
182
+		define(
183
+				'EE_FRONT_AJAX',
184
+				isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
+		);
186
+		define(
187
+				'EE_ADMIN_AJAX',
188
+				isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
+		);
190
+		//just a handy constant occasionally needed for finding values representing infinity in the DB
191
+		//you're better to use this than its straight value (currently -1) in case you ever
192
+		//want to change its default value! or find when -1 means infinity
193
+		define('EE_INF_IN_DB', -1);
194
+		define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
+		define('EE_DEBUG', false);
196
+		// for older WP versions
197
+		if ( ! defined('MONTH_IN_SECONDS')) {
198
+			define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
+		}
200
+		/**
201
+		 *    espresso_plugin_activation
202
+		 *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
+		 */
204
+		function espresso_plugin_activation()
205
+		{
206
+			update_option('ee_espresso_activation', true);
207
+		}
208 208
 
209
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
-        /**
211
-         *    espresso_load_error_handling
212
-         *    this function loads EE's class for handling exceptions and errors
213
-         */
214
-        function espresso_load_error_handling()
215
-        {
216
-            // load debugging tools
217
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
-                EEH_Debug_Tools::instance();
220
-            }
221
-            // load error handling
222
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
-                require_once(EE_CORE . 'EE_Error.core.php');
224
-            } else {
225
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
-            }
227
-        }
209
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
+		/**
211
+		 *    espresso_load_error_handling
212
+		 *    this function loads EE's class for handling exceptions and errors
213
+		 */
214
+		function espresso_load_error_handling()
215
+		{
216
+			// load debugging tools
217
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
+				EEH_Debug_Tools::instance();
220
+			}
221
+			// load error handling
222
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
+				require_once(EE_CORE . 'EE_Error.core.php');
224
+			} else {
225
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
+			}
227
+		}
228 228
 
229
-        /**
230
-         *    espresso_load_required
231
-         *    given a class name and path, this function will load that file or throw an exception
232
-         *
233
-         * @param    string $classname
234
-         * @param    string $full_path_to_file
235
-         * @throws    EE_Error
236
-         */
237
-        function espresso_load_required($classname, $full_path_to_file)
238
-        {
239
-            static $error_handling_loaded = false;
240
-            if ( ! $error_handling_loaded) {
241
-                espresso_load_error_handling();
242
-                $error_handling_loaded = true;
243
-            }
244
-            if (is_readable($full_path_to_file)) {
245
-                require_once($full_path_to_file);
246
-            } else {
247
-                throw new EE_Error (
248
-                        sprintf(
249
-                                esc_html__(
250
-                                        'The %s class file could not be located or is not readable due to file permissions.',
251
-                                        'event_espresso'
252
-                                ),
253
-                                $classname
254
-                        )
255
-                );
256
-            }
257
-        }
229
+		/**
230
+		 *    espresso_load_required
231
+		 *    given a class name and path, this function will load that file or throw an exception
232
+		 *
233
+		 * @param    string $classname
234
+		 * @param    string $full_path_to_file
235
+		 * @throws    EE_Error
236
+		 */
237
+		function espresso_load_required($classname, $full_path_to_file)
238
+		{
239
+			static $error_handling_loaded = false;
240
+			if ( ! $error_handling_loaded) {
241
+				espresso_load_error_handling();
242
+				$error_handling_loaded = true;
243
+			}
244
+			if (is_readable($full_path_to_file)) {
245
+				require_once($full_path_to_file);
246
+			} else {
247
+				throw new EE_Error (
248
+						sprintf(
249
+								esc_html__(
250
+										'The %s class file could not be located or is not readable due to file permissions.',
251
+										'event_espresso'
252
+								),
253
+								$classname
254
+						)
255
+				);
256
+			}
257
+		}
258 258
 
259
-        espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
-        espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
-        espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
-        new EE_Bootstrap();
263
-    }
259
+		espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
+		espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
+		espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
+		new EE_Bootstrap();
263
+	}
264 264
 }
265 265
 if ( ! function_exists('espresso_deactivate_plugin')) {
266
-    /**
267
-     *    deactivate_plugin
268
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
-     *
270
-     * @access public
271
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
-     * @return    void
273
-     */
274
-    function espresso_deactivate_plugin($plugin_basename = '')
275
-    {
276
-        if ( ! function_exists('deactivate_plugins')) {
277
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
-        }
279
-        unset($_GET['activate'], $_REQUEST['activate']);
280
-        deactivate_plugins($plugin_basename);
281
-    }
266
+	/**
267
+	 *    deactivate_plugin
268
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
+	 *
270
+	 * @access public
271
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
+	 * @return    void
273
+	 */
274
+	function espresso_deactivate_plugin($plugin_basename = '')
275
+	{
276
+		if ( ! function_exists('deactivate_plugins')) {
277
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
+		}
279
+		unset($_GET['activate'], $_REQUEST['activate']);
280
+		deactivate_plugins($plugin_basename);
281
+	}
282 282
 }
283 283
\ No newline at end of file
Please login to merge, or discard this patch.
core/services/loaders/CachingLoader.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -99,23 +99,23 @@
 block discarded – undo
99 99
         $fqcn = ltrim($fqcn, '\\');
100 100
         // caching can be turned off via the following code:
101 101
         // add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
102
-        if(
102
+        if (
103 103
             apply_filters(
104 104
                 'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
105 105
                 false,
106 106
                 $this
107 107
             )
108
-        ){
108
+        ) {
109 109
             // even though $shared might be true, caching should be bypassed for whatever reason,
110 110
             // so we don't want the core loader to cache anything, therefore caching is turned off
111 111
             return $this->loader->load($fqcn, $arguments, false);
112 112
         }
113
-        $identifier = md5($fqcn . serialize($arguments));
114
-        if($this->cache->has($identifier)){
113
+        $identifier = md5($fqcn.serialize($arguments));
114
+        if ($this->cache->has($identifier)) {
115 115
             return $this->cache->get($identifier);
116 116
         }
117 117
         $object = $this->loader->load($fqcn, $arguments, $shared);
118
-        if($object instanceof $fqcn){
118
+        if ($object instanceof $fqcn) {
119 119
             $this->cache->add($object, $identifier);
120 120
         }
121 121
         return $object;
Please login to merge, or discard this patch.
Indentation   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -20,117 +20,117 @@
 block discarded – undo
20 20
 class CachingLoader extends LoaderDecorator
21 21
 {
22 22
 
23
-    /**
24
-     * @var CollectionInterface $cache
25
-     */
26
-    protected $cache;
27
-
28
-    /**
29
-     * @var string $identifier
30
-     */
31
-    protected $identifier;
32
-
33
-
34
-
35
-    /**
36
-     * CachingLoader constructor.
37
-     *
38
-     * @param LoaderDecoratorInterface $loader
39
-     * @param CollectionInterface      $cache
40
-     * @param string                   $identifier
41
-     * @throws InvalidDataTypeException
42
-     */
43
-    public function __construct(LoaderDecoratorInterface $loader, CollectionInterface $cache, $identifier = '')
44
-    {
45
-        parent::__construct($loader);
46
-        $this->cache = $cache;
47
-        $this->setIdentifier($identifier);
48
-        if ($this->identifier !== '') {
49
-            // to only clear this cache, and assuming an identifier has been set, simply do the following:
50
-            // do_action('AHEE__EventEspresso\core\services\loaders\CachingLoader__resetCache__IDENTIFIER');
51
-            // where "IDENTIFIER" = the string that was set during construction
52
-            add_action(
53
-                "AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$identifier}",
54
-                array($this, 'reset')
55
-            );
56
-        }
57
-        // to clear ALL caches, simply do the following:
58
-        // do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
59
-        add_action(
60
-            'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
61
-            array($this, 'reset')
62
-        );
63
-    }
64
-
65
-
66
-
67
-    /**
68
-     * @return string
69
-     */
70
-    public function identifier()
71
-    {
72
-        return $this->identifier;
73
-    }
74
-
75
-
76
-
77
-    /**
78
-     * @param string $identifier
79
-     * @throws InvalidDataTypeException
80
-     */
81
-    private function setIdentifier($identifier)
82
-    {
83
-        if ( ! is_string($identifier)) {
84
-            throw new InvalidDataTypeException('$identifier', $identifier, 'string');
85
-        }
86
-        $this->identifier = $identifier;
87
-    }
88
-
89
-
90
-
91
-    /**
92
-     * @param string $fqcn
93
-     * @param array  $arguments
94
-     * @param bool   $shared
95
-     * @return mixed
96
-     */
97
-    public function load($fqcn, $arguments = array(), $shared = true)
98
-    {
99
-        $fqcn = ltrim($fqcn, '\\');
100
-        // caching can be turned off via the following code:
101
-        // add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
102
-        if(
103
-            apply_filters(
104
-                'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
105
-                false,
106
-                $this
107
-            )
108
-        ){
109
-            // even though $shared might be true, caching should be bypassed for whatever reason,
110
-            // so we don't want the core loader to cache anything, therefore caching is turned off
111
-            return $this->loader->load($fqcn, $arguments, false);
112
-        }
113
-        $identifier = md5($fqcn . serialize($arguments));
114
-        if($this->cache->has($identifier)){
115
-            return $this->cache->get($identifier);
116
-        }
117
-        $object = $this->loader->load($fqcn, $arguments, $shared);
118
-        if($object instanceof $fqcn){
119
-            $this->cache->add($object, $identifier);
120
-        }
121
-        return $object;
122
-    }
123
-
124
-
125
-
126
-    /**
127
-     * empties cache and calls reset() on loader if method exists
128
-     */
129
-    public function reset()
130
-    {
131
-        $this->cache->trashAndDetachAll();
132
-        $this->loader->reset();
133
-    }
23
+	/**
24
+	 * @var CollectionInterface $cache
25
+	 */
26
+	protected $cache;
27
+
28
+	/**
29
+	 * @var string $identifier
30
+	 */
31
+	protected $identifier;
32
+
33
+
34
+
35
+	/**
36
+	 * CachingLoader constructor.
37
+	 *
38
+	 * @param LoaderDecoratorInterface $loader
39
+	 * @param CollectionInterface      $cache
40
+	 * @param string                   $identifier
41
+	 * @throws InvalidDataTypeException
42
+	 */
43
+	public function __construct(LoaderDecoratorInterface $loader, CollectionInterface $cache, $identifier = '')
44
+	{
45
+		parent::__construct($loader);
46
+		$this->cache = $cache;
47
+		$this->setIdentifier($identifier);
48
+		if ($this->identifier !== '') {
49
+			// to only clear this cache, and assuming an identifier has been set, simply do the following:
50
+			// do_action('AHEE__EventEspresso\core\services\loaders\CachingLoader__resetCache__IDENTIFIER');
51
+			// where "IDENTIFIER" = the string that was set during construction
52
+			add_action(
53
+				"AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$identifier}",
54
+				array($this, 'reset')
55
+			);
56
+		}
57
+		// to clear ALL caches, simply do the following:
58
+		// do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
59
+		add_action(
60
+			'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
61
+			array($this, 'reset')
62
+		);
63
+	}
64
+
65
+
66
+
67
+	/**
68
+	 * @return string
69
+	 */
70
+	public function identifier()
71
+	{
72
+		return $this->identifier;
73
+	}
74
+
75
+
76
+
77
+	/**
78
+	 * @param string $identifier
79
+	 * @throws InvalidDataTypeException
80
+	 */
81
+	private function setIdentifier($identifier)
82
+	{
83
+		if ( ! is_string($identifier)) {
84
+			throw new InvalidDataTypeException('$identifier', $identifier, 'string');
85
+		}
86
+		$this->identifier = $identifier;
87
+	}
88
+
89
+
90
+
91
+	/**
92
+	 * @param string $fqcn
93
+	 * @param array  $arguments
94
+	 * @param bool   $shared
95
+	 * @return mixed
96
+	 */
97
+	public function load($fqcn, $arguments = array(), $shared = true)
98
+	{
99
+		$fqcn = ltrim($fqcn, '\\');
100
+		// caching can be turned off via the following code:
101
+		// add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
102
+		if(
103
+			apply_filters(
104
+				'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
105
+				false,
106
+				$this
107
+			)
108
+		){
109
+			// even though $shared might be true, caching should be bypassed for whatever reason,
110
+			// so we don't want the core loader to cache anything, therefore caching is turned off
111
+			return $this->loader->load($fqcn, $arguments, false);
112
+		}
113
+		$identifier = md5($fqcn . serialize($arguments));
114
+		if($this->cache->has($identifier)){
115
+			return $this->cache->get($identifier);
116
+		}
117
+		$object = $this->loader->load($fqcn, $arguments, $shared);
118
+		if($object instanceof $fqcn){
119
+			$this->cache->add($object, $identifier);
120
+		}
121
+		return $object;
122
+	}
123
+
124
+
125
+
126
+	/**
127
+	 * empties cache and calls reset() on loader if method exists
128
+	 */
129
+	public function reset()
130
+	{
131
+		$this->cache->trashAndDetachAll();
132
+		$this->loader->reset();
133
+	}
134 134
 
135 135
 
136 136
 }
Please login to merge, or discard this patch.